Source: https://www.hype-stack.dev/docs/backend/routing

# How to Add Routes

HTTP routes live in `src/routes/<domain>/index.ts`. Each file exports a Hono route chain that gets mounted in
`src/routes/index.ts`.

## Anatomy of a route file

```ts
import { createProjectSchema } from "@backend/features/projects/db/mutations/create-project.mutation";
import { createProject } from "@backend/features/projects/modules/create-project";
import { ApplicationError, ApplicationErrorCode } from "@backend/middleware/error";
import { hasAccess } from "@backend/middleware/permissions/has-access";
import { validate } from "@backend/middleware/validation/validate";
import { getAuthenticatedApp } from "@backend/utils/auth/auth-hono";

type ProjectMutationResponse = { projectId: string };

export const projectRoutes = getAuthenticatedApp()
  .get("/", hasAccess({ action: "read", subject: "project" }), async (ctx) => {
    const { organizationId } = ctx.var;
    const response = await getProjectsList({ organizationId });
    return ctx.json(response);
  })
  .post("/", hasAccess({ action: "write", subject: "project" }), validate("json", createProjectSchema), async (ctx) => {
    const body = ctx.req.valid("json");
    const { projectId } = await createProject({ data: body });
    return ctx.json<ProjectMutationResponse>({ projectId });
  });
```

## Registering routes

Mount routes in `src/routes/index.ts`:

```ts
import { projectRoutes } from "./projects";

export const registerRoutes = (app: Hono) => {
  return app.route("/projects", projectRoutes);
  // ... other routes
};
```

The return type of `registerRoutes` is what generates the `ApiRoutesSdk` type for the frontend. Adding a route here
automatically exposes it on the frontend SDK.

## Validation is mandatory

Every route that accepts input must use the `validate()` middleware:

```ts
// Body validation
validate("json", createProjectSchema);

// Query param validation
validate("query", filtersSchema);
```

Read validated data with `ctx.req.valid("json")` or `ctx.req.valid("query")`. Never use `ctx.req.json()` directly, since
it bypasses validation and breaks the type bridge.

## Authentication and permissions

- `getAuthenticatedApp()` creates a route group that requires authentication
- `hasAccess({ action, subject })` checks user permissions before the handler runs
- For public routes, use a plain `new Hono()` instead

## Adding a new route

1. Create `src/routes/<domain>/index.ts`
2. Define routes using `getAuthenticatedApp()` with `validate()` middleware
3. Import and register in `src/routes/index.ts` with `app.route("/prefix", routes)`
4. The frontend SDK picks up the new endpoint automatically
