Documentation
supastarter for Nuxtsupastarter for NuxtAPI

Define an API endpoint

To define a new API endpoint you can either create a new module or add a new endpoint to an existing module.

Create a new module

To create a new module you can create a new folder in the packages/api/modules folder. For example modules/posts. In this folder create a router.ts file and a procedures folder.

Then create a new .ts file for the endpoint in the procedures folder. For example modules/posts/procedures/published-posts.ts:

published-posts.ts
import { z } from "zod";
import { publicProcedure } from "../../../orpc/procedures";
import { db } from "@repo/database";

export const publishedPosts = publicProcedure
  .route({
    method: "GET",
    path: "/posts/published",
    tags: ["Posts"],
    summary: "List published posts",
  })
  .handler(async () => {
    const posts = await db.post.findMany({
      where: {
        published: true,
      },
    });

    return posts;
  });

Create the module router

Create a router.ts file in your module folder to export the endpoints:

modules/posts/router.ts
import { publishedPosts } from "./procedures/published-posts";

export const postsRouter = {
  publishedPosts,
};

Register module router

To make the module and its endpoints available in the API you need to register the router in the packages/api/orpc/router.ts file:

packages/api/orpc/router.ts
import { postsRouter } from "../modules/posts/router";

export const router = publicProcedure.router({
  // ...existing routers
  posts: postsRouter,
});

Using input validation

You can add input validation to your endpoints using Zod schemas:

modules/posts/procedures/get-post.ts
import { z } from "zod";
import { publicProcedure } from "../../../orpc/procedures";
import { db } from "@repo/database";

export const getPost = publicProcedure
  .route({
    method: "GET",
    path: "/posts/{id}",
    tags: ["Posts"],
    summary: "Get a post by ID",
  })
  .input(
    z.object({
      id: z.string(),
    }),
  )
  .handler(async ({ input: { id } }) => {
    const post = await db.post.findUnique({
      where: { id },
    });

    return post;
  });

Using middleware

You can chain middleware to add additional context to your procedures. For example, to add locale information:

import { localeMiddleware } from "../../../orpc/middleware/locale-middleware";
import { protectedProcedure } from "../../../orpc/procedures";

export const myEndpoint = protectedProcedure
  .use(localeMiddleware)
  .route({
    method: "POST",
    path: "/my-endpoint",
  })
  .handler(async ({ context: { user, locale } }) => {
    // locale is now available in the context
    return { user: user.name, locale };
  });