Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions public/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Build an Askr application

Use this guide when creating or changing an application built with Askr. Keep
the application legible: routes, state, data, server boundaries, and cleanup
must have an owner a reader can identify from the code.

## Start with the installed contract

The installed `@askrjs/*` packages are authoritative for exports, props,
types, runtime behavior, and errors. Examples are teaching aids and may lag
behind a published package. When they disagree, follow the installed package
declarations and report the stale example.

Before using a prop, export, or CLI flag, verify it in the installed package.
Existence is not endorsement: read its declaration comments and canonical
documentation too. Do not choose an API marked legacy, deprecated, limited,
or experimental unless the task specifically calls for that status and
accepts its constraints. Do not fill gaps with assumptions from React,
Next.js, Solid, or another framework.

## Structure the application

Keep the route tree visible under `src/pages`:

- `src/pages/_routes.tsx` owns the root route registry and composes route
groups.
- `src/pages/_layout.tsx` owns root providers and the application-wide shell.
- A nested route group owns its adjacent `_routes.tsx` and `_layout.tsx`.
- Files do not become routes merely because they are under `pages`.

Preserve this composition direction:

```text
pages -> features -> components -> Askr primitives
```

Pages connect routes to features. Features own coherent application
capabilities and their visible states. Components are reusable application UI
with explicit props. Components do not import features, and features do not
import pages.

When a feature uses external or mutable data, preserve this second direction:

```text
features -> queries and mutations -> services -> adapters
```

Queries and mutations call application services; services map raw adapter
results into application models. Do not make reusable components fetch
application data or make pages call transport clients directly.

## Use the building blocks

Import themed application components from `@askrjs/themes/components`.
`Block` is the general-purpose layout primitive. Use `Container` for content
width and page gutters, `Text` for themed copy, and `Grid` for explicit rows
and columns. Compose semantic page structure from published components such as
`Header`, `Main`, `Section`, `PageHeader`, and `Footer`.

Use the exact props and token values accepted by the installed declarations.
For example, use `paddingY`, not an invented `py` shorthand. Use themed
components when the shared theme owns appearance and headless `@askrjs/ui`
primitives when the application must own it.

## Load the composable skill

