Basilic
Development

OpenAPI Generation

TypeBox routes → OpenAPI → @repo/core. React Query hooks in @repo/react are handwritten.

TypeBox on Fastify routes is the source of truth. Generate OpenAPI, then the @repo/core client. Add TanStack Query hooks in @repo/react by hand when the UI needs them. There is no packages/react/src/gen/ and no Hey API React plugin in this repo.

Commands

pnpm generate                              # openapi.json + packages/core/src/gen (when routes change)
pnpm --filter @repo/api generate:openapi   # apps/api/openapi/openapi.json only
pnpm --filter @repo/core generate          # packages/core/src/gen/

@repo/web, @repo/docu, and package CI builds use committed openapi.json and src/gen/. Regenerate after route changes; api-e2e runs pnpm generate && git diff --exit-code on API PRs. The API Vercel build still runs generate:openapi inside @repo/api build.

Spec also served at /reference/openapi.json; Scalar UI at /reference. Config: packages/core/openapi-ts.config.ts.

Vercel / production builds

generate:openapi boots the Fastify app to scan routes. When env vars are missing (e.g. @repo/web on Vercel with NODE_ENV=production), the script stubs production-only values before import: ALLOWED_ORIGINS, APP_NAME, secrets, and PGLITE. Runtime API CORS rules in apps/api/src/lib/env.ts are unchanged—stubs apply only to codegen.

New endpoint

  1. Add the route + TypeBox schema in apps/api/src/routes/ (one file per endpoint).
  2. pnpm --filter @repo/api generate:openapi
  3. pnpm --filter @repo/core generate
  4. If the UI needs a hook, add it under packages/react/src/hooks/ and export from packages/react/src/index.ts.
import { createClient } from '@repo/core'
import { useUser } from '@repo/react'

const client = createClient({
  baseUrl: process.env.NEXT_PUBLIC_API_URL!,
  getAuthToken: async () => session?.token,
  getRefreshToken: async () => session?.refreshToken,
  onTokensRefreshed: async ({ token, refreshToken }) => { /* persist */ },
})

const user = await client.auth.session.user()
const { data } = useUser()

See API Architecture and Package Conventions.

On this page