Nexu is a scalable backend library built on top of Express.js, featuring encrypted requests, rate-limiting functionality
- File-Based Routing (Experimental): Automatically registers routes based on the file structure when enabled, allowing for better organization and scalability.
- Request and Response Encryption: Ensures secure communication by automatically encrypting incoming requests and server responses using a shared secret key.
- Customizable Configuration: Use
nexu.config.js
to define app configurations like port, CORS settings, body parsers, and security headers. - Middleware Support: Easily register multiple middleware functions with the
nexu.useMiddleware
method. - Security Headers: Automatically applies security headers (like CSP and XSS filters) using Helmet for enhanced protection.
- Rate Limiting: Configure rate-limiting to control the number of requests per IP in a given time window, preventing abuse.
To create a new Nexu project, all you need to do is run:
npx nexujs-cli init
On initialization, you'll see the following prompts:
◇ What is your project name?
│ nexu-app
◇ Would you like to use Typescript?
│ ● Yes (Recommended)
│ ○ No
◇ Which database would you like to use?
│ ● MongoDB
│ ○ PostgreSQL
│ ○ Neon
│ ○ Others
◆ Would you like to initialize a git repo
│ ● Yes (Default)
│ ○ No
After the prompts, nexujs-cli
will create a new Nexu project and install the required dependencies.
The nexu.config.js
file allows you to customize various aspects of your application, including port settings, middleware, body parsers, and security headers.
Example nexu.config.js
:
import { defineConfig } from "nexujs";
export default defineConfig({
port: 8080,
keys: {
public: process.env.NEXU_PUBLIC_KEY,
private: process.env.NEXU_PRIVATE_KEY,
},
corsConfig: {
origin: "yourorigin.com",
},
parserConfig: {
json: {
limit: "50mb",
},
url: {
limit: "50mb",
extended: true,
},
},
});
- Port Configuration: Set the server's port directly in the
nexu.config.js
file using the port property. - CORS Configuration: Define custom CORS settings using
corsConfig
. - Body Parser Configuration: Adjust the parser settings like request body size limits with
parserConfig
.
Encryption Details
- Request Encryption: Incoming requests are encrypted using a shared secret key defined in the key configuration.
- Response Encryption: Outgoing server responses are also encrypted with the same shared key, ensuring end-to-end secure communication.
Important: The same
NEXU_PUBLIC_KEY
andNEXU_PRIVATE_KEY
used in your backend.env
file must also be used in your client's side file to enable seamless encryption and decryption of requests and responses.
For information on setting up the client-side encryption key, refer to the nexujs-client README.
The Configuration API allows you to define key settings for your Nexu application. Each property in the configuration file serves a specific purpose and can be customized based on your requirements.
{
port: number;
keys: {
public: string;
private: string;
};
corsConfig?: CorsOptions;
parserConfig?: {
json?: OptionsJson;
url?: OptionsUrlencoded;
};
helmetOptions?: HelmetOptions;
httpsKeyPaths?: {
key: string;
cert: string;
},
experimental?: {
fileBasedRouting?: boolean;
};
rateLimit?: Options;
};
Nexu uses Helmet to automatically apply security headers such as Content Security Policy (CSP) and XSS filters. You can customize the Helmet configuration in your nexu.config.js
file.
Example nexu.config.js
with Helmet configuration:
import { defineConfig } from "nexujs";
export default defineConfig({
helmetOptions: {
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"] /* Restrict all content to the same origin */,
scriptSrc: [
"'self'",
"'unsafe-inline'",
"https://trusted-cdn.com",
] /* Allow inline scripts and trusted external sources */,
styleSrc: [
"'self'",
"'unsafe-inline'",
"https://trusted-cdn.com",
] /* Allow inline styles and trusted external stylesheets */,
fontSrc: [
"'self'",
"https://fonts.gstatic.com",
] /* Allow self and Google Fonts */,
imgSrc: [
"'self'",
"data:",
"https://trusted-image-cdn.com",
] /* Allow images from trusted sources and data URIs */,
connectSrc: [
"'self'",
"https://api.example.com",
] /* Allow connections to trusted APIs */,
objectSrc: ["'none'"] /* Prevent loading of Flash or other plugins */,
frameAncestors: [
"'none'",
] /* Prevent the site from being embedded in a frame (clickjacking protection) */,
formAction: [
"'self'",
] /* Only allow form submissions to the same origin */,
upgradeInsecureRequests:
[] /* Automatically upgrade HTTP requests to HTTPS */,
},
},
crossOriginEmbedderPolicy: true,
crossOriginOpenerPolicy: true,
xssFilter: true,
},
});
- Content Security Policy (CSP): Define your CSP settings to restrict the sources from which your app can load content (scripts, styles, etc.).
- XSS Filter: Protect your app from cross-site scripting attacks with the xssFilter option.
- Cross-Origin Policies: Set
crossOriginEmbedderPolicy
andcrossOriginOpenerPolicy
for additional security.
Nexu uses express-rate-limit
to add rate-limiting feature, you can now configure the number of requests allowed per time window. Add the following to your nexu.config.js
:
Default Config
windowMs: 15 * 60 * 1000,
limit: 20,
message: "Too many requests from this IP, please try again later.",
standardHeaders: true,
legacyHeaders: false,
windowMs
: Time window in milliseconds (e.g., 15 minutes).limit
: Maximum number of requests allowed during the windowMs period.message
: The message to display when the rate limit is exceeded.standardHeaders
: Whether to include standard rate-limit headers in the response.legacyHeaders
: Whether to include legacy rate-limit headers.
File-Based Routing is now an experimental feature in Nexu. You can enable it by setting the experimental.fileBasedRouting
option in your nexu.config.js
file.
This feature automatically registers routes based on your file structure. To add a new route, simply create a JavaScript or TypeScript file inside the routes directory, and Nexu will automatically register it.
import { defineConfig } from "nexujs";
export default defineConfig({
experimental: {
fileBasedRouting: true,
},
});
For example:
- Create a file at
routes/auth.js
. - Add your route handler in the file.
- TypeScript
import { nexuRouter } from "nexujs";
import { loginController } from "./controllers/auth.js";
const router = nexuRouter;
router.post("/login", loginController);
export = router;
- JavaScript
import { nexuRouter } from "nexujs";
import { loginController } from "./controllers/auth.js";
const router = nexuRouter;
router.post("/login", loginController);
export default router;
When this feature is enabled, Nexu will automatically map this route to localhost:5000/auth
.
Note: When working with modules inside the
routes
folder in TypeScript, ensure that you useexport =
instead ofexport default
for proper module loading. This is necessary due to how CommonJS and ESM modules are handled, particularly whenfileBasedRouting
is enabled.
The useMiddleware
method allows you to apply multiple middleware functions to your application in a single call. It accepts an array of functions, ensuring that each function is a valid middleware before applying it.
import { app, nexu, NexuMiddleware } from "nexujs";
const loggingMiddleware: NexuMiddleware = (req, res, next) => {
console.log(`Request made to: ${req.url}`);
next();
};
const authMiddleware: NexuMiddleware = (req, res, next) => {
if (req.headers["authorization"]) {
next();
} else {
res.status(401).send("Unauthorized");
}
};
nexu.useMiddleware([loggingMiddleware, authMiddleware]);
app.get("/", (req, res) => {
res.send("Hello, world!");
console.log("Hello world");
});
- nexujs-client: A complementary package for frontend applications. It automatically decrypts server responses and integrates seamlessly with Nexu Server