Fullstack API runtime
apiLoaderPlugin prod vs dev paths OpenAPI RFC catalog Link headers cold bundles.
Fullstack API runtime
When config.mode !== 'frontend', createManicServer (packages/manic/src/server/index.ts) mounts the filesystem API tree via apiLoaderPlugin.
Loader roots
const { app: apiApp, openApiSpec } = await apiLoaderPlugin(
prod ? `${dist}/api` : 'app/api'
);| Environment | Directory scanned | Notes |
|---|---|---|
| Production | <dist>/api prebuilt *.js outputs | Matches manic build per-entry bundles (Bundler transform) |
| Development | app/api TypeScript sources | Same globs as plugin (.ts, .tsx, .js) |
Mounted endpoints
| Route | Responsibility |
|---|---|
/api, /api/* | Forward to apiApp.fetch (Hono basePath('/api')) |
/openapi.json | Serialized openApiSpec from loader |
/.well-known/api-catalog | RFC 9727 linkset pointing at /openapi.json |
Built-in Link headers advertise openapi + api-catalog + MCP discovery URI (Server runtime).
Why this stays “fast” at deploy time
- Per-route bundles — serverless adapters ship only the JS for each
app/api/**/index.tsentry (Performance model). - No monolithic API graph — avoids importing every handler into one cold-start blob unless your code statically pulls them together.
- Prod scans compiled JS — loader skips TS compilation overhead at runtime.
Frontend mode contrast
mode: 'frontend' skips apiLoaderPlugin entirely — pure SPA Bun.serve surface (Server runtime).
See also
- Plugin loaders
- Discovery engine — note
manic buildusesindex.tsonly while dev loader acceptstsx - Caveats