API Server
Main Hono resource server guide.
Location: apps/api
Purpose
This application is the primary Resource Server for the starter kit. It is a lightweight
and high-performance Hono server responsible for serving business-logic API endpoints.
It is designed to be stateless and relies on the auth server for user authentication.
Key Features
- Lightweight & Fast: Built on Hono, a minimal and high-performance web framework.
- End-to-End Type Safety: Leverages Zod for environment validation and route schemas.
- Self-Documenting: Automatically generates interactive API documentation using
@hono/zod-openapiand Scalar. - Decoupled from Auth: Securely validates JWTs without having any direct access to user credentials or session data.
Project Structure
The server's code is organized logically within apps/api/src/:
index.ts: The main server entry point. It initializes the Hono app, registers middleware, sets up routes, and starts the server.env.ts: Uses@t3-oss/env-coreand Zod to validate and type-define all environment variables at startup. This prevents runtime errors caused by missing or invalid configuration.docs/: Contains all the logic for generating the OpenAPI specification and the Scalar UI.lib/: Home to shared utilities, including JWT validation middleware (jwt.ts) and standardized error responses (errors.ts).routes/: Each file in this directory defines a set of related API routes, keeping the codebase modular and easy to navigate.
Core Patterns
JWT Verification
The lib/jwt.ts file contains the jwtMiddleware. This is a Hono middleware that:
- Extracts the
Bearertoken from theAuthorizationheader. - Uses the
joselibrary to verify the token's signature against the public keys fetched from theauthserver's JWKS endpoint. - Checks the token's
issuerandaudienceto ensure it was issued by the correct authority for the correct purpose. - If valid, it attaches the token's payload to the request context (
c.set('jwtPayload', ...)), making it available to downstream route handlers.
This middleware is then applied to any route that requires authentication.
Self-Documenting Routes
Routes are defined using @hono/zod-openapi, which allows you to define the route's path, method,
input/output schemas, and documentation all in one place. For example, in routes/time.ts:
const timeRoute = createRoute({
method: "get",
path: "/time",
summary: "Current server time (protected)",
security: [{ bearerAuth: [] }], // Marks this as a protected route
responses: {
200: {
description: "OK",
content: { "application/json": { schema: TimeResponseSchema } },
},
},
});This definition not only creates the route but also provides all the necessary information for
scalar.ts to generate the beautiful, interactive API documentation.
Environment Variables
This server's environment variables are validated by src/env.ts. Refer to apps/api/.env.example for
a template.
PORT: The port the server will run on (e.g.,3010).RESOURCE_API_BASE_PATH: The base path for all API routes (e.g.,/api/v1/resource).JWKS_URL: The full URL to theauthserver's JWKS endpoint (e.g.,http://localhost:3001/api/v1/auth/jwks).JWT_ISSUER: The expectediss(issuer) claim in the JWT, which should be the base URL of theauthserver.JWT_AUDIENCE: The expectedaud(audience) claim in the JWT, which should be the base URL of this API server.OPENAPI_SERVER_URLS: A comma-separated list of base URLs for the OpenAPI documentation.
Future Evolution
The structure of this server is designed for easy extension.
- Adding New Routes: Simply create a new file in the
routes/directory, define your route schemas with Zod, and register it inindex.ts. - Scope-Based Authorization: The
lib/jwt.tsfile already includes arequireScopemiddleware. This is a starting point for a role-based access control (RBAC) system. By adding scopes (e.g.,read:time,write:data) to your JWTs in theauthserver, you can use this middleware to protect specific routes, ensuring that only users with the correct permissions can access them.