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

mates-fullstack

v1.0.7

Published

Full-stack Node.js framework built on the Mates SPA framework. RPC server functions, WebSockets, file-system routing.

Readme

mates-fullstack

TypeScript-first full-stack framework for Mates apps. It adds direct RPC-style server functions, raw HTTP escape hatches, WebSockets, static assets, and production builds without requiring a compiler in production.

No JSX. No virtual DOM. No Express/Hono/Fastify. Runtime server is pure Node.js (node:http). Bundling and TypeScript transforms use esbuild.


Install

npm install mates-fullstack mates

Add scripts to your app:

{
  "scripts": {
    "dev": "mates-fullstack dev",
    "build": "mates-fullstack build",
    "start": "mates-fullstack start"
  }
}

Project structure

mates-fullstack is convention-based; no config file is required.

my-app/
  client/
    App.ts          # root SPA component and client router
    client.ts       # browser entry point; calls renderX(App, ...)
  server/
    api/            # RPC functions callable from client imports
    helpers/        # server-only utilities; never bundled for browser
    main.ts         # optional middleware registration
    socket/         # optional WebSocket handlers
  shared/           # code/types used by both sides
    public/           # inside client/ — static files copied to dist/public in production
  package.json

Minimal app

client/App.ts

import { html } from "mates";

export default () => {
  return () => html`<h1>Hello from mates-fullstack</h1>`;
};

client/client.ts

import { renderX } from "mates";
import App from "./App";

renderX(App, document.getElementById("app")!);

server/api/todos.ts

import type { ServerCtx } from "mates-fullstack";
import { ValidationError } from "mates-fullstack";

export async function listTodos(_payload: {}, _ctx: ServerCtx) {
  return [{ id: 1, title: "Write docs" }];
}

export async function addTodo(payload: { title: string }, _ctx: ServerCtx) {
  if (!payload.title.trim()) {
    throw new ValidationError("Invalid todo", {
      fields: { title: "Required" },
    });
  }
  return { id: Date.now(), title: payload.title };
}

Client code calls server functions directly

import { asyncAction, html } from "mates";
import { listTodos } from "../server/api/todos";

const TodoPage = () => {
  const load = asyncAction(() => listTodos({}));
  load();

  return () => html`
    <pre>${JSON.stringify(load.data(), null, 2)}</pre>
  `;
};

