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

@reckona/mreact-router

v0.0.16

Published

File-system app router, SSR, actions, and deployment adapters for mreact.

Readme

@reckona/mreact-router

@reckona/mreact-router is the mreact app router. It covers file-system routes, loaders, metadata, server actions, prerendering, and deployment adapters.

Basic Usage

import { buildApp, renderBuiltAppRequest } from "@reckona/mreact-router";

await buildApp({
  projectRoot: process.cwd(),
  routesDir: "src/app",
  publicDir: "public",
  allowedSourceDirs: ["src"],
  outDir: ".mreact",
  targets: ["node"],
});

const response = await renderBuiltAppRequest({
  outDir: ".mreact",
  request: new Request("https://example.test/"),
});

For application projects, configure the router explicitly in vite.config.ts:

import { defineConfig } from "vite";
import { mreactRouter } from "@reckona/mreact-router/vite";

export default defineConfig({
  plugins: [
    mreactRouter({
      projectRoot: __dirname,
      routesDir: "src/app",
      publicDir: "public",
      allowedSourceDirs: ["src"],
    }),
  ],
});

mreact-router build reads this config. Pass --target=node for Node, container, and AWS Lambda artifacts, --target=cloudflare for Workers artifacts, or configure buildTargets: ["node"] / buildTargets: ["cloudflare"] in mreactRouter() when one deployment target should be the project default. Without an explicit target, build output includes both Node-compatible server/client artifacts and Cloudflare route modules for backward compatibility. The legacy appDir shortcut remains available for tests and older direct programmatic usage, but it is deprecated. Use projectRoot + routesDir for new code. The shortcut is planned for removal after 0.1.0.

mreact-router dev reads the same config and uses server.port from vite.config.ts when PORT is not set. This keeps Playwright webServer setups and local dev commands on the same configured port.

For TypeScript projects that type-check route modules directly, include the app-router global declarations so route files can use <Slot /> without a local import:

{
  "compilerOptions": {
    "types": ["@reckona/mreact-router/app-router-globals"]
  }
}

Client Navigation

Internal anchors are intercepted by the app-router client runtime and update the changed route payload instead of forcing a full document reload. The runtime keeps head metadata and route-data scripts synchronized, restores scroll on back/forward navigation, and prefetches client route scripts for likely navigations when the browser is not in reduced-data mode.

Use Link or linkProps() when a route needs explicit navigation behavior:

import { Link } from "@reckona/mreact-router/link";

export default function Page() {
  return (
    <nav>
      <Link href="/docs" prefetch="viewport">
        Docs
      </Link>
      <Link href="/editor" scroll="preserve" transition="auto">
        Editor
      </Link>
      <Link href="/legacy" reload>
        Legacy page
      </Link>
    </nav>
  );
}

Link and linkProps() are also re-exported from @reckona/mreact-router for compatibility, but @reckona/mreact-router/link is the preferred import for client-only code. Navigation observers are available from @reckona/mreact-router/navigation-state as getNavigationState() and subscribeNavigationState().

Route Module Exports

  • loader(context) returns data passed to the page component, or may return or throw a Response for redirects and custom responses.
  • metadata injects title, OpenGraph, viewport, and related head tags.
  • generateStaticParams() returns dynamic route params to prerender.
  • prerender = true emits HTML at build time.
  • "use server" modules and <form action={...}> provide server actions.
  • Server actions reject Content-Length values over 10 MiB by default. Pass serverActions: { maxBodyBytes } to configure the limit.
  • Route handlers may return or throw standard Response objects from method exports such as GET, POST, or ALL. Dynamic route handlers receive decoded params as the second argument: GET(request, { params }).

Deployment Adapters

  • @reckona/mreact-router/adapters/node: Node http server adapter.
  • @reckona/mreact-router/adapters/static: static export adapter for prerendered routes.
  • @reckona/mreact-router/adapters/edge: generic Request / Response runtime adapter.
  • @reckona/mreact-router/adapters/cloudflare: Cloudflare Workers adapter.
  • @reckona/mreact-router/adapters/aws-lambda: AWS Lambda HTTP API v2 adapter.

The built-in CLI can print compact request summaries for both local development and built output:

mreact-router dev --log=requests
mreact-router start .mreact --log=requests
MREACT_ROUTER_LOG=requests mreact-router dev

Each line includes method, path, status, duration, and runtime. Query strings, headers, and request bodies are intentionally omitted.

Server-only pages can opt into the lightweight navigation runtime without becoming hydrated client routes:

import { Link } from "@reckona/mreact-router/link";

export const navigationRuntime = true;

export default function Page() {
  return <Link href="/docs" prefetch="viewport">Docs</Link>;
}

The build manifest records this separately from client: true, emits a shared navigation runtime asset, prefetches client route scripts when present, and falls back to x-mreact-navigation: 1 HTML prefetches for server-only targets.

For Cloudflare Workers, combine createCloudflareBuiltRequestHandler, createCloudflareStaticAssetLoader, createCloudflarePrerenderStore, and createCloudflareRouteModuleRenderer. mreact-router build --target=cloudflare emits .mreact/cloudflare/route-modules.mjs for non-prerendered and dynamic App Router pages, so Workers entrypoints can import a plain route registry without Vite-only import.meta.glob() transforms. Client assets are served only when they appear in the generated manifest allow-list. Dynamic routes should resolve modules through a build-time registry keyed by route.file, not by constructing module ids from request input. Generated Cloudflare route modules support stream = true pages with route-local <Await> boundaries and local server-component imports.

