Skip to content

Commit a4221b6

Browse files
Add Claude Code project configuration with chrome-host MCP bridge for browser automation
Introduce CLAUDE.md and a .claude/ directory so Claude Code works from the project's documented conventions instead of guessing. * CLAUDE.md — entry doc: project overview, the devcontainer command workflow, and an index of rules, agents and the `/commit` skill. * .claude/rules/ — always-on rules (code, git, safety-guards) and path-scoped rules (frontend, styling, testing, docs) carrying the project conventions. * .claude/skills/commit/ — the `/commit` skill for committing per project rules. * .claude/agents/code-reviewer.md — a repo-tailored review agent. * .claude/settings.json — scoped command permissions and enables the `chrome-host` MCP server (plus the GitHub and Context7 plugins). Speaking of chrome-host MCP bridge: Add tooling that lets an MCP-capable assistant in the `devcontainer` drive Chrome running on the host via `chrome-devtools-mcp` over the Chrome DevTools Protocol. Because the container can only reach the host through `host.docker.internal` and Chrome's DevTools endpoint rejects non-IP `Host` headers, a small loopback proxy (`cdp_proxy.py`) runs inside the `node` container and forwards to host Chrome, so the `Host` Chrome sees stays `127.0.0.1`. Includes the host launcher (`start-host-chrome.sh`, throwaway profile opening the docs site), the in-container launcher and entry scripts, native-Docker host-gateway setup, MCP registration for Claude/Copilot (`.mcp.json`) and OpenCode (`opencode.json`), and documentation.
1 parent 4628f01 commit a4221b6

26 files changed

Lines changed: 1255 additions & 66 deletions

