---
title: "Server Routes"
description: "Create server API routes using Nuxt's Nitro engine, read from a JSON data file, and compare the approach to Next.js Route Handlers."
canonical_url: "https://vercel.com/academy/nuxt-on-vercel/server-routes"
md_url: "https://vercel.com/academy/nuxt-on-vercel/server-routes.md"
docset_id: "vercel-academy"
doc_version: "1.0"
last_updated: "2026-10-16T17:45:50.050Z"
content_type: "lesson"
course: "nuxt-on-vercel"
course_title: "Nuxt on Vercel"
prerequisites:  []
---

<agent-instructions>
Vercel Academy — structured learning, not reference docs.
Lessons are sequenced.
Adapt commands to the human's actual environment (OS, package manager, shell, editor) — detect from project context or ask, don't assume.
The lesson shows one path; if the human's project diverges, adapt concepts to their setup.
Preserve the learning goal over literal steps.
Quizzes are pedagogical — engage, don't spoil.
Quiz answers are included for your reference.
</agent-instructions>

# Server Routes

# Server Routes

In Next.js, an API route is a file called `route.ts` that exports named functions: `GET`, `POST`, `PUT`, `DELETE`. The HTTP method is the function name. The file lives inside `app/api/`, right next to your pages.

Nuxt encodes the HTTP method in the filename: `index.get.ts` handles GET requests, while `index.post.ts` handles POST. Server code lives in `server/api/`, separate from the Vue app. Nitro compiles those routes into the server output used by platforms such as Vercel.

You'll expose the 17 hot springs in the JSON file through an API route.

## Outcome

Create a server route that returns all hot springs from the JSON data file.

## Fast Track

1. Create `server/api/springs/index.get.ts` with a basic event handler
2. Import and return the springs JSON data
3. Test the endpoint at `/api/springs` in the browser

## Hands-on exercise 2.1

Build the first server route for the app: a GET endpoint that returns all hot springs.

**Requirements:**

1. Create `server/api/springs/index.get.ts`
2. Import the springs data from `server/data/springs.json`
3. Return the full array of springs
4. Verify the endpoint returns JSON at `/api/springs`

**Implementation hints:**

- `defineEventHandler` is the Nuxt equivalent of exporting a `GET` function in Next.js. It's auto-imported in the `server/` directory
- You can import JSON files directly with `import springs from "~/server/data/springs.json"`
- The `~/` alias resolves to the project root in server code, just like in app code
- Return a value and Nitro automatically serializes it as JSON with the correct content type

In Next.js, a basic API route looks like this:

```typescript
// app/api/springs/route.ts: Next.js version
import { NextResponse } from "next/server";
import springs from "@/data/springs.json";

export async function GET() {
  return NextResponse.json(springs);
}
```

Here's the Nuxt version:

```typescript title="server/api/springs/index.get.ts"
import type { Spring } from "~/types/spring";
import springs from "~/server/data/springs.json";

export default defineEventHandler((event) => {
  return springs as Spring[];
});
```

Return a value and Nitro serializes it, so this handler does not need a `NextResponse.json()` wrapper. The `event` parameter provides access to the request, query parameters, headers, and body when a route needs them.

The filename does real work here. `index.get.ts` tells Nitro three things: this handles requests to the root of the `/api/springs` path (`index`), it only responds to GET requests (`.get`), and it's a TypeScript file (`.ts`). If someone sends a POST to this endpoint, Nitro returns a 405 automatically.

Next.js can export several methods from one `route.ts` file. Nuxt uses one file per method, so the filename identifies the route's HTTP method.

\*\*Note: Server auto-imports\*\*

The `server/` directory has auto-imports separate from the `app/` directory. Nitro utilities such as `defineEventHandler`, `getQuery`, `getRouterParam`, and `createError` are available without imports. Vue utilities such as `ref` and `computed` are unavailable in server routes.

\*\*Warning: Don't mix up the aliases\*\*

In `server/` files, `~/` resolves to the project root. In `app/` files, `~/` resolves to the `app/` directory. This means `~/types/spring` works in both places, but for different reasons. If you try to import a Vue component from a server route, it will fail.

## Try It

Start the dev server and visit `http://localhost:3000/api/springs` in your browser. You should see a JSON array of 17 hot springs:

```json
[
  {
    "id": "breitenbush-hot-springs",
    "name": "Breitenbush Hot Springs",
    "description": "Tucked into the Willamette National Forest...",
    "location": {
      "region": "Pacific Northwest",
      "country": "US",
      "lat": 44.7896,
      "lng": -121.9815
    },
    "temperature": { "min": 98, "max": 112 },
    "type": "developed",
    "features": ["clothing-optional", "forest-setting", ...],
    "elevation": 2200,
    "imageUrl": "/images/springs/breitenbush-hot-springs.jpg"
  },
  ...
]
```

You can also test with curl:

```bash
curl http://localhost:3000/api/springs | head -c 200
```

If you see the JSON data, the route is working. If you get a 404, make sure the file is at `server/api/springs/index.get.ts`, not `app/api/springs/index.get.ts`. The server directory is a common source of misplaced files when you're coming from Next.js.

## Commit

```bash
git add -A && git commit -m "feat(api): add GET /api/springs server route"
```

## Done-When

- [ ] `server/api/springs/index.get.ts` exists and exports a default event handler
- [ ] Visiting `/api/springs` returns a JSON array of 17 hot springs
- [ ] You can explain how filename conventions (`.get.ts`, `.post.ts`) replace exported function names in Next.js

## Solution

```typescript title="server/api/springs/index.get.ts"
import type { Spring } from "~/types/spring";
import springs from "~/server/data/springs.json";

export default defineEventHandler((event) => {
  return springs as Spring[];
});
```


---

[Full course index](/academy/llms.txt) · [Sitemap](/academy/sitemap.md)
