createMiddleware, request middleware (.server only), server function middleware (.client + .server), context passing via next({ context }), sendContext for client-server transfer, global middleware via createStart in src/start.ts, middleware factories, method order enforcement, fetch override precedence.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
createMiddleware, request middleware (.server only), server function middleware (.client + .server), context passing via next({ context }), sendContext for client-server transfer, global middleware via createStart in src/start.ts, middleware factories, method order enforcement, fetch override precedence.
Middleware customizes the behavior of server functions and server routes. It is composable — middleware can depend on other middleware to form a chain.
CRITICAL: TypeScript enforces method order: → → → . Wrong order causes type errors.
: Client context sent via is NOT validated by default. If you send dynamic user-generated data, validate it in server-side middleware before use.
middleware()
inputValidator()
client()
server()
CRITICAL
sendContext
Two Types of Middleware
Feature
Request Middleware
Server Function Middleware
Scope
All server requests (SSR, routes, functions)
Server functions only
Methods
.server()
.client(), .server()
Input validation
No
Yes (.inputValidator())
Client-side logic
No
Yes
Created with
createMiddleware()
createMiddleware({ type: 'function' })
Request middleware cannot depend on server function middleware. Server function middleware can depend on both types.
Request Middleware
Runs on ALL server requests (SSR, server routes, server functions):
// Use @tanstack/<framework>-start for your framework (react, solid, vue)import { createMiddleware } from"@tanstack/react-start"const loggingMiddleware = createMiddleware().server(
async ({ next, context, request }) => {
console.log("Request:", request.url)
const result = awaitnext()
return result
},
)
Server Function Middleware
Has both client and server phases:
// Use @tanstack/<framework>-start for your framework (react, solid, vue)import { createMiddleware } from"@tanstack/react-start"const authMiddleware = createMiddleware({ type: "function" })
.client(async ({ next }) => {
// Runs on client BEFORE the RPC callconst result = awaitnext()
// Runs on client AFTER the RPC responsereturn result
})
.server(async ({ next, context }) => {
// Runs on server BEFORE the handlerconst result = awaitnext()
// Runs on server AFTER the handlerreturn result
})
Attaching Middleware to Server Functions
// Use @tanstack/<framework>-start for your framework (react, solid, vue)import { createServerFn } from"@tanstack/react-start"const fn = createServerFn()
.middleware([authMiddleware])
.handler(async ({ context }) => {
// context contains data from middlewarereturn { user: context.user }
})
Fetch precedence (highest to lowest): call site → later middleware → earlier middleware → createStart global → default fetch.
Common Mistakes
1. HIGH: Trusting client sendContext without validation
// WRONG — client can send arbitrary data
.server(async ({ next, context }) => {
await db.query(`SELECT * FROM workspace_${context.workspaceId}`)
returnnext()
})
// CORRECT — validate before use
.server(async ({ next, context }) => {
const workspaceId = z.string().uuid().parse(context.workspaceId)
await db.query('SELECT * FROM workspaces WHERE id = $1', [workspaceId])
returnnext()
})
2. MEDIUM: Confusing request vs server function middleware
Request middleware runs on ALL requests (SSR, routes, functions). Server function middleware runs only for createServerFn calls and has .client() method.
3. HIGH: Browser APIs in .client() crash during SSR
During SSR, .client() callbacks run on the server. Browser-only APIs like localStorage or window will throw ReferenceError:
// WRONG — localStorage doesn't exist on the server during SSRconst middleware = createMiddleware({ type: "function" }).client(
async ({ next }) => {
const token = localStorage.getItem("token")
returnnext({ sendContext: { token } })
},
)
// CORRECT — use cookies/headers or guard with typeof window checkconst middleware = createMiddleware({ type: "function" }).client(
async ({ next }) => {
const token =
typeofwindow !== "undefined" ? localStorage.getItem("token") : nullreturnnext({ sendContext: { token } })
},
)