For an end-to-end application workflow, read
[`/skills/build-askr-app/SKILL.md`](https://askrjs.com/skills/build-askr-app/SKILL.md).
It composes these capability skills:

- [`/skills/project-structures/SKILL.md`](https://askrjs.com/skills/project-structures/SKILL.md)
for pages, features, components, adapters, queries, mutations, and ownership;
- [`/skills/routes/SKILL.md`](https://askrjs.com/skills/routes/SKILL.md) for
registries, layouts, URL state, data loading, access, navigation, metadata,
and fallbacks;
- [`/skills/themes/SKILL.md`](https://askrjs.com/skills/themes/SKILL.md) for
building blocks, tokens, visual customization, and rendered styles.
- [`/skills/control-flows/SKILL.md`](https://askrjs.com/skills/control-flows/SKILL.md)
for conditional rendering, keyed collections, row reactivity, and retained
render order.
- [`/skills/icons/SKILL.md`](https://askrjs.com/skills/icons/SKILL.md) for icon
and logo selection, imports, accessibility, sizing, and themed composition.
- [`/skills/queries-and-mutations/SKILL.md`](https://askrjs.com/skills/queries-and-mutations/SKILL.md)
for cache identity, query consistency, writes, invalidation, prefetch, and
hydration.
- [`/skills/i18n/SKILL.md`](https://askrjs.com/skills/i18n/SKILL.md) for typed
catalogs, locale ownership, direction, formatting, and hydration.
- [`/skills/charts/SKILL.md`](https://askrjs.com/skills/charts/SKILL.md) for
typed plot composition, data rules, interaction, accessibility, and export.

Load only the references needed by the task. A five-page marketing SSG, an
authenticated SPA, and a server-rendered application compose these capabilities
differently; they are not separate outcome-specific skills.

## Verify the result

Run the repository-owned format, lint, type, analysis, test, and production
build gates appropriate to the application. Inspect SSR or SSG output before
hydration and exercise the hydrated browser at narrow and desktop widths.
Verify loading, empty, failure, cancellation, retry, and unauthorized states
where they exist. A pushed commit is not proof that a deployment succeeded.

## Canonical references

- [Getting started](https://askrjs.com/docs/getting-started/index.md)
- [Project structure](https://askrjs.com/docs/getting-started/project-structure/index.md)
- [Routing and data](https://askrjs.com/docs/routing/index.md)
- [Server and APIs](https://askrjs.com/docs/server/index.md)
- [UI and components](https://askrjs.com/docs/components/index.md)
- [Layout primitives and exact props](https://askrjs.com/docs/components/application-layout/index.md)
- [Production readiness](https://askrjs.com/docs/guides/production-readiness/index.md)
- [Generated API reference](https://askrjs.com/docs/reference/api/index.md)

Use [llms.txt](https://askrjs.com/llms.txt) for documentation discovery and
[llms-full.txt](https://askrjs.com/llms-full.txt) for the complete generated
documentation corpus.
10 changes: 10 additions & 0 deletions public/llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ Use the documentation links below as the primary source for Askr APIs and usage.

## Start here

- [Agent building guide](https://askrjs.com/AGENTS.md): Concise architectural rules and the entry point for agents building with Askr.
- [Build an Askr app skill](https://askrjs.com/skills/build-askr-app/SKILL.md): Thin end-to-end workflow that composes the project structures, routes, themes, and static-delivery guidance.
- [Askr themes skill](https://askrjs.com/skills/themes/SKILL.md): Theme boundaries, styled building blocks, tokens, customization, and server-rendered style integration.
- [Askr routes skill](https://askrjs.com/skills/routes/SKILL.md): Route registries, layouts, URL state, navigation, loaders, access, metadata, and fallbacks.
- [Askr project structures skill](https://askrjs.com/skills/project-structures/SKILL.md): Ownership and dependency direction across pages, features, components, data boundaries, and server code.
- [Askr control flows skill](https://askrjs.com/skills/control-flows/SKILL.md): Conditional rendering, keyed collections, reactive rows, and render-scoped ordering invariants.
- [Askr icons skill](https://askrjs.com/skills/icons/SKILL.md): Lucide icons, brand logos, accessible composition, semantic sizing, and custom SVG integration.
- [Askr queries and mutations skill](https://askrjs.com/skills/queries-and-mutations/SKILL.md): Query identity, consistency, reconciliation, mutations, invalidation, server prefetch, dehydration, and hydration.
- [Askr i18n skill](https://askrjs.com/skills/i18n/SKILL.md): Typed locale catalogs, application-owned locale resolution, direction, formatting, and SSR hydration.
- [Askr charts skill](https://askrjs.com/skills/charts/SKILL.md): Typed plotting, marks and transforms, interaction, accessibility, live data, styling, and export.
- [Documentation](https://askrjs.com/docs/index.md): Documentation overview and navigation for the Askr platform.
- [Getting started](https://askrjs.com/docs/getting-started/index.md): Install Askr, choose a starter, and build a first route.
- [Core concepts](https://askrjs.com/docs/core-concepts/index.md): Components, state, scopes, lifecycle work, and deterministic rendering.
Expand Down
84 changes: 84 additions & 0 deletions public/skills/build-askr-app/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
name: build-askr-app
description: Build, change, or review an Askr application using explicit pages, features, components, data boundaries, rendering modes, and deployment paths. Use for Askr SPAs, SSR applications, SSG sites, full-stack applications, and API-backed features.
---

# Build an Askr app

Build the smallest application mode that owns the requested behavior while
keeping every route, state transition, external boundary, and cleanup owner
visible.

## Establish the contract

1. Inspect the existing application before scaffolding or restructuring it.
2. Read its `package.json`, route registry, build configuration, and installed
`@askrjs/*` declarations.
3. Treat installed package declarations as authoritative. Verify exports,
props, token values, CLI flags, and declaration status rather than inferring
them from examples or another framework. An exported compatibility alias is
not a recommendation for new code. Avoid legacy and deprecated APIs; use
limited or experimental APIs only when their documented constraints fit the
request. For example,
`grep -n "<name>" node_modules/@askrjs/<package>/dist/*.d.ts` before relying
on a prop or export named in this skill's references.
4. Identify the requested routes, rendering mode, external systems, mutable
actions, deployment target, and completion evidence.
5. Do not invent production URLs, repository names, contact destinations,
analytics identifiers, pricing, customer claims, or credentials.

## Select the needed references

Compose only the skills and references that apply:

- Read the sibling [project structures skill](../project-structures/SKILL.md)
when placing pages, features, components, adapters, queries, mutations, or
server code.
- Read the sibling [routes skill](../routes/SKILL.md) when declaring routes,
layouts, URL state, loaders, access, navigation, metadata, or fallbacks.
- Read the sibling [themes skill](../themes/SKILL.md) when selecting a theme,
composing themed UI, customizing tokens, or integrating theme styles with
SSR or SSG.
- Read the sibling [control flows skill](../control-flows/SKILL.md) when
rendering conditional branches, keyed collections, or reactive row state.
- Read the sibling [icons skill](../icons/SKILL.md) when selecting icons or
logos, composing icon-only controls, or aligning custom SVGs with the shared
icon contract.
- Read the sibling
[queries and mutations skill](../queries-and-mutations/SKILL.md) when a
feature owns cached async data, writes, invalidation, consistency, or server
query hydration.
- Read the sibling [i18n skill](../i18n/SKILL.md) when the application owns
multiple locales, translated catalogs, direction, or locale hydration.
- Read the sibling [charts skill](../charts/SKILL.md) when a feature needs
typed plots, interaction, live visualization, or plot export.
- Read [static-delivery.md](references/static-delivery.md) when generating an
SSG, configuring a base path, or deploying static output to GitHub Pages.

These skills compose. A marketing SSG normally needs project structures,
routes, themes, and static delivery. A small static feature does not need data
boundaries merely because a larger application might.

## Implement in ownership order

1. Register the route tree and its layouts.
2. Make each page compose its route-facing features.
3. Make features compose application components and own their visible states.
4. Add services, adapters, queries, and mutations only for real external or
mutable data, preserving their documented dependency direction.
5. Compose published Askr primitives using their installed contracts.
6. Configure the selected rendering and delivery path without adding a second
route manifest or build pipeline.

## Verify the application

Run the repository-owned format, lint, type, analysis, test, and production
build gates appropriate to the change. Then inspect the actual output:

- exercise valid, empty, loading, failure, cancellation, retry, and access
states that exist;
- verify keyboard navigation, focus, accessible names, landmarks, headings,
responsive layout, hydration, and the browser console;
- inspect SSR or SSG HTML before hydration;
- for a deployment, verify the live routes, assets, metadata, fallback, and
deployment status rather than treating a local build or push as proof.
4 changes: 4 additions & 0 deletions public/skills/build-askr-app/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface:
display_name: 'Build an Askr App'
short_description: 'Compose and ship legible Askr applications'
default_prompt: 'Use $build-askr-app to build an Askr application with explicit architecture and appropriate delivery guidance.'
167 changes: 167 additions & 0 deletions public/skills/build-askr-app/references/static-delivery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# Static generation and GitHub Pages

## Contents

- Define the static contract
- Configure one SSG path
- Handle GitHub Pages base paths
- Deploy and verify
- Five-page marketing composition

## Define the static contract

Before implementation, identify every crawlable route, its purpose, primary
action, title, description, canonical URL, Open Graph data, and navigation
label. Do not guess the repository segment, production origin, custom domain,
contact destination, analytics identifier, or social image.

Use the shared route registry as the only route manifest. An SSG configuration
must render into the built client template, include required browser and public
assets, use the real `siteUrl`, and generate only intended crawlable routes.
When using themed SSR output, wrap the document renderer with the published
theme style integration and treat missing style registration as an error.

Build client assets first and static HTML second. Do not add a second static
generator, sitemap implementation, or deployment build.

## Configure one SSG path

Keep the repository's generated build path. A typical application has one
`ssg.config.ts` that imports `routeRegistry`, injects generated `appHtml` into
the built client template, copies both `public/` and built browser assets, and
excludes the explicit `/404` document from the sitemap:

```ts
// ssg.config.ts
import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import type { DocumentRenderArgs } from '@askrjs/askr/ssg';
import { withThemeStyles } from '@askrjs/themes/ssr';
import { routeRegistry } from './src/pages/_routes';

let clientTemplate: string | undefined;

function renderDocument({ appHtml }: DocumentRenderArgs): string {
clientTemplate ??= readFileSync(
resolve(process.cwd(), '.askr/client/index.html'),
'utf8'
);
const appRoot = /<div([^>]*\bid=["']app["'][^>]*)>\s*<\/div>/i;
if (!appRoot.test(clientTemplate)) {
throw new Error('Built client template must contain an empty #app root.');
}
return clientTemplate.replace(appRoot, `<div$1>${appHtml}</div>`);
}

export const staticConfig = {
registry: routeRegistry,
outputDir: 'dist',
document: withThemeStyles(renderDocument),
styleRegistrationValidation: 'error' as const,
assets: [
{ from: resolve(process.cwd(), 'public'), to: '.' },
{ from: resolve(process.cwd(), '.askr/client/assets'), to: 'assets' },
],
siteUrl: 'https://example.com',
sitemap: { routes: { '/404': false } },
};
```

Give every crawlable route explicit metadata. Register `/404` as a concrete
route so SSG emits `dist/404/index.html`, and also use a fallback so unmatched
navigation renders the same UI:

```tsx
// src/pages/_routes.tsx
import { createRouteRegistry, fallback, route } from '@askrjs/askr/router';
import NotFoundPage from './not-found';

export const routeRegistry = createRouteRegistry(() => {
route('/404', NotFoundPage, {
meta: {
title: 'Page not found',
description: 'The requested page does not exist.',
robots: 'noindex',
},
});
fallback(NotFoundPage);
});
```

Copy the generated file to `dist/404.html` after the build for static hosts
that expect a top-level fallback: `cp dist/404/index.html dist/404.html`.

## Handle GitHub Pages base paths

- A custom domain or `owner.github.io` site uses the origin root.
- An `owner.github.io/repository` project site uses `/repository` as the route
registry `basePath`, `/repository/` as Vite's `base`, and includes that
segment in `siteUrl`.

Set both route and asset bases; setting only one breaks either navigation or
assets. Use router links for internal navigation. Import build-owned assets or
prefix public assets with the configured base instead of hard-coding paths
such as `/images/hero.webp`. Canonical and Open Graph URLs must be absolute and
include the project segment.

```ts
// src/pages/_routes.tsx
export const routeRegistry = createRouteRegistry(registerRoutes, {
basePath: '/repository',
});

// vite.config.ts
export default defineConfig({
base: '/repository/',
plugins: [askr()],
});
```

Use the real repository segment in both places, and omit both entirely for an
origin-root deployment (custom domain or `owner.github.io`).

## Deploy and verify

Use GitHub Pages artifact deployment rather than committing `dist/` or adding
a publishing branch. The workflow should install from the lockfile, run the
repository's validation gates, build once, create `dist/404.html`, verify
expected output, upload `dist/`, and deploy it. Grant only `contents: read`,
`pages: write`, and `id-token: write`; use the `github-pages` environment and
serialize deployments. Pin third-party actions to reviewed commits.

Before merge, run the production build, then run the repository's preview
script (typically `vp preview`, which serves `dist/` honoring `vite.config.ts`'s
`base`) and open the printed local URL — for a project site that URL already
includes `/<repository>/`; do not strip it. Verify all routes, assets,
internal links, metadata, sitemap, robots directive, 404, keyboard behavior,
narrow layout, hydration, and browser console. After merge, wait for the Pages
deployment and repeat those checks against the live URL.

Match a broken build to its likely cause before guessing at a fix:

| Symptom | Likely cause |
| -------------------------------------------------------- | ------------------------------------------------------------------------------- |
| Blank page, console 404s on `/assets/*` | `basePath`/Vite `base` missing or mismatched for a project site |
| Every route 404s except `/` | Only one of route `basePath` or Vite `base` is set — both are required together |
| Broken link preview on social share | `openGraph`/`canonical` missing or relative instead of absolute |
| GitHub Pages serves an unstyled 404 | `dist/404.html` copy step didn't run before upload |
| Images or CSS 404 only on the deployed site, not locally | Hard-coded root-relative asset path instead of an import or base-prefixed path |

## Five-page marketing composition

Treat “five pages” as five crawlable marketing routes; `/404` is deployment
infrastructure and does not count. Unless the brief says otherwise, start with
home, features, pricing, about, and contact, but decide their distinct jobs
before implementation.

Use a marketing route group with its own `_routes.tsx` and `_layout.tsx`. Each
page composes one or more marketing features; features compose reusable
marketing components and published primitives. The layout owns shared header,
navigation, main landmark, container, and footer. Do not create five variants
of one hero or leave starter copy, fake claims, invented prices, dead links, or
controls that only appear to work.

GitHub Pages cannot process a contact form. Use published contact information
or a mail link unless a real endpoint is authorized. When an endpoint exists,
put it behind a validated adapter and mutation, then show pending, failure,
recovery, and success states.
Loading