First Application
Scaffold a project, register a route, add a piece of state, and produce a real production build.
Example
import { state } from '@askrjs/askr';
import { createRouteRegistry, route } from '@askrjs/askr/router';
function HomePage() {
const [count, setCount] = state(0);
return <button onClick={() => setCount((value) => value + 1)}>Count: {count()}</button>;
}
export const registry = createRouteRegistry(() => route('/', HomePage));Create the project
Run `askr create spa my-app` (or another template) and `cd my-app`. Open the generated route registry — `src/pages/**/_routes.tsx` for the `spa` template, or `src/router.tsx` plus `src/routes/*.ts` for `startkit`, `ssr`, `ssg`, and `full-stack` — to see how the starter route is already wired up with `route()`.
Register a route
Routes are declared with `route(path, Component, options?)` inside a `createRouteRegistry(() => { ... })` callback, which returns the registry your application boots from. Add a new entry — `route('/about', () => <About />)` — inside the existing callback, then confirm the exported registry you pass to `createSPA` picks it up.
Add state
Call `state(initialValue)` inside a component to get a `[getter, setter]` pair — read the current value by calling the getter as a function, and update it by calling the setter, e.g. `setCount((value) => value + 1)`. State reads are tracked automatically wherever they're called, so a component re-renders when the state it read changes.
Build the application
Run `npm run build` from the generated project; the SPA template's build produces a client bundle only, while `ssr` and `full-stack` both also build a server bundle to run with Node — full-stack isn't client-only the way SPA is. SSG can drive `createStaticGen()` to render every route to HTML in `outputDir`. Check the build output against the application mode you picked — an SSG build should produce static files per route, while an SSR or full-stack build produces a server bundle you run with Node.