TanStack Start SSR
Copy it into a new project:
pnpm dlx degit antstanley/blogwright/examples/tanstack-start-ssr my-siteTanStack Start (React) built through Nitro’s node-server preset, running on a Lambda Web Function. Fingerprinted /assets/ still serve from S3.
| Framework | Mode | Blogwright config | Source |
|---|---|---|---|
| TanStack Start (React) + Nitro | Server-rendered | ssr |
examples/tanstack-start-ssr |
Deploy it
Section titled “Deploy it”-
Copy the example and start a repository:
Terminal window pnpm dlx degit antstanley/blogwright/examples/tanstack-start-ssr my-sitecd my-site && git init -
Set
siteNameandregioninconfig/production.jsonc. For SSR,regionmust beus-east-1,us-east-2,us-west-2,ap-northeast-1oreu-west-1. -
Add Blogwright, then commit everything, including
pnpm-lock.yaml- the builder installs with--frozen-lockfile:Terminal window pnpm add -D blogwrightgit add -A && git commit -m "Start from the blogwright example" -
Create the infrastructure:
pnpm exec blogwright bootstrap -
Build and publish:
pnpm exec blogwright deploy
What matters
Section titled “What matters”vite.config.ts- thetanstackStart()plugin, thennitro({ preset: 'node-server' }), which writes a standalone server to.output/serverand the browser assets to.output/public, then React’s plugin.src/routes/index.tsx- a server function supplies the render timestamp, so the page proves it ran on the server.lambda.mjs- the entry shim. It mapsAWS_LAMBDA_HTTP_ENDPOINTontoNITRO_HOSTandNITRO_PORT, then importsindex.mjs. The build copies it into.output/server/.pnpm-workspace.yaml-allowBuildsapproves esbuild’s install script, which pnpm 11 otherwise fails the install on.config/production.jsonc- packages.output/server.staticDirandstaticPathspublish the fingerprinted/assets/to S3.
The files
Section titled “The files”// Blogwright config for this example. Paths are relative to the repository// root, so they assume this directory IS the repository - see README.md.{ "region": "us-east-1", "siteName": "tanstack-start-ssr", "ssr": { "packageDir": ".output/server", "entryPoint": "lambda.mjs", "staticDir": ".output/public", "staticPaths": ["/assets/*", "/favicon.svg"], },}import { tanstackStart } from '@tanstack/react-start/plugin/vite';import viteReact from '@vitejs/plugin-react';import { nitro } from 'nitro/vite';import { defineConfig } from 'vite';
export default defineConfig({ plugins: [ tanstackStart(), // Nitro's node-server preset writes a standalone Node server to // .output/server and the browser assets to .output/public. nitro({ preset: 'node-server' }), // React's plugin must come after Start's. viteReact(), ],});// Entry shim for Lambda Web Functions. Lambda passes the listen address in// AWS_LAMBDA_HTTP_ENDPOINT; Nitro's node-server reads NITRO_HOST and NITRO_PORT.const endpoint = process.env.AWS_LAMBDA_HTTP_ENDPOINT;const colon = endpoint.lastIndexOf(':');process.env.NITRO_HOST = endpoint.slice(0, colon);process.env.NITRO_PORT = endpoint.slice(colon + 1);await import('./index.mjs');# A workspace of its own, so pnpm treats this directory as the project root# even inside the blogwright repository.packages: - .
allowBuilds: # esbuild's postinstall installs its platform binary. esbuild: true{ "name": "blogwright-example-tanstack-start-ssr", "private": true, "type": "module", "packageManager": "pnpm@11.25.0", "scripts": { "dev": "vite dev", "build": "vite build && cp lambda.mjs .output/server/" }, "dependencies": { "@tanstack/react-router": "^1.170.44", "@tanstack/react-start": "^1.169.1", "react": "^19.3.0", "react-dom": "^19.3.0" }, "devDependencies": { "@types/react": "^19.3.0", "@types/react-dom": "^19.3.0", "@vitejs/plugin-react": "^6.1.2", "nitro": "3.0.260903-beta", "vite": "^8.3.4" }}Check the package locally
Section titled “Check the package locally”Run it the way Lambda does - from a copy outside the project, so nothing resolves from its own node_modules:
pnpm buildcp -R .output/server /tmp/pkg && cd /tmp/pkgAWS_LAMBDA_HTTP_ENDPOINT=127.0.0.1:8080 node lambda.mjscurl -i http://127.0.0.1:8080/The server must start listening within 10 seconds, and find .output/server -type l must print nothing: the build agent rejects a package that contains a symbolic link.
Related pages
Section titled “Related pages”- Server-rendered sites: TanStack Start - the full recipe and its options
- Examples overview - every example, and the conventions they share