For AWS Lambda, use createAwsLambdaRequestHandler() with API Gateway HTTP API v2 or Lambda Function URL payload format 2.0:

import { createAwsLambdaRequestHandler } from "@reckona/mreact-router/adapters/aws-lambda";

export const handler = createAwsLambdaRequestHandler({
  outDir: ".mreact",
  importPolicy: {
    allowedPackages: [
      "@reckona/mreact",
      // "cookie",
      // "zod",
    ],
  },
  onResponse(response) {
    response.headers.set("x-content-type-options", "nosniff");
  },
});

Production adapters enforce the app-router import policy when bundling loaders, middleware, route handlers, metadata, and server actions. Add every npm package imported by server-side application code to importPolicy.allowedPackages, including dependencies reached through app-local helper modules.

For Lambda and other Node-only deployments, build with mreact-router build --target=node or buildApp({ targets: ["node"] }). Node-only builds skip .mreact/cloudflare route modules, so loaders and server helpers may import Node-only dependencies such as database drivers without being bundled for the Workers runtime.

For Lambda deployments, package a minimal asset directory instead of the full project checkout. AWS Lambda enforces a 250 MB unzipped deployment package limit, and the runtime only needs .mreact/, the bundled handler, package.json / lockfiles, and production node_modules; src/, tests, dev dependencies, build caches, and Vite/Vitest/Playwright tooling are not required. mreact-router build --target=node keeps compiled server route artifacts in .mreact/server/server-modules/*.json instead of embedding them in one large server manifest. createAwsLambdaRequestHandler() treats outDir as read-only and materializes generated runtime files under /tmp/mreact-router/<hash>/runtime by default, with a node_modules symlink back to the deployed package root. Handler creation starts a background preload for the built runtime, loader modules, middleware, route handlers, and route metadata so route-specific bundling can move out of the first matched request on warmable runtimes; if a request arrives before preload finishes, middleware is resolved first, middleware responses or redirects return without loading the matched page artifact, and continuing requests load only the matched route's artifact closure. Pass runtimeDir only when you need to control that writable cache location. With pnpm, copy those files into .lambda/ and run pnpm --dir .lambda install --prod --frozen-lockfile --ignore-scripts --config.node-linker=hoisted. pnpm's default isolated linker is symlink-heavy, so verify the artifact's symlink count with find .lambda -type l | wc -l and measure actual file bytes in addition to du -sh .lambda before upload. Every package listed in importPolicy.allowedPackages must also be installed in that production artifact.

Set timings: true on createAwsLambdaRequestHandler() or createAwsLambdaStreamingRequestHandler() when you need low-overhead Lambda phase diagnostics. The adapter emits a router:request:timing debug log event with eventToRequestMs, runtimeDirMs, renderMs, and response serialization or streaming time, so production measurements can separate API Gateway event normalization, runtime materialization, route rendering, and Lambda response conversion.

The Lambda adapter returns proxy responses with cookies, headers, statusCode, body, and isBase64Encoded. It buffers response bodies because API Gateway and Lambda Function URL proxy responses do not expose true streaming SSR. Prefer S3 + CloudFront for .mreact/client assets on production Lambda deployments.

For Lambda Function URL response streaming, use createAwsLambdaStreamingRequestHandler() instead:

import { createAwsLambdaStreamingRequestHandler } from "@reckona/mreact-router/adapters/aws-lambda";

export const handler = createAwsLambdaStreamingRequestHandler({
  outDir: ".mreact",
});

The streaming handler requires the Node.js Lambda runtime awslambda.streamifyResponse() and awslambda.HttpResponseStream.from() APIs. It streams response bytes directly and preserves status, headers, and cookies through Lambda response streaming metadata.

Related APIs

  • renderAppRequest: development and test API for rendering a source app directory.
  • renderBuiltAppRequest: production API for rendering a .mreact/ build artifact.
  • startDevServer: dev server that watches the app directory.
  • startServer: helper that serves a .mreact/ build artifact with Node.

renderAppRequest and the development server enforce the app-router import policy before bundling loaders, middleware, metadata, and server actions. Packages must either be explicitly allowed through importPolicy.allowedPackages or, in dev, be declared by the application package.json. Allowed server dependencies may use normal Node runtime features, including CommonJS modules that require Node built-ins such as events.

Use relative imports for app-local modules in server-side route code. The production server bundler applies the import policy before Vite-only or tsconfig path alias plugins can rewrite aliases such as ~/*, so an alias like ~/lib/csrf is treated as a package import named "~". Prefer ../lib/csrf.js or another relative specifier in loaders, middleware, route handlers, metadata modules, server actions, and their app-local helper modules.

Route pages may extract server-only UI into app-local .tsx or .mreact.tsx components and pass JSX children through them. The router compiles those local server-component dependencies with the same server string or stream target before inserting the page output into layout <Slot /> positions.

Sessions

Application code should import session helpers from @reckona/mreact-auth: createMemorySessionStore(), createSession(), getSession(), destroySession(), and rotateSession(). The router still re-exports these helpers for older code, but those re-exports are deprecated.