The Packbase API lives in wildbasehq/packbase, under apps/server. It runs on Node.js and uWebSockets.js; Deno is not the server runtime.
Use the current Packbase REST API documentation for the published contract. Use server source and route checks to investigate implementation, drift, or a proposed change.
Runtime map
src/index.ts connects Prisma, runs boot-time data migrations, prepares resumable import work, starts the in-memory howl and gossip workers plus cleanup loops, compiles the explicit route registry, and then listens for HTTP traffic.
The central registry is src/routes/index.ts. Route modules are never discovered by scanning filenames at startup. Baozi is the server’s typed, sequential in-process event bus for hooks such as OpenGraph enrichment; it is code architecture, not a team chat tool.
| Path | Owns |
|---|---|
src/http | Typed route definitions, compilation, request pipeline, and response helpers. |
src/routes/<domain> | HTTP schemas and handlers grouped by product domain. |
src/models | Shared TypeBox response and domain shapes. |
src/lib | Domain services, jobs, storage, feeds, migrations, and integrations. |
src/server | Authentication, configuration, hooks, and runtime HTTP concerns. |
src/db | Prisma connection and boot-time data work. |
prisma/schema | Split Prisma schema files by domain. |
Add or change an endpoint
- Find the nearest domain under
src/routes. - Define
params,query,body, and response contracts with TypeBox. - Set
auth: "required"when the operation needs an authenticated user. - Keep domain rules in an appropriate helper when the handler would otherwise become the model.
- Return ordinary JSON or the explicit
json,text,bytes, oremptyresponse helper. - Add the module to the domain’s
routes.ts. Add a new domain registry tosrc/routes/index.tsonly once. - Run route compilation, types, and focused tests.
pnpm --dir apps/server routes:check
pnpm --dir apps/server routes:list
pnpm --dir apps/server check-types
pnpm --dir apps/server testWhen the intentional public path sets changes, run pnpm --dir apps/server routes:snapshot and review the src/routes/contract.json diff. Do not update the snapshot merely to silence an unexpected route change.
Authentication and authorisation
The request pipeline resolves Clerk-backed credentials before a protected handler. Authentication answers who the caller is; route and domain code must still decide what that caller may do. Enforce staff, content-moderator, pack permission, ownership, and object-scope rules on the server even when the web client hides the control.
Multipart protected routes authenticate before accepting upload bytes. Keep that ordering when adding streaming work.
Data and assets
PostgreSQL is accessed through Prisma 7 and the PostgreSQL adapter. Client construction stays side-effect free, so static route checks and unit tests can import handlers without a database; connectPrisma() is the real startup boundary.
The generated profile-history schema, PostgreSQL triggers and tables, and public route have been retired. Profile routes expose the current profile state; do not build new work against the removed history schema or endpoint.
Assets use S3-compatible storage. Large uploads stream through multipart upload rather than buffering the entire body. Video processing additionally depends on FFmpeg and is deliberately concurrency-limited.
Use the database procedure before changing schema or data, and the background-work guide before changing asynchronous side effects.
Environment and startup
DATABASE_URL, PROFILES_CDN_URL_PREFIX, BSKY_IDENTIFIER, and BSKY_APP_PASSWORD are current hard startup requirements. The profile CDN prefix is read by boot migration 7, and the Bluesky login is currently awaited unconditionally. DIRECT_URL is the Prisma command datasource rather than an ordinary runtime dependency. Clerk and S3-compatible storage credentials are required by the authentication and asset paths that use them.
The checked-in .env.example is a partial list of names, not proof that every blank or comment matches current startup behaviour. In particular, its suggestion that blank Bluesky values may be ignored does not match current startup.
Do not copy a production .env. Use isolated development services and record the exact missing variable or first failing subsystem when local startup is incomplete.