npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

actix

v0.0.2

Published

A fast and easy-to-use web server framework for Node.js

Readme

Actix

NPM Version License NPM Downloads Node Version Types

A lightweight, zero-dependency, type-safe web server framework for Node.js.
Build performant HTTP services with a modern, Express-like routing interface, dynamic path routing, and modular nested routers.


Table of Contents


Key Features

  • 🚀 Zero External Dependencies — Built directly on Node.js's native http module.
  • 🛡️ Fully Type-Safe — First-class TypeScript support with out-of-the-box declarations.
  • 🔗 Dynamic Routing — Native support for segment-based routing using modern {param} syntax (e.g. /api/users/{id}).
  • 📦 Built-in Body & Query Parsing — Automatically parses JSON, URL-encoded request bodies, and query parameter objects.
  • 🧱 Modular Nested Routers — Group related handlers into isolated sub-routers and mount them dynamically onto prefixes.
  • 🍪 Cookie & Header Management — Simple, declarative helpers for headers and cookie management.

Installation

Ensure you have Node.js (v18+) installed. actix is distributed as an ES Module.

npm install actix

[!IMPORTANT] Since Actix uses modern ES modules (import/export), you must set "type": "module" in your project's package.json.


Quick Start

Creating a server is simple and highly intuitive:

import Actix from "actix";

const app = new Actix();

// Simple GET endpoint
app.get("/", (req, res) => {
  res.json({ message: "Welcome to Actix!" });
});

// Start the server
app.listen(3000, () => {
  console.log("🚀 Server running on http://localhost:3000");
});

Request Lifecycle

The incoming request is parsed asynchronously before passing control to the middleware and handler stack.

1. Body Parsing

req.body is populated automatically. Actix supports application/json and application/x-www-form-urlencoded payloads:

app.post("/api/posts", (req, res) => {
  const { title, content } = req.body;
  res.status(201).json({ success: true, data: { title, content } });
});

2. Query Parsing

Url-encoded search queries are automatically parsed into req.query:

// Request: GET /api/search?q=typescript&limit=10
app.get("/api/search", (req, res) => {
  const { q, limit } = req.query; // { q: "typescript", limit: "10" }
  res.json({ results: [], query: q, limit: parseInt(limit || "10", 10) });
});

3. Dynamic Path Parameters

Path variables are declared using {parameterName} placeholders. Extracted variables are populated in req.params:

// Request: GET /api/users/1023/orders/9482
app.get("/api/users/{userId}/orders/{orderId}", (req, res) => {
  const { userId, orderId } = req.params; // { userId: "1023", orderId: "9482" }
  res.json({ userId, orderId });
});

Middlewares

Middlewares are async functions executing sequentially. Each middleware receives req, res, and next (a function to continue the chain).

1. Global Middlewares

Runs for every incoming request:

app.use(async (req, res, next) => {
  console.log(`${req.method} ${req.url}`)
  await next()
});

2. Prefix/Path Middlewares

Runs on any request where the path starts with the specified prefix:

app.use("/api", async (req, res, next) => {
  const apiKey = req.raw.headers["x-api-key"];
  if (!apiKey) {
    return res.status(401).json({ error: "Unauthorized" });
  }
  await next();
});

3. Route-Specific Middlewares

Pass inline middlewares directly inside route declarations:

const requireAdmin = async (req, res, next) => {
  if (req.body.role !== "admin") {
    return res.status(403).json({ error: "Forbidden" });
  }
  await next();
};

app.post("/admin/settings", requireAdmin, (req, res) => {
  res.send("Admin settings updated!");
});

Modular Routing (Sub-Routers)

Isolate routes in nested controllers using Router and mount them with optional path-specific middlewares.

// routes/users.js
import { Router } from "actix";

const userRouter = new Router();

// Routes are relative to where the router is mounted
userRouter.get("/{id}", (req, res) => {
  const { id } = req.params;
  res.json({ id, name: "Amit Kumar" });
});

userRouter.post("/create", (req, res) => {
  res.json({ created: true });
});

export default userRouter;

Mounting the router in the main application:

import Actix from "actix";
import userRouter from "./routes/users.js";

const app = new Actix();

// Protect user endpoints with custom auth middleware
const auth = async (req, res, next) => {
  // Authentication logic...
  await next();
};

// Mount the userRouter. All routes inside userRouter will automatically 
// run after 'auth' and be prefixed with /api/users
app.use("/api/users", auth, userRouter);

app.listen(3000);

API Reference

Actix Application

| Method / Property | Signature | Description | | :--- | :--- | :--- | | use | use([path,] ...handlers) | Mounts global, path-specific middlewares, or sub-routers. | | get | get(path, ...handlers) | Registers a GET handler. | | post | post(path, ...handlers) | Registers a POST handler. | | put | put(path, ...handlers) | Registers a PUT handler. | | delete | delete(path, ...handlers) | Registers a DELETE handler. | | patch | patch(path, ...handlers) | Registers a PATCH handler. | | listen | listen(port, [callback]) | Starts the server listening on the specified port. |

Request Object

| Property / Method | Type / Signature | Description | | :--- | :--- | :--- | | raw | IncomingMessage | Raw Node.js incoming request object. | | method | "GET" \| "POST" \| "PUT" \| "PATCH" \| "DELETE" | The HTTP request method. | | url | string | The complete request URL. | | path | string | The path part of the URL (excluding query string). | | query | Record<string, string> | Parsed query parameters. | | params | Record<string, string> | Parsed dynamic route parameters. | | body | any | Parsed request body object. | | getCookie | getCookie(name: string) | Retrieves the raw cookie string value for the given cookie name. |

Response Object

| Method | Signature | Description | | :--- | :--- | :--- | | status | status(code: number) | Sets the HTTP status code (returns this for chaining). | | send | send(data: string) | Sends a plain text response and ends the connection. | | json | json(data: any) | Sends a JSON payload, sets headers, and ends the connection. | | redirect | redirect(url: string) | Sends a 302 redirect to the client. | | setHeader| setHeader(name: string, value: string) | Sets a custom response header. | | removeHeader| removeHeader(name: string) | Removes a response header. | | setCookie| setCookie(name, value, [options]) | Sets a cookie with CookieOptions. |

CookieOptions

type CookieOptions = {
  httpOnly?: boolean;
  secure?: boolean;
  path?: string;
  domain?: string;
  maxAge?: number;
  sameSite?: "strict" | "lax" | "none";
};

Full Example

Here is a full integration demonstrating how everything ties together:

import Actix, { Router } from "actix";

const app = new Actix();
const apiRouter = new Router();

// Global request logger
app.use(async (req, res, next) => {
  console.log(`-> Received ${req.method} request to ${req.path}`);
  await next();
});

// Nested Router endpoints
apiRouter.get("/info", (req, res) => {
  res.json({ name: "Actix Engine", version: "0.0.1" });
});

apiRouter.post("/data/{id}", (req, res) => {
  const { id } = req.params;
  const { filter } = req.query;
  const body = req.body;

  res.json({
    id,
    filter,
    receivedBody: body,
    timestamp: new Date().toISOString()
  });
});

// Mount modular sub-router under /api
app.use("/api", apiRouter);

// Fallback 404 handler (automatically triggered if no handler/middleware sends a response)
app.listen(3000, () => {
  console.log("🚀 Production server live on port 3000");
});

License

This project is licensed under the MIT License.