adapter-standalone

v2026.09.25

Mount tRPC on Node.js built-in HTTP server with createHTTPServer() from @trpc/server/adapters/standalone, createHTTPHandler() for custom http.createServer, createHTTP2Handler() for HTTP/2 with TLS. Configure basePath to slice URL prefix, CORS via the cors npm package passed as middleware option. CreateHTTPContextOptions provides req and res for context creation.

GitHub
Install command
npx skhub add trpc/adapter-standalone
Markdown
SKILL.md

tRPC — Adapter: Standalone

Setup

// server.ts
import { initTRPC } from '@trpc/server';
import { createHTTPServer } from '@trpc/server/adapters/standalone';
import { z } from 'zod';

const t = initTRPC.create();

const appRouter = t.router({
  greet: t.procedure
    .input(z.object({ name: z.string() }))
    .query(({ input }) => ({ greeting: `Hello, ${input.name}!` })),
});

export type AppRouter = typeof appRouter;

createHTTPServer({
  router: appRouter,
  createContext() {
    return {};
  },
}).listen(3000);

console.log('Listening on http://localhost:3000');

Core Patterns

CORS with the cors package

import { createHTTPServer } from '@trpc/server/adapters/standalone';
import cors from 'cors';
import { createContext } from './context';
import { appRouter } from './router';

createHTTPServer({
  middleware: cors({ origin: 'http://localhost:5173' }),
  router: appRouter,
  createContext,
}).listen(3000);

Install CORS support: npm install cors @types/cors

Custom HTTP server with createHTTPHandler

import { createServer } from 'http';
import { createHTTPHandler } from '@trpc/server/adapters/standalone';
import { appRouter } from './router';

const handler = createHTTPHandler({
  router: appRouter,
  createContext() {
    return {};
  },
});

createServer((req, res) => {
  if (req.url?.startsWith('/health')) {
    res.writeHead(200);
    res.end('OK');
    return;
  }
  handler(req, res);
}).listen(3000);

basePath for URL prefix stripping

import { createServer } from 'http';
import { createHTTPHandler } from '@trpc/server/adapters/standalone';
import { appRouter } from './router';

const handler = createHTTPHandler({
  router: appRouter,
  basePath: '/trpc/',
});

createServer((req, res) => {
  if (req.url?.startsWith('/trpc/')) {
    return handler(req, res);
  }
  res.statusCode = 404;
  res.end('Not Found');
}).listen(3000);

The basePath option strips the prefix before routing, so /trpc/greet resolves to the greet procedure.

HTTP/2 with createHTTP2Handler

import http2 from 'http2';
import { readFileSync } from 'node:fs';
import { createHTTP2Handler } from '@trpc/server/adapters/standalone';
import type { CreateHTTP2ContextOptions } from '@trpc/server/adapters/standalone';
import { appRouter } from './router';

const tlsKey = readFileSync('./certs/server.key');
const tlsCert = readFileSync('./certs/server.crt');

async function createContext(opts: CreateHTTP2ContextOptions) {
  return {};
}

const handler = createHTTP2Handler({
  router: appRouter,
  createContext,
});

const server = http2.createSecureServer(
  { key: tlsKey, cert: tlsCert },
  (req, res) => {
    handler(req, res);
  },
);

server.listen(3001);

Limiting batch size with maxBatchSize

import { createHTTPServer } from '@trpc/server/adapters/standalone';
import { appRouter } from './router';

createHTTPServer({
  router: appRouter,
  maxBatchSize: 10,
}).listen(3000);

Requests batching more than maxBatchSize operations are rejected with a 400 Bad Request error. Set maxItems on your client's httpBatchLink to the same value to avoid exceeding the limit.

Common Mistakes

HIGH No CORS configuration for cross-origin requests

Wrong:

createHTTPServer({
  router: appRouter,
  createContext() {
    return {};
  },
}).listen(3000);

Correct:

import cors from 'cors';

createHTTPServer({
  middleware: cors({ origin: 'http://localhost:5173' }),
  router: appRouter,
  createContext() {
    return {};
  },
}).listen(3000);

The standalone adapter has no CORS handling by default. Cross-origin browser requests fail silently because preflight OPTIONS requests receive no CORS headers.

Source: www/docs/server/adapters/standalone.md

See Also

  • server-setup -- initTRPC.create(), router/procedure definition, context
  • adapter-express -- alternative adapter when you need Express middleware ecosystem
  • adapter-fetch -- alternative adapter for edge/serverless runtimes
  • subscriptions -- adding real-time subscriptions to a standalone server
Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.25

Published

Sep 25, 2026

Category

Uncategorized

License

MIT

Source path

packages/server/skills/adapter-standalone

Default branch

main

Latest commit

8b649ad

Tree SHA

6d43a32