Views
A view is a named screen in the app, identified by a URL route. Views are where components and requests get scoped, and where most authoring happens.
version: 1
views: - name: FlightSearch route: /search description: Main search page with date and origin/destination pickers source: src/pages/FlightSearch.tsx components: - name: DepartureDatePicker selector: '[data-picker="departure"]' requests: - name: SearchFlights route: /api/flights/search method: POSTname and route are required. description and source are documentary — they aren’t surfaced at runtime but pay for themselves in PR review and future maintenance. See Schema reference for every field.
Route matching
Section titled “Route matching”Routes use glob patterns against the URL pathname.
*matches exactly one path segment:/users/*matches/users/42, not/users/42/edit.**matches any depth of segments:/admin/**matches/admin,/admin/users, and/admin/users/42/edit.- Literal segments match themselves.
- Matching is case-sensitive. Query strings and fragments are ignored. Trailing slashes are normalized away before matching.
For requests, Express-style :param segments are normalized to *, so /api/users/:id/orders and /api/users/*/orders are equivalent. See Requests.
Most specific wins
Section titled “Most specific wins”When more than one view’s route matches the URL, the most specific route wins — not the first one listed. Definition order does not set priority; it only breaks ties between routes of equal specificity. You don’t have to hand-order routes specific-before-general.
Specificity is the sum of per-segment scores:
| Segment | Score |
|---|---|
Literal (e.g. users) | 3 |
:param (e.g. :id) | 2 |
* (single segment) | 1 |
** or empty | 0 |
The root route / scores 1 — more specific than any wildcard-only pattern. When two routes score equal, the first declared view wins.
views: - name: UserProfile route: /users/* # score 3+1 = 4 — listed first, still loses - name: UserSettings route: /users/me/settings # score 3+3+3 = 9 — wins for its path/users/me/settings resolves to UserSettings (score 9) regardless of declaration order — flipping these two lines changes nothing. /users/* (score 4) still wins for paths like /users/42.
Scoped vs global
Section titled “Scoped vs global”Components and requests can live at the file root or nested inside a view.
- Global (file root): matched against every view.
- View-scoped (inside a view): matched only when that view is active.
- They are additive. A view defines its own components on top of any globals; both apply.
components: - name: Navigation # global — matched on every view selector: 'nav[data-component="Navigation"]'
views: - name: Dashboard route: /dashboard components: - name: DashboardLayout # scoped — only on /dashboard selector: '[data-component="DashboardLayout"]'Dependencies
Section titled “Dependencies”source names the view’s primary file. A view often touches more code than that — a feature-specific hook, a Zustand store, a CSS module. Listing those in dependencies lets reverse-lookup tooling tie file edits back to the view without forcing every supplementary file into its own entry:
views: - name: ListView route: /lists/:id source: src/views/ListView.tsx dependencies: - src/hooks/useChecklist.ts - src/stores/listStore.ts - src/styles/list-card.cssdependencies is purely curation-time — strings are minimatch globs, project-root-anchored, with !-prefix negation. The runtime never reads source files. See the schema reference for the full rules (what belongs, what doesn’t, normative diagnostics).
Components covers selector strings, arrays, and nesting rules. Requests covers method filters and route normalization.