N
Nuxt5mo ago
Sovereign

API doesnt work

server/api/auth/register.post.ts
import { User } from "~/models/user.model";
import rateLimit from "../../../server/middleware/rateLimit";

export default defineEventHandler(async (event) => {
await rateLimit(event);

const body = await readBody(event);
const { username, email, password } = body;

if (!username || !email || !password) {
throw createError({ statusCode: 400, statusMessage: "Missing fields" });
}

if (await User.exists({ $or: [{ username }, { email }] })) {
throw createError({
statusCode: 409,
statusMessage: "Username or email already exists",
});
}

const user = await User.create({
username,
email,
password,
role: "user",
});

return {
status: "ok",
user: { id: user._id, username: user.username, email: user.email },
};
});
import { User } from "~/models/user.model";
import rateLimit from "../../../server/middleware/rateLimit";

export default defineEventHandler(async (event) => {
await rateLimit(event);

const body = await readBody(event);
const { username, email, password } = body;

if (!username || !email || !password) {
throw createError({ statusCode: 400, statusMessage: "Missing fields" });
}

if (await User.exists({ $or: [{ username }, { email }] })) {
throw createError({
statusCode: 409,
statusMessage: "Username or email already exists",
});
}

const user = await User.create({
username,
email,
password,
role: "user",
});

return {
status: "ok",
user: { id: user._id, username: user.username, email: user.email },
};
});
I made a request to it and I just get index page
curl -X POST http://localhost:3000/api/auth/register \
-H "Content-Type: application/json" \
-d '{"username":"sovereign","email":"sovrign@proton.me","password":"secret"}'
curl -X POST http://localhost:3000/api/auth/register \
-H "Content-Type: application/json" \
-d '{"username":"sovereign","email":"sovrign@proton.me","password":"secret"}'
I followed https://nuxt.com/docs/guide/directory-structure/server and couldnt understand what I am doing wrong?
Nuxt
server · Nuxt Directory Structure v3
The server/ directory is used to register API and server handlers to your application.
14 Replies
kapa.ai
kapa.ai5mo ago
Hi @Sovereign. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Based on your code and the request you made, your API route should work as expected if everything is set up correctly in your Nuxt 3 project. Here are some things to check, based on the official Nuxt documentation and similar issues: 1. File Location and Naming
Make sure your file is located at server/api/auth/register.post.ts. Nuxt automatically registers files in the server/api directory as API endpoints, and the .post.ts suffix ensures it only handles POST requests. The route should be available at /api/auth/register for POST requests, as you are doing in your curl command.
See: Directory structure and API route conventions 2. Returning Index Page Instead of API Response
If you are getting the index page (your Nuxt app) instead of the API response, it usually means the route is not being matched. This can happen if: - The file is not in the correct directory or is misnamed. - There is a build or HMR issue—try restarting your dev server. - There is a misconfiguration in your nuxt.config.ts that interferes with server routes. 3. Middleware Import
You are importing rateLimit from ../../../server/middleware/rateLimit. Make sure this middleware is exporting a function compatible with defineEventHandler and does not return a response itself (middleware should only modify the event or throw errors, not return data)
See: Server middleware usage 4. Model Import
Your import import { User } from "~/models/user.model"; assumes you have a working Mongoose or ORM setup. Make sure this is correctly initialized and available in the server context. 5. Testing the Endpoint
Try accessing a simple test endpoint to confirm your API routes are working. For example, create server/api/test.post.ts:
export default defineEventHandler(async (event) => {
return { status: "ok" }
})

export default defineEventHandler(async (event) => {
return { status: "ok" }
})

Then run:
curl -X POST <http://localhost:3000/api/test>

curl -X POST <http://localhost:3000/api/test>

