Wire the Wow View Engine into a host app: one engine with resources and saved-view store (MemoryViewStore, WowViewStore behind CoSec, stored system views), ViewHost, bind and routes, Wow commands on records as declared actions, and moving off fetcher-viewer. Use for @ahoo-wang/wow-view-engine hosts, including the Wow repository's compensation console and Storybook. Exclude definitions (wow-view-definition), other client code, and changing the engine.
Installs into .claude/skills of the current project.
Are you the author of Wow View Host?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/ahoo-wang-wow-view-host)
---
name: "wow-view-host"
description: "Wire the Wow View Engine into a host app: one engine with resources and saved-view store (MemoryViewStore, WowViewStore behind CoSec, stored system views), ViewHost, bind and routes, Wow commands on records as declared actions, and moving off fetcher-viewer. Use for @ahoo-wang/wow-view-engine hosts, including the Wow repository's compensation console and Storybook. Exclude definitions (wow-view-definition), other client code, and changing the engine."
---
# wow-view-host
The deliverable is a host a reviewer can merge: one engine for the application, registered once with every resource and a store; a `ViewHost` around the pages with the router, the language and the theme; a `bind` per resource with its route, its record reading and the commands on its records declared as actions; and tests that read those declarations, routes and definitions the way the engine does. What a definition declares is `wow-view-definition`; this Skill takes the definitions as given.
The engine owns the mechanism — where a command is placed, the confirmation, a selection partly able to take it, running a few at a time, progress, the refresh after, the address's `?view=` and `?id=`, light and dark. The host owns the choices: which resources, where each lives, which commands reach the screen, when each is available and what a refusal says. Write only the choices.
## Before writing
1. Find the host's router, i18n, theme (shadcn or none, who paints dark mode), its Wow service clients (generated by `wow-generator`, or wow-client's), how it authenticates (CoSec token, or nobody signs in), and whether it renders on the server (Next.js). A page still on the deprecated `@ahoo-wang/fetcher-viewer` is rebuilt, not renamed: `references/wiring.md` has the path.
2. Collect the definitions to register and the words of their keys, per language.
3. For each resource, read the aggregate's commands and state: which commands a person issues on a record, and which state fields decide whether one is allowed.
4. Load `references/wiring.md` before writing the engine and the host.
## Workflow
1. **One engine, registered once.** `new ViewEngine({ resources, store, environment })` at the application's start, shared by every page. Each resource pairs a definition with its source: the Wow snapshot (or event stream) query client's `paged`, `cursor`, `aggregate`, and the descriptor client's `describe`, so the engine narrows to the store it runs on. A board's definition has no source. Give the fetcher the sources and the store use a timeout (`fetcher.timeout = 60_000`): neither fetcher nor the engine sets one, and a server that never answers holds a view's opening, and the engine's query slots, for ever.
2. **Choose the store** by who must see saved views: `MemoryViewStore` for tests and demos, `localStorageSnapshot` for one browser in development, `WowViewStore` on the Wow view store for everyone else. Load `references/storage.md`; the tenant and owner come from the fetcher's interceptors, never from options, and the CoSec gateway decides who may use which path. Grant `editSystem` (publish and edit stored system views; absent means refused) only to the role the gateway admits to the system views' path (tenant `(platform)`, owner `(system)`).
3. **One `ViewHost` around the pages:** `engine`, `router` (`useReactRouter()` from `@ahoo-wang/wow-view-engine/react-router`, or the two-member `ViewRouter`), `locale` and `messages` (the engine's catalogue plus the definitions' words), `bindings`, and one theme path. Surfaces under it take only an id: `<DataWorkbench definitionId="orders" />`.
4. **Bind each resource.** `route(instanceId)` is the path of the page that opens a view of it (`null`: the page's default) — the engine keeps `?view=` and `?id=` in sync itself, so do not write that glue. `reading` is how one record reads in its detail. `actions` are its commands, declared. Draw your shell's navigation from `useViewNavigation()`; there is no page shell to configure.
5. **From commands to actions.** Load `references/actions.md` and decide, per command: whether it reaches the screen; the rule that makes it available, read from the record's state (declare the fields it reads in the definition's `record.rowFields`); the refusal in the audience's words; the aggregate id it goes to (read off the row when the row key is a business key); a confirmation asked for one record too (`ask` left at `'always'`) wherever it cannot be undone, `ask: 'bulk'` only where it is undone as easily, and `tone: 'danger'` only where something is lost (cancel, refund, delete), not for a routine step such as shipping; whether a selection may take it (`on`); the form or choice it needs; when its availability flips on its own (`changesAt`); and `run` resolving only after the read model shows the command (`CommandStage.SNAPSHOT`). Slots are the escape hatch, not the path.
6. **Theme and CSP are pointers, not work:** pick `theme="host"` (with `shadcn-bridge.css`) or a `preset` (with its stylesheet), `colorMode="host"` where the app already paints dark mode, and follow the engine's Content Security Policy section where the host has one. Do not hand-write token overrides or a dark-mode switch.
## Self-check
A host is done when its tests read the declarations as the engine does and they pass:
- **Actions:** `actionHarness(actions, rows, { now })` from `@ahoo-wang/wow-view-engine/testing` — each action offered where intended (`at`), available or refused with the right reason on representative rows (`state`, `bulk`), asked where intended (`asks`), and `run` sending the right command (a fake commands object).
- **Routes:** `resolveNavigation(to, bindingOf)` over the host's own bindings sends each resource's ways off to its page.
- **Definitions:** `admit` over the registered resources and committed descriptors in every language returns `[]` or only findings asserted with their reason (`wow-view-definition` owns fixing them).
- These tests and `admit` run in Node; give them a Node Vitest config where the package's own is a browser project.
- The host's type check, lint and existing tests; `references/actions.md` lists the report.
Do not re-verify by hand what these read; they run the engine's own rules.
## References
The references hold names, shapes, rules and gotchas; each links the page of https://wow.ahoo.me/guide/typescript/view-engine.html that covers its topic in depth. Repository paths (`compensation/…`, `typescript/…`) are in the Wow repository.
- `references/wiring.md`: the engine, resources and sources, `ViewHost`, `bind`, routes, navigation, the record reading, theme and CSP pointers, the route test, server rendering, and moving off fetcher-viewer. Load it first.
- `references/actions.md`: from Wow commands to declared actions, the decisions per command, an example over a command client, the harness test and the report. Load it for any command on a record.
- `references/storage.md`: choosing a store, `WowViewStore` with fetcher-cosec, permissions and `editSystem`, stored system views, a host nobody signs in to, and the CoSec gateway rules for the view store's paths. Load it before choosing the store.
## Related Skills
- $wow-view-definition: what each definition declares, its words, system views and boards.
- $wow-client: the command and query clients themselves, errors and wait stages, and generating the typed command clients the actions call.