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

@act-spec/runtime-next

v0.2.0-rc.1

Published

PRD-501 Next.js runtime SDK for the ACT (Agent Content Tree) v0.1 reference implementation. App Router route handlers + middleware for the discovery hand-off Link header. Consumes @act-spec/runtime-core (PRD-500).

Readme

@act-spec/runtime-next

Next.js runtime SDK for ACT (Agent Content Tree).

This package is a thin leaf adapter over @act-spec/runtime-core. It binds runtime-core's framework-neutral resolver / dispatch contract onto Next.js's App Router (and a Pages Router escape hatch), adding only the framework-specific glue: catch-all [...id] segment joining, request normalization (Request.cookies), the App Router file layout, and a middleware.ts-shaped helper for the discovery hand-off Link header on non-ACT routes.

Status

ACT v0.1 internal hand-test candidate. Public release lands at v0.2.

Install

Unpublished in v0.1. Consume via the workspace:

// package.json
{ "dependencies": { "@act-spec/runtime-next": "workspace:*" } }

next is a peerDependencies entry (>=14.2 <16) so consumers control the version. The SDK does not import Next at runtime — handlers are WHATWG (req: Request, ctx) => Promise<Response> functions, compatible with both the Node.js Runtime and the Edge Runtime.

Quick start (Core)

// app/act-mount.ts
import { defineActMount } from '@act-spec/runtime-next';

export const actMount = defineActMount({
  manifest: {
    act_version: '0.1',
    site: { name: 'Acme Workspace' },
    delivery: 'runtime',
    conformance: { level: 'core' },
    auth: { schemes: ['cookie', 'bearer'] },
    index_url: '/act/index.json',
    node_url_template: '/act/n/{id}',
  },
  runtime: {
    async resolveManifest(req, ctx) { /* ... */ },
    async resolveIndex(req, ctx) { /* ... */ },
    async resolveNode(req, ctx, { id }) { /* ... */ },
  },
  identityResolver: async (req) => {
    const principal = await yourAuth(req);
    if (!principal) return { kind: 'auth_required', reason: 'missing' };
    return { kind: 'principal', key: principal.id };
  },
  tenantResolver: async (req, identity) => ({ kind: 'scoped', key: identity.kind === 'principal' ? identity.key : 'default' }),
});
// app/.well-known/act.json/route.ts
import { actMount } from '@/app/act-mount';
export const GET = actMount.manifest;
// app/act/index.json/route.ts
import { actMount } from '@/app/act-mount';
export const GET = actMount.index;
// app/act/n/[...id]/route.ts
import { actMount } from '@/app/act-mount';
export const GET = actMount.node;

The catch-all [...id] segment is mandatory for nodes and subtrees — IDs may contain /, and the single-segment [id] form would silently truncate them.

File layout (App Router)

app/
├── .well-known/
│   └── act.json/route.ts          # GET = actMount.manifest
├── act/
│   ├── index.json/route.ts        # GET = actMount.index
│   ├── index.ndjson/route.ts      # Plus only — GET = actMount.indexNdjson
│   ├── n/[...id]/route.ts         # GET = actMount.node
│   ├── sub/[...id]/route.ts       # Standard / Plus — GET = actMount.subtree
│   └── search/route.ts            # Plus only — GET = actMount.search
└── act-mount.ts                    # exports actMount = defineActMount({ ... })

Discovery hand-off Link header

The SDK emits the discovery Link header on every ACT-endpoint response automatically. To emit the header on non-ACT routes (the host application's HTML pages), mount the actLinkHeaderMiddleware in middleware.ts:

// middleware.ts
import { NextResponse } from 'next/server';
import { actLinkHeaderMiddleware } from '@act-spec/runtime-next';

const linkMw = actLinkHeaderMiddleware({
  isAuthenticated: (req) => req.cookies.has('next-auth.session-token'),
});

export async function middleware(req: Request) {
  const res = NextResponse.next();
  return linkMw(req, res);
}

export const config = {
  matcher: '/((?!api|_next/static|_next/image|favicon.ico).*)',
};

The isAuthenticated predicate is the host's responsibility — keep it fast (cookie / header presence check), NOT a full identity verification (too expensive on every page load).

Hybrid mounts

A Next.js app MAY participate in a parent manifest's mounts array by setting basePath:

defineActMount({
  manifest: { /* ... conformance: { level: 'standard' }, ... */ },
  basePath: '/app',
  // ...
});

The served manifest then advertises URLs prefixed with /app; the parent manifest at /.well-known/act.json (typically served by a sibling static-export build) declares the mount at prefix: "/app".

Two-principal probe (cross-tenant non-disclosure)

This package wires the mandatory two-principal probe from @act-spec/runtime-core/test-utils against an in-process synthetic resolver. The probe verifies that:

  1. Each principal can resolve their own visible nodes (sanity baseline).
  2. Cross-tenant requests (principal A asks for principal B's node, and vice versa) return 404.
  3. The cross-tenant 404 is byte-equivalent to an absent-node 404 (status, body, every header — Content-Type, Cache-Control, Link).
  4. The discovery Link header is present and identical across both 404 paths (does not leak tenant identity in error cases).

The probe is in src/probe.test.ts and runs as part of pnpm test. It is a CI-mandatory test; do not skip and do not weaken.

Pages Router escape hatch

For hosts that have not migrated to the App Router:

// pages/api/act/[...act].ts
import { createActPagesHandler } from '@act-spec/runtime-next';
export default createActPagesHandler({ /* same options as defineActMount */ });

The Pages Router branch normalizes requests through the same dispatch pipeline. NDJSON streaming is buffered (eager) since legacy NextApiResponse does not support streaming bodies; use the App Router for Plus deployments.

Conformance

pnpm -F @act-spec/runtime-next conformance runs @act-spec/validator in validateSite runtime-walk mode against an in-process Standard mount via a synthetic fetcher (no real HTTP server). Pass criterion: 0 gaps; achieved level == declared level.

License

Apache-2.0. See LICENSE.