Add a Server-Only API Endpoint to Nuxt 3 Without a Separate Backend
Nuxt 3's server/api directory lets you add server-only API endpoints without a separate backend, keeping client bundles small and local testing simple.
14 Aug 2026, 10:17 UTC

Your Nuxt frontend needs a tiny server endpoint, but you do not want to deploy a separate API service
Maybe you need a webhook receiver, a health-check path, or a feature-flag endpoint. Spinning up a dedicated backend for one route adds infrastructure, deployment pipelines, and CORS configuration. Nuxt 3, running on Nitro, lets you place server-only route handlers directly in your project under server/api/. The file name becomes the URL path, the code never reaches the browser, and you can test it locally with the standard dev server.
How file-based server routes work
Any file you add to server/api/ is automatically registered as an HTTP endpoint by Nitro, Nuxt's underlying server engine. For example, server/api/hello.ts answers requests to /api/hello. Each file exports a default handler function. That handler receives an H3 event object, which is Nitro's standardized interface for reading request headers, query parameters, and bodies, and for writing responses. Because these files run only on the server, they are excluded from the client JavaScript bundle, so your frontend stays smaller.
Nuxt auto-imports do not apply inside server/api files. You must write explicit imports, or configure Nitro aliases if you want to reuse shared modules across routes.
Worked example: a JSON health check
Create server/api/ping.ts in your Nuxt project root:
export default defineEventHandler((event) => {
return {
status: 'ok',
timestamp: new Date().toISOString(),
};
});
Run the development server from your project directory:
npx nuxt dev
This command requires no special permissions beyond normal file access to your project folder. Once Nuxt starts, request:
http://localhost:3000/api/ping
You should receive a JSON response with a 200 status and a content-type of application/json. To verify the route is handled by the server and not by client-side code, open your browser's Developer Tools, go to the Network tab, reload /api/ping, and inspect the request. The response should come from the Nuxt server process, and the handler code should not appear in your client bundle.
This pattern is useful for endpoints that must stay secret, such as validating a webhook signature from a payment provider. Because the handler runs only on the server, sensitive logic and environment variables never ship to the browser.
Trade-offs and limits
- Server-only: browser APIs such as
windowordocumentare unavailable inside these handlers. - No auto-imports: every dependency needs an explicit import statement.
- Secrets: never hardcode API keys or secrets in these files. Use
runtimeConfigor environment variables instead. - Scope: this pattern fits lightweight, stateless endpoints. For database transactions, authentication sessions, or long-running jobs, a dedicated backend service is more appropriate.
Practical verification
After adding server/api/ping.ts, confirm these items:
- The request to
/api/pingreturns JSON with a200status. - The Network tab shows the response coming from the Nuxt server, not a client-side fetch.
- Your built client assets do not contain the handler logic.
If the endpoint returns 404, check that the file is directly under server/api/ and that you restarted the dev server after creating it.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.