Getting started with Nuxt 3 Server Routes

Building an API with Server Routes (Basic)

Getting Started with Nuxt 3 Server Routes

Building an API with Server Routes (Basic)

The server/ directory allows Nuxt create powerful backend APIs using the modern Nitro Engine. Due to the power of the auto-import feature Nuxt is designed to scan files in the following api/, routes/, middleware/ and plugins/ - to register APIs and server handlers.

Files in these folders accept an event as their first argument which comes from the H3 Utilities. This can be defined in a function that handles the event - defineEventHandler() or eventHandler().

Creating a Server Route

In this tutorial we will break our API based on the folder structure for the server/ directory.

  • server/

    • api/

    • routes/

    • middleware/

    • plugins/

Creating a Server Route in the api/ folder

The files in the api/ folder are prefixed with the api/ in the route path. For example, if we have a file called api/todo it will be available at http://localhost:3000/api/todos.

export default defineEventHandler(async (event) => {
    // @ts-ignore
    const _recipes: RecipeTodo = sampleData
    const status = getResponseStatus(event)
    return {
        status,
        message: "Success",
        data: _recipes
    }
})

With this API route in place, we can access it on our pages and components using the data-fetching method useFetch.

<script setup lang="ts">
const _recipeTodo = await useFetch('api/todos')
</script>

Let us rework this example and make it more readable and reusable. We can create a new directory in the api/ folder called todos/ and create a file called index.ts in it. This will allow us to create multiple routes for the todos API.

export default defineEventHandler(async (event) => {
    // @ts-ignore
    const _recipes: RecipeTodo = sampleData
    const status = getResponseStatus(event)
    return {
        status,
        message: "Success",
        data: _recipes
    }
})

With this, we can now create a new file called createTodo.post.ts in the todos/ folder. This will allow us to create a new route for creating a todo. (Note: This is similar to how pages are created.)

Note: The file name can be suffixed with an HTTP method.

export default defineEventHandler(async (event) => {
    // Handle request with body
    const body = await readBody(event);

    const { title, description }: Partial<RecipeTodo> = body;

    // @ts-ignore
    const _recipes: RecipeTodo = {
        id: uuidv4(),
        title: title,
        description: description,
    }

    const status = getResponseStatus(event)
    sampleData.push(_recipes)
    return {
        status,
        message: "Success",
        data: sampleData
    }
});

Note: The readBody function is a helper function that allows us to read the body of the request. This is similar to the req.body in Express. This function (like so many others - getResponseStatus()) are available from the H3 utilities.

Creating a Server Route in the routes/ folder

Similar to the api/ folder, the files in the routes/ create the API route path without api/ prefix. For example, if we have a file called routes/todo it will be available at http://localhost:3000/routes/todos.

export default defineEventHandler(async (event) => {
    // @ts-ignore
    const _recipes: RecipeTodo = sampleData
    const status = getResponseStatus(event)
    return {
        status,
        message: "Success",
        data: _recipes
    }
})

Creating a Server Middleware

Files in the middleware/ will be automatically registered as a middleware in Nuxt. Middleware handlers will be called before the API handlers.

Note: Middleware handlers should not return a response. They should only inspect or extend the request or give an error.

export default defineEventHandler((event) => {
  console.log('New request: ' + getRequestURL(event))
})

Another example:


export default defineEventHandler(async (event) => {
    try {
        // const data = await $fetch('https://jsonplaceholder.typicode.com/todos')
        // console.log(data)
        event.context.data = sampleData.length
    } catch (e) {
        console.error(e)
        sendError(event, createError({
            statusCode: 401,
            statusMessage: "Unauthorized",
        }))
    }

});

Creating a Server Plugin

Files in the plugins/ will be automatically registered as a plugin in Nuxt. Plugins are useful for extending the functionality of the server.

export default defineEventHandler((event) => {
  console.log('New request: ' + getRequestURL(event))
})

Conclusion

In this tutorial, we explored the server/ directory and how to use it to create server routes (APIs). Nuxt provides a full-stack experience that provides a backend and a frontend in one package.