Skip to content

API Workflows

This page covers the development workflows for the HonoX backend API — running it locally, working with auth, and managing the OpenAPI spec.

Local development

bash
# Generate Prisma client first
pnpm --filter=@kubuli/database db:generate

# Start the API dev server
pnpm dev --filter=api

If a Laravel migration changed the shared schema, apply it from apps/admin, then sync Prisma with prisma db pull and rerun db:generate. Do not run prisma migrate from packages/database.

The API runs at http://localhost:3001.

Authentication model

The API implements two auth surfaces:

SurfacePurpose
/api/v1/auth/*Public JWT contract — registration, login, guest sessions, refresh
/api/auth/*Better Auth session and social provider workflows

Protected routes accept either a bearer JWT (Authorization: Bearer <token>) or a valid Better Auth session cookie. The shared auth middleware is in apps/api/app/lib/.

Key auth endpoints

EndpointMethodPurpose
/api/v1/auth/registerPOSTEmail registration
/api/v1/auth/loginPOSTEmail login → JWT
/api/v1/auth/guestPOSTAnonymous session token
/api/v1/auth/refreshPOSTRotate JWT
/api/v1/auth/phone/send-otpPOSTPhone OTP request
/api/v1/auth/phone/verify-otpPOSTPhone OTP verify → JWT
/api/v1/meGET / PATCHCurrent user profile

→ Full contracts: Authentication · Registration

Project structure

apps/api/
├── app/
│   ├── server.ts         # App entry point
│   ├── lib/              # Auth, validation, storage, utilities
│   └── routes/
│       ├── _404.ts
│       ├── _error.ts
│       └── api/
│           ├── index.ts      # /api/health
│           └── v1/
│               ├── admin/    # Admin-facing photo helpers
│               ├── app/      # App config and onboarding payloads
│               ├── auth/     # JWT auth endpoints
│               ├── culture/  # Stories and topics
│               ├── map/      # Map and POI endpoints
│               ├── me/       # Current-user profile and preferences
│               ├── tours/    # Tour generation and stop workflows
│               ├── users/    # Handle/profile helpers
│               ├── categories.ts
│               ├── favorites.ts
│               ├── feed.ts
│               ├── openapi.ts
│               ├── places.ts
│               ├── reviews.ts
│               └── search.ts
├── vite.config.ts
└── tsconfig.json

OpenAPI spec

The API ships a generated OpenAPI 3.1 spec via GET /api/v1/openapi. The TypeScript source is at apps/api/app/lib/openapi-spec.ts.

Export the spec as a static artifact:

bash
pnpm --filter=@kubuli/api openapi:export

This writes to apps/api/docs/openapi.json. Commit this file whenever you add or change endpoints — the docs site and any tooling that consumes the spec picks it up from here.

Testing

bash
# Run all API tests
pnpm test --filter=api

# Watch mode
pnpm test --filter=api -- --watch

# Run OpenAPI validation tests specifically
pnpm --filter=@kubuli/api test -- app/lib/openapi-spec.test.ts app/routes/api/v1/openapi.test.ts

Coverage reports live in apps/api/coverage/.

Adding a new endpoint

  1. Create the route file under app/routes/api/v1/ following the existing pattern.
  2. Add the endpoint to app/lib/openapi-spec.ts.
  3. Write a test in the adjacent *.test.ts file.
  4. Run pnpm --filter=@kubuli/api openapi:export to update the generated spec.
  5. Update apps/docs/api/ if this is a user-facing endpoint family.

Built with VitePress