.claude/agents/code-reviewer.md

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
---
2+
name: code-reviewer
3+
description: Thorough review of a change against this repo's rules — intent/requirements, correctness, design, security (incl. dependency audit), and test coverage. Reviews flexibly by scope: uncommitted work, the whole branch against its base (default master), a specific commit, or a named branch — always as one combined diff. Use after implementing a change, or to review a branch before merge. Complements the generic /code-review skill, which does not know these project rules.
4+
tools: Read, Grep, Glob, Bash
5+
---
6+
7+
# Code Reviewer
8+
9+
Review a change as one coherent diff and report findings only — do not edit
10+
files. Read enough of the surrounding code to judge it, read the cited rule and
11+
doc files before ruling, and cite `file:line` for every finding.
12+
13+
## Scope — what to review
14+
15+
Orient first: `git status --short` and `git rev-parse --abbrev-ref HEAD`. Then
16+
pick the scope and state which you chose. Always review the **net result as a
17+
single diff, never commit-by-commit** — later commits (fixups, reverts) may
18+
correct earlier ones, and only the final state matters.
19+
20+
* **Explicitly requested** — honour what the invocation asks for: a base branch
21+
(`git diff <branch>...HEAD`), a single commit (`git show <sha>`), or a commit
22+
range (`git diff <from>..<to>`).
23+
* **Uncommitted work present** (`git status --short` non-empty) → review the
24+
working tree against `HEAD` (`git diff HEAD`) plus any untracked files (list
25+
with `git status`, then read them).
26+
* **Clean tree** → review the whole branch against its base (default `master`):
27+
`git diff master...HEAD` (three dots = only what this branch introduced).
28+
29+
Work top-down: first establish what the change is supposed to do, then judge
30+
whether it does so correctly, cleanly, safely, and with tests. The repo-specific
31+
rules in section 6 are the easiest to miss — do not skip them.
32+
33+
## 1. Intent & requirements
34+
35+
* Establish the intent from the task / PR description and any linked issue (a
36+
GitHub issue number appears in parentheses in the commit/PR name, e.g.
37+
`(#261)`). Check the diff against it.
38+
* Is all the planned functionality present, or is something stubbed, `TODO`, or
39+
silently dropped?
40+
* Flag scope creep — unrelated changes riding along
41+
([code.md](../rules/code.md)).
42+
43+
## 2. Correctness & robustness
44+
45+
* **Error handling.** Failures are handled at the right level, not swallowed;
46+
promises are awaited; rejections are handled.
47+
* **Edge cases.** Empty / `null` / `undefined`, zero / one / many, boundary
48+
values, async ordering, and failure paths are handled. Component edge cases:
49+
missing `children`, controlled vs uncontrolled, ref forwarding.
50+
* **Resource hygiene.** `useEffect` subscriptions / listeners / timers are
51+
cleaned up; no retained references or unbounded state growth.
52+
53+
## 3. Design & maintainability
54+
55+
* Clean separation of concerns; the change integrates with the existing patterns
56+
rather than introducing a parallel style — `React.forwardRef` +
57+
`withGlobalProps`, context-aware variants via `useContext`, `classNames()` for
58+
CSS Module classes, `transferProps()` for HTML attribute pass-through, CSS
59+
Modules for styles ([frontend.md](../rules/frontend.md),
60+
[styling.md](../rules/styling.md)).
61+
* Props follow the [API Guidelines](../../src/docs/contribute/api.md) and nesting
62+
follows [Composition](../../src/docs/contribute/composition.md).
63+
* DRY without premature abstraction; sound, reasonably performant code — no heavy
64+
work in render, no needless re-renders.
65+
66+
## 4. Security
67+
68+
* Validate / sanitise external data; no unsafe HTML
69+
(`dangerouslySetInnerHTML`) with untrusted content; no secrets committed.
70+
* **Dependencies.** If `package.json` / `package-lock.json` changed: new
71+
dependencies need explicit approval
72+
([safety-guards.md](../rules/safety-guards.md)); run `npm audit` (in the
73+
devcontainer) and report advisories; sanity-check the lockfile diff for
74+
unexpected or transitive version bumps.
75+
76+
## 5. Tests
77+
78+
* New or changed code is covered — co-located Jest tests in `__tests__/` and/or
79+
Playwright component tests (`.spec.tsx` + `.story.tsx`); obsolete tests for
80+
removed code are deleted. Never leave a component or helper untested
81+
([testing.md](../rules/testing.md)).
82+
* A bug-fix test must fail before the fix and pass after.
83+
* Tests assert behaviour, not implementation details.
84+
85+
## 6. This repo's rules
86+
87+
Easy-to-miss invariants beyond the generic checks above:
88+
89+
* **Lint gate** ([CLAUDE.md](../../CLAUDE.md#commands)): `npm run lint` =
90+
eslint + markdownlint + stylelint. It is not auto-run — remind the author to
91+
run `npm run lint`, `npm run test:jest`, and `npm run test:playwright-ct:all`.
92+
* **Component layout** ([frontend.md](../rules/frontend.md)): every component
93+
folder has the `.jsx` + `index.js` barrel + `*.module.scss` + `_settings`/
94+
`_theme`/`_tools` SCSS partials + `README.md` + `__tests__/`. PropTypes, not
95+
TypeScript, in source.
96+
* **CSS Modules class naming** ([styling.md](../rules/styling.md)): `root`,
97+
`isRootXxx`, `hasRootXxx`, `isRootInXxx`, `isRootLayoutXxx`.
98+
* **Docs** ([docs.md](../rules/docs.md)): component docs live in the component's
99+
`README.md`; new doc pages are wired into `mkdocs.yml`.
100+
* **Git hygiene** ([git.md](../rules/git.md)): no push or remote change without
101+
approval; commit/PR subjects imperative English with backticked symbols and a
102+
trailing `(#issue)` when one exists; **no `Co-Authored-By`**. PR names land in
103+
the changelog.
104+
105+
## Output format
106+
107+
Group findings by severity. For each:
108+
`severity | file:line | rule/doc cited | what is wrong | concrete fix`.
109+
110+
```text
111+
## Blocking
112+
- [requirements] src/components/Foo/Foo.jsx:42 — acceptance criterion not implemented.
113+
- [tests] src/helpers/bar/bar.js:10 (testing.md) — new helper `bar` has no test.
114+
115+
## Non-blocking / nits
116+
- [design] src/components/Foo/Foo.jsx:7 (frontend.md) — ref not forwarded to root element.
117+
118+
## Reminders
119+
- Run `npm run lint`, `npm run test:jest`, and `npm run test:playwright-ct:all` before committing.
120+
```
121+
122+
End with a one-line verdict: APPROVE / APPROVE WITH NITS / REQUEST CHANGES.

.claude/rules/code.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Code
2+
3+
* Modify files only within defined scope, do not make changes that affect
4+
unrelated parts of the codebase, e.g. do not change unrelated comments,
5+
imports, code or documentation.
6+
* Keep changes minimal and focused.
7+
* Follow the project formatting and style sources:
8+
[.editorconfig](../../.editorconfig) (general),
9+
[.markdownlint.jsonc](../../.markdownlint.jsonc) (Markdown),
10+
[.eslintrc](../../.eslintrc) / [.eslintrc-ts](../../.eslintrc-ts)
11+
(JavaScript/TypeScript), [stylelint.config.js](../../stylelint.config.js)
12+
(SCSS).
13+
* Only fix linting/formatting issues in files you created or modified for the
14+
current task. Do not fix pre-existing issues outside that scope.
15+
* Keep comments simple and use terminology and language matching repository
16+
standards.
17+
* Revert unrelated changes. If they are worth keeping, ask the user whether to
18+
track them separately — either as a GitHub issue (propose a title and
19+
description first, and confirm before creating it) or, for small changes, on a
20+
separate branch without an issue.
21+
* Do not use one character long variable names or shortened names unless it is a
22+
common abbreviation.

.claude/rules/docs.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
paths:
3+
- "src/docs/**"
4+
- "src/components/**/README.md"
5+
- "src/helpers/**/README.md"
6+
- "README.md"
7+
---
8+
9+
# Documentation
10+
11+
## Commands
12+
13+
* Run `npm run markdownlint` after changes (add `-- --fix` to autofix).
14+
* Run `mkdocs build` and `mkdocs serve` to build and serve the documentation
15+
* To verify a rendered component or the docs previews in a real browser
16+
(navigate, click, screenshot, inspect the running docs site), drive host
17+
Chrome through the `chrome-host` MCP. See
18+
[AI Integration](../../src/docs/contribute/ai-integration.md).
19+
20+
See [Commands](../../CLAUDE.md#commands).
21+
22+
## Conventions
23+
24+
* Documentation is built with [Material for MkDocs][mkdocs-material] and
25+
[Docoff][docoff] (live, runnable component previews). Component docs live in
26+
each component's `README.md`; guides and foundations live under `src/docs/`.
27+
* New pages must be wired into the navigation in [mkdocs.yml](../../mkdocs.yml).
28+
* Use relative links between docs.
29+
30+
## Reference
31+
32+
* [General Guidelines › Documenting](../../src/docs/contribute/general-guidelines.md#documenting)
33+
34+
[mkdocs-material]: https://squidfunk.github.io/mkdocs-material/
35+
[docoff]: https://github.com/react-ui-org/docoff

.claude/rules/frontend.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
---
2+
paths:
3+
- "src/**/*.js"
4+
- "src/**/*.jsx"
5+
---
6+
7+
# Frontend (React component library)
8+
9+
## Commands
10+
11+
* If dependencies change, run `npm ci`.
12+
* Run `npm run eslint` after changes (add `-- --fix` to autofix).
13+
* To verify a rendered component or the docs previews in a real browser
14+
(navigate, click, screenshot, inspect the running docs site), drive host
15+
Chrome through the `chrome-host` MCP. See
16+
[AI Integration](../../src/docs/contribute/ai-integration.md).
17+
18+
## Stack
19+
20+
React UI is a themeable React component library, distributed as a UMD bundle
21+
(with separate CSS) and as ESM (consumers run their own SASS pipeline).
22+
Components are plain JavaScript / JSX (Babel, no TypeScript in the source) for
23+
React 18, validated with `prop-types`. TypeScript appears only in tests and type
24+
checks.
25+
26+
## Component structure
27+
28+
Each component lives in `src/components/<ComponentName>/` and follows this
29+
layout:
30+
31+
```text
32+
Button/
33+
Button.jsx # Component implementation (React.forwardRef + withGlobalProps)
34+
Button.module.scss # CSS Modules styles
35+
index.js # Re-exports default (withGlobalProps-wrapped) as named export
36+
_settings.scss # Component-level SCSS variables
37+
_theme.scss # CSS custom properties (design tokens)
38+
_tools.scss # SCSS mixins
39+
README.md # Docoff/MkDocs documentation with live previews
40+
helpers/ # Component-specific helper functions
41+
__tests__/
42+
Button.spec.tsx # Playwright visual + functional tests
43+
Button.story.tsx # Story components used as test fixtures
44+
_propTests/ # Reusable prop test generators (arrays of test cases)
45+
```
46+
47+
## Implementation pattern
48+
49+
Components are `.jsx` files (not `.tsx`) using PropTypes. They:
50+
51+
1. Use `React.forwardRef` to forward refs to the root HTML element.
52+
2. Are wrapped with `withGlobalProps(Component, 'ComponentName')` for global prop
53+
injection; the wrapped version is the default export.
54+
3. Use `useContext` to detect layout/group contexts (`FormLayoutContext`,
55+
`ButtonGroupContext`, `InputGroupContext`) and apply CSS class variants
56+
accordingly.
57+
4. Use the `classNames()` helper to conditionally combine CSS Module class names.
58+
5. Use `transferProps()` to pass through non-React HTML attributes to the root
59+
element.
60+
61+
Honour the [API Guidelines](../../src/docs/contribute/api.md) and
62+
[Composition](../../src/docs/contribute/composition.md) when shaping props and
63+
nesting.
64+
65+
## Styling
66+
67+
Component styles use SCSS with CSS Modules — see the [styling rule](styling.md).
68+
69+
## Tests
70+
71+
Components are covered by Jest unit tests and table-driven Playwright component
72+
tests — see the [testing rule](testing.md).

.claude/rules/git.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Git
2+
3+
## Skills
4+
5+
Use `/commit` to commit changes.
6+
7+
## Conventions
8+
9+
Full rules are in [General Guidelines › Git Workflow](../../src/docs/contribute/general-guidelines.md#git-workflow).
10+
11+
## Reference
12+
13+
* [General Guidelines › Git Workflow](../../src/docs/contribute/general-guidelines.md#git-workflow)

.claude/rules/safety-guards.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Safety guards
2+
3+
* Never modify files listed in [.gitignore](../../.gitignore) unless approved
4+
in a skill
5+
* Never modify any files outside the project root
6+
* Never run shell commands that can alter system state or access sensitive data
7+
when run on the host system
8+
* Never modify the git remote (e.g. `git push`) without explicit human approval
9+
* Never introduce new dependencies without explicit human approval

.claude/rules/styling.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
---
2+
paths:
3+
- "src/**/*.scss"
4+
- "src/**/*.css"
5+
---
6+
7+
# Styling
8+
9+
## Commands
10+
11+
Run `npm run stylelint` after changes (add `-- --fix` to autofix).
12+
13+
## Styling
14+
15+
Styles use SCSS with CSS Modules (`.module.scss`) with camelCase class names. A
16+
component's styles live next to it as `Foo.module.scss` and are imported as a
17+
module.
18+
19+
Class naming convention:
20+
21+
* `root` for the root element.
22+
* Modifiers follow `isRootXxx` (state), `hasRootXxx` (has feature),
23+
`isRootInXxx` (context), `isRootLayoutXxx` (layout variant).
24+
25+
`src/styles/` contains the global theming system: settings (variables), tools
26+
(mixins), and a large set of CSS custom properties for theming. Component SCSS
27+
files `@use` their own `_settings`, `_theme`, `_tools` partials plus the shared
28+
styles from `src/styles/`. Theme tokens are exposed as CSS custom properties.
29+
30+
## Reference
31+
32+
* [CSS Guidelines](../../src/docs/contribute/css.md)

.claude/rules/testing.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
---
2+
paths:
3+
- "**/*.spec.tsx"
4+
- "**/*.story.tsx"
5+
- "**/__tests__/**"
6+
- "tests/**"
7+
---
8+
9+
# Testing
10+
11+
## Commands
12+
13+
* Run all Jest unit tests with `npm run test:jest` (TS + JS). For a single file:
14+
`npm run test:jest:ts -- <file>` or `npm run test:jest:js -- <file>`.
15+
* Run all Playwright component tests with `npm run test:playwright-ct:all`; for
16+
one component, `npm run test:playwright-ct:all -- -- src/components/Button`.
17+
* Update Playwright snapshots with `npm run test:playwright-ct:all-with-update`.
18+
* Serve the report with `npm run test:playwright-ct:show-report`.
19+
20+
## Testing
21+
22+
Create/update tests for added or changed components and helpers, and remove
23+
obsolete tests when functionality is removed. Never leave a component or helper
24+
without tests. When fixing a bug, add a test that fails before the fix and
25+
passes after it.
26+
27+
### Organization
28+
29+
Jest unit/component tests are co-located in a component's `__tests__/` folder.
30+
31+
### Playwright component tests
32+
33+
`.spec.tsx` specs use a table-driven pattern:
34+
35+
* Import arrays of test cases from `_propTests/` directories and from shared
36+
`tests/playwright/propTests/`.
37+
* Each test case is `{ name, props, onBeforeTest?, onBeforeSnapshot? }`; custom
38+
field tests add `customFieldLayoutProps`, `customFieldProps`, etc.
39+
* `mixPropTests([...arrays])` generates the cartesian product of multiple prop
40+
arrays.
41+
* `propTests` from `tests/playwright/` provides standard reusable test sets
42+
(e.g. `layoutPropTest`, `sizePropTest`, `disabledPropTest`).
43+
* Snapshot images are stored alongside the spec file in
44+
`<ComponentName>.spec.tsx-snapshots/`.
45+
46+
**Story components** (`.story.tsx`) wrap the real component in a minimal fixture
47+
(sometimes inside a context provider) and are imported only by `.spec.tsx`
48+
files. Naming convention: `<ComponentName>ForTest`, `<ComponentName>ForRefTest`,
49+
`<ComponentName>ForFormLayoutTests` — the FormLayout story component is always
50+
last.
51+
52+
**Test describe structure:** `test.describe('ComponentName')`
53+
`test.describe('base')` (if present) → `visual` / `non-visual` /
54+
`functionality`; the `formLayout` describe is always the last block at the same
55+
level as `base`.
56+
57+
## Reference
58+
59+
* [Testing Guidelines](../../src/docs/contribute/testing-guidelines.md)

0 commit comments

Comments
 (0)