Zeno is a zero-dependency, lightweight web framework for TypeScript, designed for maximum simplicity and flexibility. It provides intuitive file-based routing and makes building APIs and web applications straightforward while ensuring high performance.
Note
This project is intended for educational purposes only. It is not production-ready and should not be used in production environments. Use at your own risk, and ensure thorough testing before considering it for production use.
-
No External Dependencies: Built entirely with TypeScript and Node.js standard libraries.
-
File-Based Routing: Routes are automatically generated from your folder structure in the
routes/
directory, simplifying route management and code maintenance. -
Dynamic Routes: Easily create dynamic routes using template parameters directly in file and folder names, e.g.,
api/[model].ts
. -
HTTP Method Handlers: Define specific handlers for different HTTP methods (GET, POST, PUT, DELETE, PATCH) in the same file.
-
Performance Optimized: Designed to be ultra-fast with efficient route handling and a minimal memory footprint.
-
Hot Reloading: Automatically refresh the application when code changes, providing a smooth development experience without manual server restarts.
-
Middleware Support: Add route-specific middleware using
+middleware.ts
files that can run before and after requests. -
Server-Sent Events (SSE): Built-in support for real-time updates using SSE.
-
Multi-Platform: Runs on Node.js, Vercel, or Netlify with the same codebase.
Zeno requires Node.js and npm or yarn to function. Make sure you have these tools installed before getting started.
Here's an example folder structure for a Zeno project:
/project-root
/routes
+middleware.ts # Global middleware
hello.ts # Simple route
/api
+middleware.ts # API-specific middleware
methods.ts # Route with different HTTP methods
[model].ts # Dynamic route
/models
[model].ts # Nested dynamic route
routes/api/[model].ts:
import { Response, Request } from "zeno";
export default async function handler(req: Request, res: Response) {
const { model } = (req as any).params; // 'model' corresponds to the [model] in the filename
res.json({ message: `Model: ${model}` })
}
routes/api/methods.ts:
import { Response, Request } from "zeno";
export async function GET(req: Request, res: Response) {
res.json({ message: "Get all users" });
}
export async function POST(req: Request, res: Response) {
res.json({ message: "Create new user" });
}
routes/hello.ts:
import type { Request, Response } from "zeno";
export const GET = async (req: Request, res: Response) => {
res.send("Hello World!");
};
To start a server with Zeno, use the createServer
function:
import { createServer, getRoutesDir } from "zeno";
const routesDir = getRoutesDir();
createServer(routesDir);
npm run dev
Starts a local server in development mode with automatic file reloading.
npm run build
Compiles your code to JavaScript and prepares your project for production.
npm run start
Starts the server in production mode without automatic reloading.
Middleware functions let you execute code before and after handling a request. Create a +middleware.ts
file:
import type { Request, Response } from "zeno";
export const beforeRequest = async (req: Request, res: Response) => {
console.log(`Request: ${req.method} ${req.url}`);
res.setHeader('X-Custom-Header', 'true');
return true; // Continue processing
};
export const afterRequest = async (req: Request, res: Response) => {
console.log(`Response sent with status: ${res.statusCode}`);
};
Zeno includes built-in support for SSE:
import type { Request, Response } from "zeno";
export async function GET(req: Request, res: Response) {
res.initSSE();
res.sseSend({ status: "connected" });
res.sseEvent("userUpdate", { id: 1, name: "John" });
// Close the connection after sending events
res.sseClose();
}
Zeno is under the MIT License. See the LICENSE file for details.
-
Dynamic Routes: Files in the
routes/
directory are treated as routes. If a file uses the[param]
syntax in its name (likeapi/[model].ts
), it's processed as a dynamic route wheremodel
becomes a request parameter. For example, a request to/api/user
will match the fileapi/[model].ts
, and you can retrieve the value ofmodel
asreq.params.model
. -
Static Routes: Files like
api/methods.ts
are processed as static routes and are directly accessible at the URL/api/methods
.
- Simplicity: Easy to set up and use with an intuitive file structure.
- Flexibility: Allows you to create APIs and web applications in a modular way.
- Performance: Designed to operate with low latency and optimized route handling.
- Zero Dependencies: Built entirely on Node.js standard libraries with no external packages required.
✨ Fun fact: The project name comes from the philosopher Zeno and the Dragon Ball character Zeno. Useless information, do with it what you will!