@imfusion/web-ui 0.6.1-dev.27.gfc6e5abb → 0.6.1-dev.3.g5b432448

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +169 -102
  2. package/dist/{code-C_56u-Vk.js → code-Blo48PGr.js} +2 -2
  3. package/dist/components/stack/stack.d.ts +1 -1
  4. package/dist/icons/icon-config-provider.d.ts +8 -0
  5. package/dist/icons/icon-context.d.ts +4 -0
  6. package/dist/{icons-Cy1HAosO.js → icons-wBmF0U2x.js} +1 -1
  7. package/dist/icons.js +1 -1
  8. package/dist/index.d.ts +0 -1
  9. package/dist/index.js +830 -1009
  10. package/dist/integrations/code-highlight/highlighter.d.ts +0 -24
  11. package/dist/integrations/code-highlight.js +47 -80
  12. package/dist/integrations/image-display-options.js +2 -2
  13. package/dist/provider/web-ui-provider.d.ts +3 -3
  14. package/dist/style.css +1 -1
  15. package/dist/{tabs-DIe1Utiy.js → tabs-CMKvMF4E.js} +0 -2
  16. package/package.json +4 -5
  17. package/src/docgen/doc.gen.json +1 -389
  18. package/src/llms/install-templates/AGENTS.md +18 -15
  19. package/src/llms/llms.gen.txt +33 -39
  20. package/src/llms/skills/imf-web-ui/SKILL.md +39 -30
  21. package/src/llms/skills/imf-web-ui-audit/SKILL.md +102 -50
  22. package/src/llms/skills/imf-web-ui-components/SKILL.md +104 -47
  23. package/src/llms/skills/imf-web-ui-conventions/SKILL.md +52 -44
  24. package/src/llms/skills/imf-web-ui-conventions/templates/AUDIT_CHECKLIST.md +0 -1
  25. package/src/llms/skills/imf-web-ui-conventions/topics/agent-tooling.md +62 -40
  26. package/src/llms/skills/imf-web-ui-conventions/topics/assets.md +12 -11
  27. package/src/llms/skills/imf-web-ui-conventions/topics/authentication.md +46 -31
  28. package/src/llms/skills/imf-web-ui-conventions/topics/class-names.md +23 -18
  29. package/src/llms/skills/imf-web-ui-conventions/topics/components.md +69 -20
  30. package/src/llms/skills/imf-web-ui-conventions/topics/data.md +146 -50
  31. package/src/llms/skills/imf-web-ui-conventions/topics/docs-structure.md +23 -17
  32. package/src/llms/skills/imf-web-ui-conventions/topics/git.md +20 -15
  33. package/src/llms/skills/imf-web-ui-conventions/topics/library-boundary.md +19 -28
  34. package/src/llms/skills/imf-web-ui-conventions/topics/library-setup.md +16 -20
  35. package/src/llms/skills/imf-web-ui-conventions/topics/npm-project.md +42 -28
  36. package/src/llms/skills/imf-web-ui-conventions/topics/project-structure.md +30 -28
  37. package/src/llms/skills/imf-web-ui-conventions/topics/react.md +74 -28
  38. package/src/llms/skills/imf-web-ui-conventions/topics/styling.md +62 -65
  39. package/src/llms/skills/imf-web-ui-conventions/topics/testing.md +14 -12
  40. package/src/llms/skills/imf-web-ui-conventions/topics/tokens.md +4 -9
  41. package/src/llms/skills/imf-web-ui-conventions/topics/tooling.md +68 -40
  42. package/src/llms/skills/imf-web-ui-conventions/topics/typescript.md +50 -26
  43. package/src/llms/skills/imf-web-ui-conventions/topics/validation.md +25 -19
  44. package/src/llms/skills/imf-web-ui-setup/SKILL.md +64 -45
  45. package/src/llms/skills/imf-web-ui-update/SKILL.md +114 -48
  46. package/src/llms/skills/imf-web-ui-ux/SKILL.md +92 -64
  47. package/src/llms/skills/imf-web-ui-ux/references/forms.md +36 -16
  48. package/src/llms/skills/imf-web-ui-ux/references/usability-heuristics.md +27 -14
  49. package/src/llms/skills/imf-web-ui-ux/references/visual-design.md +38 -22
  50. package/src/llms/tokens.gen.json +5 -5
  51. package/dist/codegen/gen-code-highlight-theme.d.ts +0 -1
  52. package/dist/components/toast/index.d.ts +0 -2
  53. package/dist/components/toast/toast.d.ts +0 -200
  54. package/dist/components/toast/toast.meta.d.ts +0 -2
  55. package/dist/icons/icon-config.d.ts +0 -12
