API routes
File-based routing
Files under server/routes/ become routes; server/routes/api/* is the API.
The scaffolded examples are meant to be read, curled, and then deleted:
curl localhost:3000/api/posts/hello-zenness # 200
curl localhost:3000/api/posts/Hello%20There # 400, with a readable message
server/routes/api/posts/[slug].ts is the shortest example of a dynamic
route: the matched segment arrives on event.context.params, still
percent-encoded, which is why the handler decodes before it validates —
using the magic-regexp slug pattern from server/utils/slug.ts, so nothing
downstream ever sees a malformed segment.
useEvent()
server/utils/event.ts exports zenness’s useEvent(), a thin alias for
Nitro’s useRequest(). It lets a helper reach the current request without
having it threaded down from the handler:
export function requestInfo() {
const request = useEvent() // no argument, no plumbing
return { path: new URL(request.url).pathname }
}
This depends on experimental.asyncContext: true in nitro.config.ts. Turn
it off and the call throws Nitro request context is not available.
It returns the current request — a web Request, so url is a string;
use new URL(request.url) to read the path. Handlers that want the h3 event
should use the argument defineHandler already gives them.
Auto-imports
imports.dirs in nitro.config.ts publishes everything under server/utils
to the virtual #imports module:
import { requestInfo } from '#imports'
In this Nitro beta imports builds that barrel rather than injecting true
globals, so an import statement is still required. The scaffolded code uses the
@ alias (@/utils/event) instead, which resolves identically and typechecks
without extra declarations.
Logging and errors
server/utils/logger.ts is one tagged, level-aware Consola instance;
everything else logs through it. server/plugins/errors.ts covers the request
lifecycle with it: request lines at debug, deliberate 4xx at warn without a
stack trace, unhandled errors with one. The debug line in
server/routes/api/hello.ts is meant to stay there — it is silent until you
ask for it:
NITRO_LOG_LEVEL=4 npm run dev # 3 is the default, 4 adds debug, 5 adds trace
Outbound calls
server/utils/http.ts is a preconfigured ofetch client: JSON in and out, a
thrown FetchError (with the upstream’s parsed body on .data), retries with
a timeout, and interceptors as the place for auth headers or tracing.
server/routes/api/upstream.ts uses it, and translates the failure — an
upstream 503 becomes a 502 from this service, because the caller asked this
service for something. Point it somewhere real with NITRO_UPSTREAM_URL.