During development and production builds, imports from server/api/** are converted into browser-safe RPC stubs. Imports from any other server/** path are blocked from client code.


Commands

npm run dev      # native ESM dev server, no browser bundle
npm run build    # production client bundle + compiled server runtime
npm run start    # start production server from dist/

Development mode

Development intentionally serves source modules instead of a client bundle:

  • app source modules: /_src/**
  • package modules: /_pkg/**
  • framework helpers: /_mates/**
  • import map injected into the HTML shell
  • chokidar watches client/ (including client/public/), server/, shared/, .env*, and config files
  • reload generation is owned by the parent dev process and delivered through SSE

This makes stack traces point at source-like module URLs and keeps rebuilds fast.


Authentication

Email/Password + Social Login

mates-fullstack provides a complete auth system out of the box. Access tokens are short-lived (15 min default), stored in httpOnly cookies. Refresh tokens (30 days) live in a separate httpOnly cookie and rotate automatically, with JTI replay detection.

// server/main.ts
import { matesAuth, auth, useArctic } from "mates-fullstack";

matesAuth({ secret: process.env.AUTH_JWT_SECRET! });

useArctic({
  google: {
    clientId: process.env.GOOGLE_CLIENT_ID!,
    clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    onSuccess: async (profile, ctx) => {
      const user = await db.users.upsert({ ... });
      await auth.login(ctx, { userId: user.id, email: user.email });
    },
  },
});

Routes /auth/google and /auth/google/callback are registered automatically. onSuccess gives you full control — call auth.login() to issue tokens, or skip it to just link accounts.

10 built-in OAuth providers: Google, GitHub, Discord, Microsoft, Twitter, LinkedIn, Facebook, Apple, Spotify, GitLab. Custom providers via arcticProvider({ handler, ... }).

Cross-Domain SSO

For apps on different domains sharing one auth server. The auth server signs a 30-second code JWT with a shared secret — each app verifies it locally, no round-trip needed.

// auth.com/server/main.ts
import { useSsoProvider } from "mates-fullstack";

useSsoProvider({
  secret: process.env.SSO_SECRET!,
  login: "/login",
  allowedOrigins: ["https://app1.com", "https://app2.com"],
});

// app1.com/server/main.ts
import { useSsoClient } from "mates-fullstack";

useSsoClient({
  authUrl: "https://auth.com",
  secret: process.env.SSO_SECRET!,
  protected: ["/dashboard", "/settings"],
});

Each app issues its own httpOnly session cookies. Works with social login — put useArctic() on the auth server, useSsoClient() on every app.


Middleware

All middleware registers globally in server/main.ts and runs in registration order.

Recommended server/main.ts:

import {
  matesAuth, requestLogger, useSecurityHeaders, useCors, rateLimit,
} from "mates-fullstack";

matesAuth({ secret: process.env.AUTH_JWT_SECRET! });
requestLogger({ skip: [/^\/health$/, /^\/_mates\//] });
useSecurityHeaders();
useCors({ origins: "https://app.example.com" });
rateLimit({ max: 10, window: "15m", pathPrefix: "/auth" });
rateLimit({ max: 300, window: "1m" });

Request Logger

requestLogger({ skip: [/^\/health$/, /^\/assets\//] });

Logs every request (method, path, IP) on arrival and every RPC response (status, ms) on completion. Stamps x-request-id on every response. Structured logging — NDJSON in production, pretty-printed in dev.

Security Headers

useSecurityHeaders();
useSecurityHeaders({ contentSecurityPolicy: "default-src 'self'", xFrameOptions: "DENY" });

Sets 14 standard security headers on every response — complete helmet-equivalent coverage. Every header individually overridable or disableable. HSTS auto-enabled in production, skipped in dev. CSP and Permissions-Policy are opt-in.

CORS

useCors({ origins: "https://app.example.com", credentials: true });
useCors({ origins: (origin) => origin.endsWith(".example.com") });

Handles preflight OPTIONS automatically (returns 204). Reflects origin when credentials: true as required by the CORS spec. Sets Vary: Origin.

Rate Limiting

rateLimit({ max: 100, window: "1m" });                             // all routes
rateLimit({ max: 10, window: "15m", pathPrefix: "/auth" });        // auth only
rateLimit({ max: 5, window: "1h", key: (_req, ctx) => String(ctx.auth.userId) }); // per-user

Sliding-window counter, in-memory. Returns 429 with Retry-After and X-RateLimit-* headers. Auto-evicts expired entries. Custom key function for per-user or per-endpoint limiting.

Raw HTTP hooks

For cases where an external service dictates the HTTP contract (webhooks, custom OAuth flows):

import { onHttpRequest } from "mates-fullstack";

onHttpRequest(async (req, ctx) => {
  const url = new URL(req.url);
  if (req.method === "POST" && url.pathname === "/stripe-webhook") {
    const body = await req.text();
    await handleWebhook(body, ctx.reqHeaders["stripe-signature"]);
    return new Response("ok");
  }
});

Request Limits / Resource Protection

Built-in limits prevent CPU and memory exhaustion. All have safe defaults — override only to tune for your app.

// server/main.ts — at the top, before middleware
import { configureRpcRunner } from "mates-fullstack/internal";

configureRpcRunner({
  maxJsonBytes: 5 * 1024 * 1024,     // default 1MB
  maxJsonDepth: 30,                    // default 50
  maxArrayLength: 5000,                // default 10_000
  maxStringLength: 50_000,             // default 100_000
  maxUploadBytes: 50 * 1024 * 1024,   // default 10MB
  maxMultipartParts: 100,              // default 200
});

Or set server-level limits when starting:

await startServer({
  maxConnections: 2000,           // default 1000
  staticStreamTimeout: 120_000,   // default 60s
  maxSseClients: 1000,            // default 500
});

All defaults are active without any configuration call. See DOCS.md for full details.


Public entrypoints

| Import | Use for | |---|---| | mates-fullstack | stable app API: errors, redirects, middleware registration, ServerCtx, validation/sanitize/upload helpers | | mates-fullstack/client | browser hydration and RPC helpers | | mates-fullstack/browser | browser-safe error/redirect/stream/download helpers | | mates-fullstack/server | server-safe helpers and middleware runners | | mates-fullstack/internal | unstable build/runtime/scanner internals for tooling |


License

MIT