QUESTPIE
Build Your BackendArchitecture

File Convention

How QUESTPIE discovers your files and wires them into the runtime — naming rules, layouts, and discovery mechanics.

QUESTPIE uses your file system as the source of truth. Drop a file in the right directory, run codegen, and it's part of your app. No manual registration.

Directory Categories

Each directory maps to a category of entity:

DirectoryEntityExport StyleKey Derivation
collections/CollectionsDefault or namedFilename → camelCase
globals/GlobalsDefault or namedFilename → camelCase
routes/RoutesDefaultFilename → camelCase/slash path
jobs/JobsDefaultFilename → camelCase
routes/ (raw)RoutesDefaultFilename → slash-separated path
services/ServicesDefaultFilename → camelCase
emails/Email templatesDefaultFilename → camelCase
blocks/BlocksNamed exportsFactory arg → export name
messages/i18n messagesDefaultFilename → locale key
migrations/DB migrationsDefaultArray (ordered)
seeds/DB seedsDefaultArray (ordered)

Name derivation

Filenames are converted from kebab-case to camelCase:

blog-posts.ts      → blogPosts
create-booking.ts  → createBooking
site-settings.ts   → siteSettings

Single-File Conventions

Some configs are single files, not directories:

FileFactoryPurpose
questpie.config.tsruntimeConfig({...})DB, plugins, adapters
modules.tsexport default [...]Module dependencies
auth.tssatisfies AuthConfigAuth configuration
locale.tslocale({...})Content locales
hooks.tsexport default { collections, globals }Global lifecycle hooks (applied across all entities)
access.tsexport default { read, create, update, delete }Default access rules for all entities
config/app.tsexport default appConfig({...})App-level config (context, locale, tenant scoping)
fields.tsexport default { ...customFields }Custom field type definitions
sidebar.tssidebar({...})Admin sidebar
dashboard.tsdashboard({...})Admin dashboard
branding.tsbranding({...})Admin branding
admin-locale.tsadminLocale({...})Admin UI locale

Layouts

By-Type (default)

Group files by entity type:

src/questpie/server/
├── collections/
│   ├── posts.ts
│   ├── categories.ts
│   └── comments.ts
├── routes/
│   ├── create-booking.ts
│   └── get-stats.ts
├── jobs/
│   └── send-email.ts
└── services/
    └── blog.ts

By-Feature

Group files by domain:

src/questpie/server/
├── features/
│   ├── blog/
│   │   ├── collections/
│   │   │   └── posts.ts
│   │   ├── routes/
│   │   │   └── publish.ts
│   │   └── jobs/
│   │       └── notify-subscribers.ts
│   └── booking/
│       ├── collections/
│       │   └── appointments.ts
│       └── routes/
│           └── create-booking.ts

Mixed

Both layouts can coexist. Codegen scans all configured paths.

Nested Namespacing

Routes support nested directories:

routes/
├── booking/
│   ├── create.ts    → client.routes.booking.create()
│   └── cancel.ts    → client.routes.booking.cancel()
├── admin/
│   └── stats.ts     → client.routes.admin.stats()
└── get-barbers.ts   → client.routes.getBarbers()

Discovery Process

  1. Scan — Codegen walks the configured directories
  2. Match — Files matching the category pattern are picked up
  3. Import — Each file is imported and its exports are read
  4. Key derivation — Factory string arg → export name → filename (camelCase)
  5. Merge — Project entities + module entities are merged
  6. Emit — Generated types and runtime wiring in .generated/

The #questpie Import

Collection and global files use #questpie as an import alias:

import { collection } from "#questpie/factories";

This resolves to the generated app context, giving the builders access to field types and relation targets for autocompletion. It's configured via TypeScript path mapping.

On this page