You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CLAUDE.md
+19-4Lines changed: 19 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -74,9 +74,13 @@ Actual `mvn` invocations do **not** run in-process. `DesktopService` (per-OS imp
74
74
75
75
Frontend lives in `src/main/assets/` — Vite root, sources under `src/`:
76
76
-`api/` — one module per endpoint group over a shared `fetch` wrapper (`http.ts`, base `/api`). `agrest.ts` builds the Agrest `include`/`sort`/`cayenneExp` parameters; `types.ts` mirrors the Java enums and entity shapes.
77
-
-`domain/` — pure, unit-tested logic with no Vue imports: `releaseBoard.ts` holds the release/rollback state machine, `version.ts` the version arithmetic. **Changes to board button visibility belong here, with a test.**
-`domain/` — pure, unit-tested logic with no Vue imports: `releaseBoard.ts` holds the release/rollback state machine, `version.ts` the version arithmetic, `nav.ts` the nav derivation, `labelColor.ts` the GitHub label contrast maths. **Changes to board button visibility belong here, with a test** — that means `stageActions()`, which composes the predicates into the ordered list of buttons a cell offers, not just the predicates themselves.
78
+
-`composables/` — shared reactive state. `useAsyncResource` is the one way to load data (fetch + `loading` + `error`); `useAgrestList` adds URL-synced sort/filter on top of it. Also `useJobStatus`, `useReleaseBoard`, `useSession`, `useCacheWarmup`, `useReleaseSummary`.
79
+
-`components/`, `views/`, `styles/`, `router/` (`routes.ts` is the route table; `index.ts` builds the router).
80
+
81
+
**The route table is the single source of truth for paths, page headings and the nav.** A route's `meta.title` is its `<h1>` (via `PageShell`) and its document title; `meta.nav` puts it in `AppNav`. Views never pass a title, and cross-page links use route `name`, never a literal path.
82
+
83
+
`src/styles/` — `_bs.scss` is the only file that may name `bootstrap/scss/bootstrap`; it configures Bootstrap through `@forward ... with`. Overrides go there as Sass variables, because Bootstrap regenerates its whole `--bs-*` set per `data-bs-theme` and so gets dark mode for free. The `--app-*` tokens in `_tokens.scss` deliberately hold **no colours**, since an app-defined colour would need a hand-written dark twin.
80
84
81
85
Vite emits to `target/classes/static/ui/` with `base: '/ui/'`; Jetty serves it from `classpath:static`. Nothing else may be written into `target/classes/static/` — the `ui/` subdirectory is what makes `emptyOutDir` safe.
JUnit 5 (`bootique-junit`) + Mockito. Tests instantiate services directly and hand-build a Cayenne `ServerRuntime` from `cayenne/cayenne-project.xml` rather than booting the full app. Hand-written `Mock*` doubles (e.g. `MockPreferenceService`, `MockGitHubApi`, `MockReleasePersistentService`) live alongside the tests and are the preferred way to fake collaborators. Some tests are `@Disabled` (they depend on local git/maven state) — don't assume the whole suite runs clean offline. Test fixtures (sample POMs/repos) are under `src/test/resources/`.
89
93
90
-
Frontend tests are Vitest over `src/main/assets/src/domain/*.spec.ts`, wired into the Maven `test` phase (skipped by `-DskipTests`). They cover the release-board predicates and version arithmetic— the logic worth protecting. Components are not mounted in tests; `vue-tsc --noEmit` runs as part of `npm run build`, so a type error fails the Maven build.
94
+
Frontend tests are Vitest over `src/main/assets/src/**/*.spec.ts`, wired into the Maven `test` phase (skipped by `-DskipTests`). They cover the releaseboard, version arithmetic, nav derivation, label contrast and `useAsyncResource`— the logic worth protecting. **Components are deliberately not mounted**: the environment is `node`, and component tests here would assert Bootstrap class strings rather than behaviour. Push logic into `domain/` instead. `vue-tsc --noEmit` runs as part of `npm run build` with `strictTemplates`, so a type error — including a component used but not imported — fails the Maven build.
91
95
92
96
## Coding standards
93
97
@@ -96,6 +100,17 @@ Frontend tests are Vitest over `src/main/assets/src/domain/*.spec.ts`, wired int
96
100
- tests should cover public contracts, not internal implementation aspects
97
101
- pure utility methods that use single Cayenne object's data are good candidates for inclusion in the cayenne layer
98
102
103
+
### Frontend conventions
104
+
105
+
These exist because each was violated in more than one way before, not as style preference:
106
+
107
+
-**Destructure composables at the top of `<script setup>`, renaming on the way out where names collide. A template never contains `.value`.**
108
+
-**One loading idiom per situation**: `LoadingBar` (page-level, a listing is being fetched), `JobProgress` (a server batch job with a real percentage), `InlineSpinner` (a region with nothing to show yet), `BusyButton` (a single action in flight). Nothing else hand-rolls a spinner.
109
+
-**One error surface**: `AppAlert`, inside modals as much as on pages. Guidance is not an error — it belongs in an `EmptyState`, not in a red banner.
110
+
-**Tables go through `TableFrame`**, which owns the card frame and the canonical classes. `ModuleTable` covers every module listing; omit `selected` for a read-only one.
111
+
-**Modals that ask for a decision use `ConfirmModal`**; `AppModal` is the primitive underneath it.
112
+
- Badges and pills use `chip-*` (`_chips.scss`), never Bootstrap's `text-bg-*`, whose `light` variant is not theme-scoped and glares in dark mode.
0 commit comments