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 starter, start the development server, and verify the production build.

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 loaders — 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.