Build1 distinct publisher3 min readPublished
Nuxt Endpoints builds on the validated-routing design under discussion in H3 RFC #1437, keeping files, URLs and methods while the declared schema constrains both the handler and the caller. The upstream design is still being debated.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
The direction the types flow is what makes `defineRouteHandler()` worth reading. Yoshinori Ishii's argument in the post is that a server contract should do more than type the response, that it should constrain the handler, and that it should let the client switch on features which depend on that contract, so a pagination adapter can require a route that declares pagination [18].
Writing `pagination: { kind: 'cursor', item: Article }` in `server/api/articles.get.ts` gives the request validated `cursor` and `limit` query fields and pins the `200` body to `{ items: Article[], nextCursor?: string }` [5]. The handler's successful return has to match, so returning `{ nextCursor }` without `items` is a server-side type error [6]. The generated OpenAPI document carries the same fields, which is why another service or `curl` can call the route without NE [7]. On the client, `infiniteQueryOptions()` refuses an endpoint that does not declare the cursor contract, at compile time [8]. That is five distinct checks from one declaration [1], and the database query and cursor encoding are still your code [17].
Status narrowing is the other piece worth copying. A detail route declares `200` with an article and `404` with a message; checking `result.status` narrows `result.body`, so the 404 arrives as a value you handle rather than a thrown fetch error, while network failures still reject the request [10].
The limits are stated in the post itself, which is more than most pagination helpers bother with. Declared response types describe declared responses, and a proxy or other infrastructure can return something outside them [11]. The `{ items, nextCursor }` envelope is NE's convention, not an HTTP standard [12]. The contract checks shape, not semantics, so it cannot prove your query returned the right next page [13].
The form path keeps the same rule. In the experimental Nuxt 5 prototype the server is an explicit POST route that declares a form action of `/users/new` and a redirect to `/users/{id}` [14]. One `UserInput` schema validates both `application/json` and `application/x-www-form-urlencoded` bodies, the second through `formOf()`, alongside a declared `201` response [15]. The page side takes `form.attrs`, `form.enhance`, `form.fields` and `form.issues` from `useEndpointForm()` [16].
For that DX to transfer you need to be on H3, to accept a schema per route, and to tolerate churn, because the upstream validated-routing design is still under discussion and NE both implements and extends it [4]. The comparison the post is answering is server or remote functions in Next.js, SolidStart, TanStack Start and SvelteKit [1], so the choice on the table is who owns the contract rather than whether the URL survives.
Right now the contract's portable surface is the OpenAPI document, readable without NE [7], while the only compile-time consumer shown is NE's own adapter [8]. RFC #1437 is where that asymmetry gets settled.
Ranked by verification strength, evidence, and original report placement.
Next.js, SolidStart, TanStack Start and SvelteKit all offer some form of server or remote functions, and the appeal is connecting server code to forms and data fetching.
The author, Yoshinori Ishii, writes that he has used Nuxt since its early releases and likes Nuxt 5's work on typed HTTP routes.
In Nuxt Endpoints, routes keep their files, URLs and HTTP methods, and defineRouteHandler() builds on the validated-routing design being discussed in H3 RFC #1437: request and response schemas alongside the handler, with a contract that other tools can read.
Nuxt Endpoints implements and extends the RFC #1437 design to connect it to client behaviour including pagination and forms; the upstream design is still under discussion, and the post's examples use NE's implementation.
Declaring pagination: { kind: 'cursor', item: Article } in server/api/articles.get.ts defines GET /api/articles with validated cursor and limit query fields and a 200 response of { items: Article[], nextCursor?: string }.
The handler's successful return must match the declared page shape; returning { nextCursor } without items is a server-side type error.
Distinct publishers with included, body-backed reporting in this cluster.
1 article · September 5, 2026
Follow any of these and your For You feed starts watching them — no settings page required.
build
Five frameworks, one store, and a benchmark that measures when the button works1 distinct publisher
build
The 300-monitor wall is real, and sharding Uptime Kuma is a bill you keep paying1 distinct publisher
build
Build concurrency on one VPS is a division problem, and the app you serve pays the remainder1 distinct publisher
build
A 74 on the agent-readiness scoreboard, and two checks worth failing1 distinct publisher
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Checkable snippets, one witness
The mechanics are stated precisely enough to be checked against code a reader can run: the return missing items that fails to type, the adapter call that refuses an endpoint with no pagination declaration. Against that, the developer-experience case is demonstrated rather than measured, and the claims about what already ships on Nuxt 4 rest on the author's word with no repository artifact or test output in front of the reader.
Shipped code, no visible users
What is real is a published Nuxt 4 release carrying pagination, status-aware requests, Pinia Colada adapters, OpenAPI generation and idempotency. Past that the trail ends: the Nuxt 5 work only runs on prototype forks whose extensions upstream declined to take, and no install figure, dependent project or second team appears. Uptake here amounts to the author's own release cadence.
Caveats outrun the pitch
A project post by its own maintainer usually oversells; this one keeps trimming itself. Ishii flags that the H3 design is still being discussed and that the contract checks a response shape without proving a cursor query returns the right page. The claim actually made is small, that a declaration in the route file gates a client adapter at compile time, and the code makes it. If anything the more consequential part gets said too quietly: because the contract is expressed in OpenAPI, a service that has never installed the module can still call the route.
Author, publisher and beneficiary are one person
Nuxt Endpoints is the author's module, the post sits on his own dev.to account, and it closes with an intention to get the contract-introspection and type-inference work adopted by Nuxt and Nitro so the module can reuse it. None of that is concealed and the register stays technical, but the comparison against other frameworks' server functions is drawn entirely by the party with a stake in the answer.
Narrow claims, single-witness sourcing
The specific mechanics are the sort of thing that would be embarrassing to get wrong in public code, and the limits are self-imposed rather than extracted, which raises trust in the details. The uncertainty sits a level up, in whether the H3 proposal keeps this shape and whether anything outside the author's own repositories comes to depend on it. One publisher and one witness, with nothing to corroborate and nothing to contradict.