If this works, the issue is likely with your model or middleware. 6. Error Handling
If there is an error in your handler (e.g., model import fails), Nuxt should return a 500 error, not the index page. If you see the index page, it strongly suggests the route is not being matched. Summary:
Double-check your file location and naming, restart your dev server, and test with a minimal endpoint. If the minimal endpoint works, incrementally add your logic back to isolate the problem. If you still get the index page, your route is not being registered—this is almost always a directory or filename issue in Nuxt 3 projects.
See: Nuxt server directory and API route registration If you need to debug further, try removing the middleware and model imports to see if the basic handler works, then add them back one at a time. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5mo ago
<@1322335282309107733> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Sovereign
SovereignOP5mo ago
@kapa.ai That is the thing I tried using the hello world API example and it also just outputted index page.
kapa.ai
kapa.ai5mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- If even the basic "hello world" API example from the Nuxt documentation just outputs the index page, this strongly suggests that your API routes are not being registered at all. According to the official Nuxt docs, files placed in server/api/ should automatically be available as API endpoints (e.g., server/api/hello.ts should be accessible at /api/helloserver directory usage. Common causes for this issue: 1. Missing or Misnamed server Directory
The directory must be named exactly server (not api, _server, etc.), and your API files should be inside server/api/. 2. Incorrect File Extensions or Structure
The files should have a supported extension (e.g., .ts or .js). For example:
server/api/hello.ts

server/api/hello.ts

with content:
export default defineEventHandler(() => {
return { hello: 'world' }
})

export default defineEventHandler(() => {
return { hello: 'world' }
})

This should be accessible at <http://localhost:3000/api/hello.> 3. Pages Directory Disabled
If you are only using app.vue and not the pages directory, make sure you have not disabled the server engine or API routes in your nuxt.config.ts. By default, Nuxt should include the server engine unless explicitly disabled pages directory docs. 4. Custom Server Middleware or Configuration
If you have custom server middleware or are using a custom server (like Express), it may override or interfere with Nuxt's built-in API routing. The knowledge sources show that using Express as middleware requires careful proxying and configuration, otherwise Nuxt's API routes may not be available Node.js with Nuxt.js. 5. Dev Server Needs Restart
Sometimes, changes to the server/ directory require a full restart of the Nuxt dev server. What to try next: - Double-check your directory and file structure. - Remove any custom server middleware or configuration from nuxt.config.ts to isolate the issue. - Restart your Nuxt dev server after making changes. - Try the minimal example from the docs in a clean project:
server/api/hello.ts

server/api/hello.ts

export default defineEventHandler(() => {
return { hello: 'world' }
})

export default defineEventHandler(() => {
return { hello: 'world' }
})

Then access <http://localhost:3000/api/hello.> If you still only get the index page, there may be a fundamental misconfiguration or conflict in your project setup. The knowledge sources do not provide further troubleshooting steps for this specific scenario, but following the above should resolve the issue in a standard Nuxt 3 project server directory usage. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5mo ago
<@1322335282309107733> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Sovereign
SovereignOP5mo ago
Yeah, I also used your example, @kapa.ai, I still just get
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Welcome to Nuxt!</title>
<style>
@property --gradient-angle {
syntax: "<angle>";
inherits: false;
initial-value: 180deg
}

@keyframes gradient-rotate {
0% {
--gradient-angle: 0deg
}

to {
--gradient-angle: 360deg
}
}

*,
:after,
:before {
border-color: var(--un-default-border-color, #e5e7eb);
border-style: solid;
border-width: 0;
box-sizing: border-box
}

:after,
:before {
--un-content: ""
}

html {
line-height: 1.5;
-webkit-text-size-adjust: 100%;
font-family: ui-sans-serif, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
font-feature-settings: normal;
font-variation-settings: normal;
-moz-tab-size: 4;
tab-size: 4;
-webkit-tap-highlight-color: transparent
}

body {
line-height: inherit;
margin: 0
}

h1,
h2,
h3 {
font-size: inherit;
font-weight: inherit
}

a {
color: inherit;
text-decoration: inherit
}

h1,
h2,
h3,
p,
ul {
margin: 0
}
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Welcome to Nuxt!</title>
<style>
@property --gradient-angle {
syntax: "<angle>";
inherits: false;
initial-value: 180deg
}

@keyframes gradient-rotate {
0% {
--gradient-angle: 0deg
}

to {
--gradient-angle: 360deg
}
}

*,
:after,
:before {
border-color: var(--un-default-border-color, #e5e7eb);
border-style: solid;
border-width: 0;
box-sizing: border-box
}

:after,
:before {
--un-content: ""
}

html {
line-height: 1.5;
-webkit-text-size-adjust: 100%;
font-family: ui-sans-serif, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
font-feature-settings: normal;
font-variation-settings: normal;
-moz-tab-size: 4;
tab-size: 4;
-webkit-tap-highlight-color: transparent
}

body {
line-height: inherit;
margin: 0
}

h1,
h2,
h3 {
font-size: inherit;
font-weight: inherit
}

a {
color: inherit;
text-decoration: inherit
}

h1,
h2,
h3,
p,
ul {
margin: 0
}
kapa.ai
kapa.ai5mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- If you are getting the Nuxt index page (the default HTML output) when trying to access an API route like /api/hello, this means the API route is not being registered or matched by Nuxt. According to the official documentation, files placed in server/api/ should automatically be available as API endpoints, and you should not receive the index page for those requests server directory usage. Based on the knowledge sources, here are the most likely causes: 1. Directory or File Naming Issue
The file must be located at server/api/hello.ts (or similar), and the directory must be named exactly server (not api, _server, etc.). The file extension should be .ts or .js. 2. Custom Server Middleware or Configuration
If you have configured custom server middleware (such as Express) in your nuxt.config.ts, it can override or interfere with Nuxt's built-in API routing. The knowledge sources show that using Express as middleware requires careful proxying and configuration, otherwise Nuxt's API routes may not be available How to use Node.js with Nuxt.js? Part 1. 3. Dev Server Needs Restart
Sometimes, changes to the server/ directory require a full restart of the Nuxt dev server for the routes to be picked up. 4. Static Site Generation (SSG) or Prerendering
If you are using nuxt generate or static hosting, server endpoints will not be included in your output folder, and API routes will not work Universal Rendering. What you should do: - Double-check your directory and file structure. - Remove any custom server middleware or configuration from nuxt.config.ts to isolate the issue. - Restart your Nuxt dev server after making changes. - Make sure you are running in development mode or using nuxt build (not nuxt generate). - Try the minimal example from the docs in a clean project:
server/api/hello.ts

server/api/hello.ts

export default defineEventHandler(() => {
return { hello: 'world' }
})

export default defineEventHandler(() => {
return { hello: 'world' }
})

Then access <http://localhost:3000/api/hello.> If you still only get the index page, the knowledge sources do not provide further troubleshooting steps for this specific scenario, but following the above should resolve the issue in a standard Nuxt 3 project server directory usage. If you are using custom server middleware, you may need to proxy API requests as described in the knowledge sources. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5mo ago
<@1322335282309107733> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Sovereign
SovereignOP5mo ago
@kapa.ai I made my source folder ~/src should I put server in there instead?
kapa.ai
kapa.ai5mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- If you have set your srcDir to ~/src, by default, the server directory should also be placed inside src/ (i.e., src/server/). This is confirmed by the Nuxt configuration documentation, which states:
Define the server directory of your Nuxt application, where Nitro routes, middleware and plugins are kept. If a relative path is specified, it will be relative to your rootDir.
>
- Default: "/<srcDir>/server"
>
Nuxt Config: serverDir
So, with your setup:
src/
server/
api/
hello.ts
pages/
app.vue
nuxt.config.ts
src/
server/
api/
hello.ts
pages/
app.vue
nuxt.config.ts
This is the correct structure if you have srcDir: 'src/' in your nuxt.config.ts. Note:
If you are using the new v4 directory structure (with future.compatibilityVersion: 4), the default for serverDir changes to <rootDir>/server (i.e., at the project root, not inside src/). You can override this by explicitly setting serverDir in your config if needed Upgrade Guide: New Directory Structure. If you are unsure which structure you are using, check your Nuxt version and configuration. If you are on v3 and have set srcDir, put server inside src/. If you are on v4 or using the new structure, server should be at the root unless configured otherwise. If you still have issues, double-check your srcDir and serverDir settings in nuxt.config.ts to ensure they match your folder structure. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5mo ago
<@1322335282309107733> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Sovereign
SovereignOP5mo ago
@kapa.ai Well, you can say I was an idiot and forgot to put it in source directory
kapa.ai
kapa.ai5mo ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- No worries—this is a common mistake! According to the Nuxt documentation, if you set srcDir to src/ in your nuxt.config.ts, then your server directory (and all API routes) must also be inside src/ (i.e., src/server/api/hello.ts). By default, Nuxt looks for the server directory inside your srcDir unless you are using the new v4 directory structure, which places server at the project root Nuxt Config: serverDir Nuxt Config: srcDir. So, moving your server directory into your source directory should resolve the issue! ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5mo ago
<@1322335282309107733> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?