@@ -1,44 +1,50 @@
1
1
  # Tooling
2
2
 
3
- Read this topic before adding a dependency or configuring a tool. Use the tool's current documentation rather than memory.
3
+ Dependency and configuration baseline for an ImFusion frontend; check before adding a dependency and before writing its
4
+ config.
4
5
 
5
6
  ## Topic-to-tool map
6
7
 
7
- | Need | Default |
8
- | --------------------- | -------------------------------------------- |
9
- | Build | Vite |
10
- | Routing and URL state | TanStack Router |
11
- | Server state | TanStack Query |
12
- | Forms | TanStack Form |
13
- | Data grids | TanStack Table plus Web UI `Table` parts |
14
- | App-wide client state | TanStack Store, after URL/server/local state |
15
- | Schema validation | Zod at the boundary |
16
- | Tests | Vitest |
17
- | Format | Prettier |
18
- | Lint | ESLint flat config |
19
- | Types | `tsc --noEmit` |
20
- | Staged files | lint-staged or nano-staged |
21
- | Dead code | Knip via `verify:knip` |
8
+ - Use the mapped tool for each topic; prefer typed config (`.ts` over `.json`) where the tool supports it.
9
+
10
+ | Topic | Tool |
11
+ | --------------------- | ----------------------------------------------------------------------------------------------------- |
12
+ | Build | [Vite](https://vite.dev) |
13
+ | Routing, URL state | [TanStack Router](https://tanstack.com/router) — file-based, type-safe search params |
14
+ | Server state | [TanStack Query](https://tanstack.com/query) — the pattern around it is [data.md](data.md) |
15
+ | Forms | [TanStack Form](https://tanstack.com/form) |
16
+ | Data grids | [TanStack Table](https://tanstack.com/table) + web-ui's styled `Table` parts |
17
+ | App-wide client state | [TanStack Store](https://tanstack.com/store) — last resort in the state ladder ([react.md](react.md)) |
18
+ | Schema validation | [Zod](https://zod.dev) — at the network boundary ([data.md](data.md)) |
19
+ | Styling | CSS Modules ([styling.md](styling.md)) |
20
+ | Test | [Vitest](https://vitest.dev) |
21
+ | Format | [Prettier](https://prettier.io) |
22
+ | Lint | [ESLint](https://eslint.org) flat config |
23
+ | Types | `tsc --noEmit` — own script, own CI step |
24
+ | Staged files | [lint-staged](https://github.com/lint-staged/lint-staged) (or nano-staged, drop-in) |
25
+ | Dead code | [Knip](https://knipjs.dev) via `verify:knip` — needs per-repo config |
22
26
 
23
27
  ## When a library owns a layer
24
28
 
25
- Use the library that already owns the problem. Adopt Form for form rules, Query for caching and refetching, Router for URL
26
- state, and Table for sorting and pagination instead of rebuilding those layers. Keep an existing project choice when it
27
- works.
29
+ - Adopt the library once you're rebuilding what it does — validation timing and cross-field rules (Form), caching and
30
+ refetching (Query), URL as source of truth (Router), sorting/pagination over rows (Table): adding it mid-project is cheap,
31
+ unpicking a hand-rolled version later is not.
28
32
 
29
33
  ## Devtools
30
34
 
31
- Add the devtools package for a TanStack library when one exists, mount it only in development, and check for a matching
32
- devtools package whenever a new TanStack dependency is added.
35
+ - Every TanStack library with a devtools package gets it as a dev dependency, mounted in development only — Router's
36
+ `@tanstack/react-router-devtools` is a given; Query's goes in when Query does.
37
+ - Check for a `-devtools` sibling on every new TanStack dependency — not every library has one yet.
38
+ - Once several are in, host them in one panel via `@tanstack/devtools`.
33
39
 
34
40
  ## Docs over memory
35
41
 
36
- Use `npx @tanstack/cli` for TanStack documentation. If TanStack Intent is configured, use it for the Agent Skills the
37
- TanStack package provides.
42
+ - `npx @tanstack/cli` for TanStack docs — never work from memory.
43
+ - Where `@tanstack/intent` is wired up, use it to reach and read the Agent Skills the TanStack dependencies ship.
38
44
 
39
45
  ## Prettier
40
46
 
41
- Use a config file. The repo's values are:
47
+ - Config file shape is free (`.prettierrc`, `prettier.config.ts`); the values are not:
42
48
 
43
49
  ```ts
44
50
  import type { Config } from "prettier";
@@ -53,36 +59,58 @@ const config: Config = {
53
59
  singleQuote: false,
54
60
  proseWrap: "always"
55
61
  };
56
-
57
- export default config;
58
62
  ```
59
63
 
60
- ## ESLint and TypeScript
61
-
62
- Use flat ESLint config with type-aware rules and the repo's ignore file. The baseline bans `as` and non-null `!` outside
63
- tests, requires the `#/` alias instead of parent-relative imports, and uses project-service type information.
64
+ - Never omit the config file — no file means defaults, and the values silently differ.
65
+
66
+ ## ESLint
67
+
68
+ Flat config (`eslint.config.ts`):
69
+
70
+ - `strictTypeChecked` + `stylisticTypeChecked`, `projectService: true`
71
+ - `as` and `!` banned outside tests (`consistent-type-assertions`)
72
+ - `.gitignore` as the ignore source (`includeIgnoreFile` from `@eslint/compat`)
73
+ - `#/` alias enforced via `no-restricted-imports` banning `../*` — parent-relative paths error, siblings (`./`) stay relative
74
+ ([project-structure.md](project-structure.md))
75
+
76
+ ## tsconfig
77
+
78
+ ```jsonc
79
+ {
80
+ "compilerOptions": {
81
+ "strict": true,
82
+ "moduleResolution": "bundler",
83
+ "verbatimModuleSyntax": true, // import type stays import type
84
+ "noUnusedLocals": true,
85
+ "noUnusedParameters": true,
86
+ "noFallthroughCasesInSwitch": true,
87
+ "noUncheckedSideEffectImports": true,
88
+ "skipLibCheck": true,
89
+ "paths": { "#/*": ["./src/*"] }
90
+ }
91
+ }
92
+ ```
64
93
 
65
- Use strict TypeScript with bundler module resolution, `verbatimModuleSyntax`, unused-value checks, and `#/` paths. Keep
66
- `import type` for type-only imports.
94
+ - `#/` → `src/` alias rationale: [project-structure.md](project-structure.md).
67
95
 
68
96
  ## Staged files
69
97
 
70
- The staged-file runner applies ESLint fixes and Prettier writes only to staged files. It also runs the relevant project
71
- checks when source or config can affect the dependency graph.
98
+ - Runner config (lint-staged or nano-staged) applies eslint `--fix` and prettier `--write` to staged files only.
99
+ - The pre-commit runner also invokes `verify:knip` when staged source or project config can change the reachability graph.
72
100
 
73
101
  ## CSS class names
74
102
 
75
- Register Web UI's `readableCssModuleNames` plugin in every compiler that processes the app's CSS, including development,
76
- Storybook, and production:
103
+ - Generated CSS Module class names are readable in the DOM, `{prefix}-{file}-{local}`, never the default hash: a legible DOM
104
+ is what makes devtools and browser automation usable.
105
+ - The library ships the plugin; pass a short, app-scoped prefix:
77
106
 
78
107
  ```ts
79
- import { defineConfig } from "vite";
80
- import react from "@vitejs/plugin-react";
81
108
  import { readableCssModuleNames } from "@imfusion/web-ui/build/vite-css-module-names";
82
109
 
83
110
  export default defineConfig({
84
- plugins: [react(), readableCssModuleNames({ prefix: "app" })]
111
+ plugins: [react(), readableCssModuleNames({ prefix: "acme" })]
85
112
  });
86
113
  ```
87
114
 
88
- A compiler left out of the plugin produces different class names and styles that appear to work only in some environments.
115
+ - One pattern for dev, Storybook, and production: register the plugin in **every** tool that compiles the CSS — a compiler
116
+ left out generates different names for the same source, and its styles silently don't apply.
@@ -1,49 +1,73 @@
1
- # TypeScript and code style
1
+ # TypeScript & code style
2
2
 
3
- Prefer pure functions, immutable values, and side effects at the edges.
3
+ Functional by default: pure functions over stateful classes, immutable data over in-place mutation, expressions over
4
+ statements, side effects at the edges (network, DOM, store).
4
5
 
5
6
  ## Types
6
7
 
7
- - Do not use `any`. Accept `unknown` at an untrusted boundary and narrow it.
8
- - Infer local values; give exported functions explicit return types.
9
- - Model states directly instead of filling a nullable value later.
10
- - Derive types from their source. Use `z.infer` for schemas and `React.ComponentProps` for Web UI components.
11
- - Avoid `as`. Keep an assertion only at an untyped third-party boundary where it is the honest boundary.
12
- - Use one or two positional arguments. At three or more, pass a named object.
8
+ - No `any`. `unknown` at a boundary you can't type, narrowed before use.
9
+ - Infer locals; annotate contracts. Exported functions get an explicit return type.
10
+ - No temporal coupling — model the states instead of initialising `null` and filling in later.
11
+ - Avoid `as`. Fix the type. The honest exception: an untyped third-party boundary, kept at the boundary.
12
+ - Derive, don't duplicate:
13
13
 
14
14
  ```ts
15
15
  const sizes = ["sm", "md", "lg"] as const;
16
16
  type Size = (typeof sizes)[number];
17
17
 
18
- const labels: Record<Size, string> = {
19
- sm: "S",
20
- md: "M",
21
- lg: "L"
22
- };
18
+ const labels: Record<Size, string> = { sm: "S", md: "M", lg: "L" }; // compiler breaks if `sizes` changes
23
19
  ```
24
20
 
25
- ## Immutability and expressions
21
+ - Same rule across boundaries: library props via `React.ComponentProps<typeof Button>`
22
+ ([library-boundary.md](library-boundary.md)), untrusted data via a runtime schema and `z.infer`
23
+ ([validation.md](validation.md)).
24
+ - Function signatures: 1–2 positional arguments; at 3+, one destructured object.
26
25
 
27
- Use `map`, `filter`, `find`, `some`, and `flatMap` for ordinary collection work. Create new values instead of mutating the
28
- input. Use `toSorted` and `toReversed` instead of their mutating counterparts.
26
+ ## Immutability & expressions
29
27
 
30
- A loop is fine when it has a real early exit or measured hot-path benefit. A long chain or a `reduce` with several jobs wants
31
- named intermediate values.
28
+ - Array methods before loops — `map`, `filter`, `find`, `some`, `flatMap` name what they do:
32
29
 
33
- ## Naming
30
+ ```ts
31
+ const activeNames = users.filter(u => u.isActive).map(u => u.name);
32
+ ```
34
33
 
35
- Name what a value is, not how it is built. Booleans read as assertions (`isOpen`, `hasAccess`, `canSubmit`). Props use `onX`;
36
- component implementations use `handleX`.
34
+ - Produce new values: spreads and `structuredClone` over in-place edits, `toSorted`/`toReversed` over `sort`/`reverse` (which
35
+ mutate their receiver).
36
+ - Allowed exceptions: a genuine early exit (`for` + `break`), a measured hot loop.
37
+ - Keep chains flat: 3–4 steps read well; longer wants named intermediates, and a `reduce` doing four things wants to be a
38
+ loop.
39
+
40
+ ## Naming
37
41
 
38
- Keep a hook or query result as a namespace and name the local after its domain:
42
+ - Say what it is, not what it's made of: `useUserQuery`, not `useUserHook`; `retryDelay`, not `num`.
43
+ - Booleans read as assertions: `isOpen`, `hasAccess`, `canSubmit`.
44
+ - Handlers: `onX` as props, `handleX` as implementations.
45
+ - Match the vocabulary the product and the API already use — no synonyms for terms the backend named.
46
+ - Keep the object a hook or query returns as a namespace instead of destructuring it, and drop the `Query`/`Mutation` suffix
47
+ from the local binding — the binding reads as the domain name, and every field access shows where it came from:
39
48
 
40
49
  ```tsx
41
- const search = Route.useSearch();
42
- const user = useSuspenseQuery(context.api.user.getDetails());
50
+ const search = Route.useSearch(); // not const { page, filter } = ...
51
+ const user = useSuspenseQuery(context.api.user.getDetails()); // not const { data } = ...
52
+ const updateUser = useMutation(context.api.user.update());
43
53
 
44
54
  search.page;
45
55
  user.data.name;
56
+ updateUser.mutate(values);
57
+ updateUser.isPending;
46
58
  ```
47
59
 
48
- Destructure a primitive only when a stable value is needed, such as an effect dependency. Match existing product and API
49
- vocabulary instead of inventing synonyms.
60
+ - Exception: a `useEffect` dependency array needs a stable primitive, since deps compare by identity — destructure the
61
+ primitive out first rather than listing the object or a deep path into it:
62
+
63
+ ```tsx
64
+ const user = useSuspenseQuery(context.api.auth.getUser());
65
+ const { name } = user.data; // destructure for the dep array
66
+
67
+ useEffect(
68
+ function syncDocumentTitle() {
69
+ document.title = name;
70
+ },
71
+ [name]
72
+ );
73
+ ```
@@ -1,22 +1,20 @@
1
1
  # Validation
2
2
 
3
- Validate data when it crosses into frontend-owned code. Use the schema as both the runtime check and the TypeScript source.
3
+ Validate where data crosses from untrusted representation into frontend-owned values; the schema is the single source of
4
+ truth for runtime check and TypeScript type.
4
5
 
5
6
  ## Boundaries
6
7
 
7
- Validate once at the edge:
8
-
9
- - network responses on entry;
10
- - URL path and search values;
11
- - persisted browser data when read;
12
- - user input when it becomes a submitted domain or request value.
13
-
14
- After the boundary, use parsed values. A generic on a typed client only tells TypeScript what you hope the response looks
15
- like; it does not validate it.
8
+ - Validate once, at the edge: network responses on entry; URL path and search params before business logic; persisted browser
9
+ data on read; user input becoming a submitted domain or request value.
10
+ - Inside the boundary: parsed values only, no repeated defensive shape checks.
11
+ - Outgoing requests built from already parsed domain values are serialized, not re-validated.
12
+ - A typed client's handwritten generic is not validation — it only asserts a type onto an untrusted response.
16
13
 
17
14
  ## Schema first, type derived
18
15
 
19
- Use a Zod schema and derive the type:
16
+ - Zod schema, type via `z.infer`; never a handwritten type beside its schema.
17
+ - Same rule for request and response shapes the frontend owns or consumes at runtime.
20
18
 
21
19
  ```ts
22
20
  import { z } from "zod";
@@ -29,13 +27,17 @@ export const userSchema = z.object({
29
27
  export type User = z.infer<typeof userSchema>;
30
28
  ```
31
29
 
32
- Apply the same rule to request and response shapes the frontend owns at runtime.
33
-
34
30
  ## TanStack Router search params
35
31
 
36
- Pass a Zod v4 schema to `validateSearch`. Route search types then come from that schema:
32
+ - `validateSearch` takes a Zod v4 schema directly (TanStack Router v1) — no adapter or parsing wrapper.
33
+ - `Route.useSearch()` infers its type from `validateSearch`.
34
+ - `.catch()`: malformed URL input falls back without interrupting navigation.
35
+ - `.default()`: only for missing values; malformed values still follow the route's validation error path.
37
36
 
38
37
  ```tsx
38
+ import { createFileRoute } from "@tanstack/react-router";
39
+ import { z } from "zod";
40
+
39
41
  const searchSchema = z.object({
40
42
  page: z.number().int().positive().catch(1),
41
43
  filter: z.string().catch("")
@@ -45,12 +47,16 @@ export const Route = createFileRoute("/users")({
45
47
  validateSearch: searchSchema,
46
48
  component: Users
47
49
  });
48
- ```
49
50
 
50
- Use `.catch()` for malformed values that can safely fall back. Use `.default()` only for missing values.
51
+ function Users() {
52
+ const search = Route.useSearch(); // inferred: z.infer<typeof searchSchema>
53
+ return <UserList page={search.page} filter={search.filter} />;
54
+ }
55
+ ```
51
56
 
52
57
  ## Failure handling
53
58
 
54
- - Use `parse` when invalid data is a contract failure that should reach the normal error boundary.
55
- - Use `safeParse` when failure is expected and the caller can show a validation message.
56
- - Keep trimming, coercion, transforms, and defaults in the boundary schema.
59
+ - `schema.parse`: invalid data is a contract failure on the normal error path (malformed backend response → route error
60
+ boundary).
61
+ - `schema.safeParse`: failure is expected and the caller handles the issues (submitted user input).
62
+ - Transforms and coercion live in the boundary schema — never scatter trimming, number conversion, or defaulting downstream.
@@ -1,68 +1,87 @@
1
1
  ---
2
2
  name: imf-web-ui-setup
3
3
  description:
4
- "Plan and, after explicit approval, bootstrap a consumer project that uses @imfusion/web-ui. Use this whenever a project
5
- needs library wiring, tooling, git, npm, authentication, structure, data, testing, docs, or agent tooling. Inspect first,
6
- propose concrete files, and write only what the user approves. Use imf-web-ui-audit for read-only checks."
4
+ "Plan and, after explicit approval, bootstrap an ImFusion frontend against the conventions baseline: library setup,
5
+ tooling, git, npm project, authentication, project structure, docs structure, data, testing, or agent tooling. Inspect
6
+ statically first and write only the approved files. Use imf-web-ui-audit for read-only health checks or topics with no
7
+ setup action."
7
8
  argument-hint: "[full|library-setup|tooling|git|npm-project|authentication|project-structure|docs-structure|data|testing|agent-tooling]"
8
9
  allowed-tools: Read Glob Grep Write
9
10
  ---
10
11
 
11
- # Set up a consumer project
12
+ # imf-web-ui-setup
12
13
 
13
- Plan the missing pieces of an ImFusion frontend. The existing project wins; this skill fills gaps instead of reshaping
14
- working choices.
14
+ You are the frontend bootstrap planner. Inspect the repository statically, read the applicable `imf-web-ui-conventions`
15
+ topics, and prepare a complete proposal for every file you would create or change. The project wins where it already has a
16
+ working convention. This skill is plan-first: enter the host's plan mode before presenting the proposal, and do not create a
17
+ report file as a substitute for the host plan.
15
18
 
16
19
  ## Workflow
17
20
 
18
- 1. Resolve the argument. Bare means `full`. A named topic limits the assessment to that topic. If the argument is unknown,
19
- list the supported topics and point to `imf-web-ui-audit`.
20
- 2. Enter the host's plan mode before inspecting or proposing changes.
21
+ 1. Resolve the argument, not the prose. Bare means `full`; a topic argument selects one supported setup topic. A prompt that
22
+ merely _mentions_ one area ("wire up the tooling", "get the project set up") is still a `full` run — the words describe a
23
+ starting point, not a scope that excludes the rest. For a greenfield `full` run the application boundary (router, route
24
+ groups, current-user query, AppShell) is part of the deliverable even when the prompt never names it; propose it and let
25
+ the human remove it, never silently defer it as "out of scope." For an unsupported topic argument, list the available
26
+ setup topics and point the human to `imf-web-ui-audit` for a read-only report.
27
+ 2. Enter the host's plan mode. If it is not already active, use the host plan-mode control before inspecting and planning.
21
28
  3. Read the selected convention topics and inspect the repository with `Read`, `Glob`, and `Grep` only.
22
- 4. Put a complete proposal in the host plan, using [`templates/REPORT.md`](../imf-web-ui-conventions/templates/REPORT.md).
23
- For new or updated documentation, invoke `/documentation-writer` before writing and use the `docs-structure` topic for
24
- repository-specific boundaries. Name every file to create or change, include its intended content, and cite the repository
25
- evidence behind the choice.
26
- 5. Wait for explicit approval. After approval, write only the listed files.
27
- 6. Run `imf-web-ui-audit full` as a follow-up and review its findings before calling setup complete.
29
+ 4. Build the complete proposal in the host plan from the shared report contract at
30
+ [`../imf-web-ui-conventions/templates/REPORT.md`](../imf-web-ui-conventions/templates/REPORT.md). Include the concrete
31
+ content of every file the approved setup would create or change, with repository evidence for each decision.
32
+ 5. A greenfield `full` setup proposes the whole starter skeleton, not just tooling — tooling without the application boundary
33
+ is an unfinished setup. Include, as concrete files in the plan:
34
+ - the TanStack Router **package added to `package.json`** (with its router devtools as a dev dependency), not just
35
+ imported — code that imports an uninstalled package is an incomplete setup
36
+ ([project-structure.md](../imf-web-ui-conventions/topics/project-structure.md));
37
+ - pathless `_public/` and `_app/` route groups behind one server-backed current-user boundary
38
+ ([authentication.md](../imf-web-ui-conventions/topics/authentication.md));
39
+ - the minimal branded `AppShell` in `_app/` by default — omit the shell only when the human explicitly says the product
40
+ has no persistent authenticated navigation (ask first), but keep the `_app/` boundary either way;
41
+ - a per-topic `api/` folder for any data the first screen shows, never an inline fixture in the component
42
+ ([data.md](../imf-web-ui-conventions/topics/data.md)).
28
43
 
29
- ## Greenfield `full` setup
44
+ The plan documents this starter shape as concrete file content; it does not copy a full external starter template.
45
+ Existing projects keep their working choices — propose only the gaps.
30
46
 
31
- Include these pieces unless the existing project already has them or the user removes them from the plan:
47
+ 6. Keep the plan as the approval gate. After the host approves and exits plan mode, write only the listed files. Complete any
48
+ immediately requested bootstrap work covered by that approved plan, then invoke `imf-web-ui-audit full` as a verification
49
+ step and review the findings it reports back before declaring the setup complete. The audit stays out of plan mode here —
50
+ the human has just left it to let this work happen.
32
51
 
33
- - `@tanstack/react-router` and its router devtools in `package.json`;
34
- - pathless `_public/` and `_app/` route groups;
35
- - one server-backed current-user query at the route boundary;
36
- - a minimal `AppShell` in `_app/`, unless the user says the product has no persistent authenticated navigation;
37
- - an API topic folder for data shown by the first screen;
38
- - the root provider and library wiring.
52
+ Installer and hook runs stay with the human: an `agent-tooling` proposal lists the `npx web-ui-install` commands as human
53
+ steps, applies the judgment from the topic (read existing registrations first, never stack a hook on a covered event), and
54
+ includes the topic's Codex trust follow-up whenever hooks are part of the plan.
39
55
 
40
- The plan describes the exact starter files. It does not copy a generic starter project.
56
+ ## Checklist
41
57
 
42
- ## Installer steps
43
-
44
- For `agent-tooling`, list the `npx web-ui-install` commands as steps for the human. Read existing registrations first and do
45
- not stack a hook on an event the project already covers. Include the Codex trust review when hooks are part of the plan.
58
+ The post-implementation audit uses the shared
59
+ [convention audit checklist](../imf-web-ui-conventions/templates/AUDIT_CHECKLIST.md) to verify the complete baseline, not
60
+ only the setup topic selected at the start.
46
61
 
47
62
  ## Safety
48
63
 
49
- During inspection use only `Read`, `Glob`, and `Grep`. Do not run shells, Git, Node, npm, npx, installers, builds, tests, or
50
- local config. Report anything that needs runtime state as unverified. After approval, `Write` is limited to the approved file
51
- list; put commands in the plan for the human to run.
64
+ Use only static inspection: `Read`, `Glob`, and `Grep`. Do not use a shell or invoke Node, npm, npx, package scripts, hooks,
65
+ config imports, linters, tests, builds, Git commands, project binaries, installers, or package managers. Read config as text
66
+ and report runtime or machine-local state that cannot be established statically as unverified. After approval, `Write` is
67
+ limited to the files listed in the approved report; anything needing execution goes in the plan for the human.
68
+
69
+ ## Setup topics
52
70
 
53
- ## Topics
71
+ `full` covers every topic below. A one-topic run assesses only that topic.
54
72
 
55
- | Topic | Covers |
56
- | ------------------- | ------------------------------------------------------------------------ |
57
- | `library-setup` | Stylesheet, `WebUIProvider`, and package wiring. |
58
- | `tooling` | Dependencies, devtools, formatter, linter, TypeScript, and verification. |
59
- | `git` | Hooks, verification scopes, and staleness checks. |
60
- | `npm-project` | Manifest, scripts, pins, npm, and Node. |
61
- | `authentication` | Current-user query, route groups, login, and logout. |
62
- | `project-structure` | Source tree, route placement, naming, and imports. |
63
- | `docs-structure` | README, AGENTS, docs index, and content boundaries. |
64
- | `data` | Transport, schemas, query/mutation options, keys, and invalidation. |
65
- | `testing` | Test boundaries and coverage. |
66
- | `agent-tooling` | Vendored skills, hooks, registrations, and Codex trust. |
73
+ | Topic | Assess and plan |
74
+ | ------------------- | ------------------------------------------------------------------------------ |
75
+ | `library-setup` | styles import, `WebUIProvider`, and library package wiring |
76
+ | `tooling` | dependency selection, devtools, Prettier, ESLint, TypeScript, and verification |
77
+ | `git` | tracked hooks, verification scopes, and staleness wiring |
78
+ | `npm-project` | package metadata, scripts, pins, npm, and Node configuration |
79
+ | `authentication` | current-user query, public/app guards, login, and logout |
80
+ | `project-structure` | source tree, route groups, optional app shell, naming, and placement |
81
+ | `docs-structure` | README, AGENTS, docs index, and content boundaries |
82
+ | `data` | transport, schemas, query/mutation options, keys, and invalidation |
83
+ | `testing` | test boundaries and verification coverage |
84
+ | `agent-tooling` | vendored skills, AGENTS fence, lifecycle hooks, registrations, and staleness |
67
85
 
68
- The other convention topics are read by `imf-web-ui-audit` when a project needs assessment rather than setup.
86
+ Setup has no file-creation action for `react`, `typescript`, `class-names`, `validation`, `components`, `styling`, `assets`,
87
+ `library-boundary`, or `tokens`; select those in `imf-web-ui-audit`.