Askr documentation
Getting Started

Project Structure and Conventions

Where the composition root, routes, server boundary, and generated artifacts live in a scaffolded Askr project.

Example

Create a readable starter, run it unchanged, and make one small production build after the first route works.

npx @askrjs/cli@latest create startkit my-app
cd my-app
npm run dev
npm run build

Composition root

Askr apps have one obvious place where the app is assembled: the call to `createIsland`, `createSPA`, or `hydrateSPA` from `@askrjs/askr/boot`, which wires the route registry to a DOM root. Keep that call in one file rather than scattering startup configuration across the app.

Pages and routes

Where routes live depends on which template you started from: the `spa` template nests route files as `src/pages/**/_routes.tsx`, while `startkit` (the CLI's actual default template) and `ssr`/`ssg`/`full-stack` use a flatter `src/router.tsx` plus `src/routes/*.ts`. Match whichever shape your generated project already has rather than assuming one convention across templates. A page or route file should own URL-reachable shell and composition; domain logic, queries, and mutations belong in a feature folder (e.g. `src/features/<feature>/`), not inline in the route.

Server boundary

Code that talks to request data, auth context, or a database belongs behind the server-facing entrypoints — `@askrjs/askr/ssr`'s `renderRouteRequest` and friends, or route `loader`s — not inside components that also render in the browser. Keep transport and DTO mapping in an adapters layer (`src/adapters/`) so a page component never imports a generated API client directly.

Tests and generated artifacts

Keep tests next to the surface they cover rather than in a separate mirrored tree, matching whatever convention the starter template already uses. Treat `.askr/blueprint.json`, `.askr/builder-brief.md`, and any SSG `outputDir` as generated output — safe to regenerate, and worth committing only when you want a record of what the CLI decided.