mirror of
https://github.com/rommapp/romm.git
synced 2026-06-27 22:35:57 +00:00
cleanup
This commit is contained in:
@@ -17,7 +17,7 @@ Related skills: `frontend-v2-theming` (tokens/colors), `frontend-v2-input` (focu
|
||||
|
||||
1. **v1 is frozen.** Don't touch `src/views/`, `src/components/`, `src/console/`, `src/layouts/`. When coexistence forces a v2 fork of a store/composable/util, annotate the v1 export with `@deprecated` pointing at the v2 replacement.
|
||||
2. **Three component tiers** (below).
|
||||
3. **Shared resources are canonical.** Pinia stores, API services, OpenAPI types (`src/__generated__/`), locales, utils — v2 *imports* them, never forks them. Additive changes to shared resources are allowed; changing a shared store API to work around a v2 call-site issue is not.
|
||||
3. **Shared resources are canonical.** Pinia stores, API services, OpenAPI types (`src/__generated__/`), locales, utils — v2 _imports_ them, never forks them. Additive changes to shared resources are allowed; changing a shared store API to work around a v2 call-site issue is not.
|
||||
4. **TypeScript strict.** Zero `any` (justify with a comment if unavoidable). No `as unknown as ...`; fix the source or define an intermediate type.
|
||||
5. **Universal substitution.** When an `R*` primitive exists, use it. If it doesn't, create or extend it. Never drop to raw HTML or raw Vuetify when a primitive applies.
|
||||
6. **Wrapper contract.** Wrappers around Vuetify use `defineOptions({ inheritAttrs: false })` + `v-bind="$attrs"` + slot passthrough, and accept every prop/slot of the wrapped component.
|
||||
@@ -66,16 +66,16 @@ If any fails: **shared composite** if generic across features, **feature composi
|
||||
|
||||
```ts
|
||||
// 1. External
|
||||
import { computed, ref } from "vue";
|
||||
// 2. v2 primitives
|
||||
import { RBtn, RDialog } from "@v2/lib";
|
||||
// 3. v2 composables / shared
|
||||
import { useCan } from "@/v2/composables/useCan";
|
||||
// 4. v2 feature siblings
|
||||
import GameCard from "@/v2/components/GameCard.vue";
|
||||
import { computed, ref } from "vue";
|
||||
import type { SimpleRom } from "@/__generated__";
|
||||
// 5. Canonical shared resources
|
||||
import storeAuth from "@/stores/auth";
|
||||
import type { SimpleRom } from "@/__generated__";
|
||||
// 4. v2 feature siblings
|
||||
import GameCard from "@/v2/components/GameCard.vue";
|
||||
// 3. v2 composables / shared
|
||||
import { useCan } from "@/v2/composables/useCan";
|
||||
```
|
||||
|
||||
- `@v2/lib` — primitives barrel. `@/v2/...` — anything else under v2. `@/...` — canonical shared resources. Never relative paths (`../../foo`) when an alias exists.
|
||||
@@ -109,7 +109,7 @@ import type { SimpleRom } from "@/__generated__";
|
||||
5. Don't add backwards-compat shims inside v2: delete removed code; no `// removed`, no renamed-but-unused exports, no deprecated wrappers that just call the new function.
|
||||
6. Don't write redundant tests; don't touch v1; never `--no-verify` on commits.
|
||||
|
||||
**Allowed (often misread):** modifying shared stores/services/utils *additively*; creating v2-only composables; importing from `src/__generated__/`.
|
||||
**Allowed (often misread):** modifying shared stores/services/utils _additively_; creating v2-only composables; importing from `src/__generated__/`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ Don't push state into `useUISettings` "so it persists" — follow the rule above
|
||||
|
||||
- Use the **`RForm` primitive** (wraps `v-form`: Enter-to-submit when valid, scroll-to-first-error after a failed `validate()`). **Never use `v-form` directly.**
|
||||
- **Native Vuetify rules** — no Zod/Yup. Rules are arrays of `(v) => true | string`.
|
||||
- **Reusable rules** in `src/v2/utils/validation.ts` (`required(msg?)`, `email`, `asciiOnly`, `lengthBetween`, `usernameLength/Chars`, `passwordLength`). Utility code *may* call `i18n.global.t(...)` (the no-i18n rule covers lib primitives, not utils).
|
||||
- **Reusable rules** in `src/v2/utils/validation.ts` (`required(msg?)`, `email`, `asciiOnly`, `lengthBetween`, `usernameLength/Chars`, `passwordLength`). Utility code _may_ call `i18n.global.t(...)` (the no-i18n rule covers lib primitives, not utils).
|
||||
- **Submit pattern:** `await formRef.value?.validate()` before the API call; submit button uses `:loading="submitting"`; errors → snackbar; field errors stay in-place via `:error-messages`.
|
||||
|
||||
## G. Permissions
|
||||
|
||||
@@ -13,12 +13,12 @@ description: Theming, design tokens, colors, and visual language in the RomM v2
|
||||
|
||||
`src/v2/tokens/index.ts` is the source. It feeds two consumers:
|
||||
|
||||
- **`src/v2/styles/tokens.css`** — *generated* by `scripts/build-tokens.ts` (`npm run build:tokens`, hooked into `predev`/`prebuild`). **Do not hand-edit.** This is how the vast majority of tokens are consumed: `var(--r-color-...)` in CSS.
|
||||
- **`src/v2/styles/tokens.css`** — _generated_ by `scripts/build-tokens.ts` (`npm run build:tokens`, hooked into `predev`/`prebuild`). **Do not hand-edit.** This is how the vast majority of tokens are consumed: `var(--r-color-...)` in CSS.
|
||||
- **Direct JS/TS imports** of named exports (`colorCanvas`, `colorCoverArt`, `layout`, …) for the few cases needing a token value in JavaScript — baking colors into an SVG string (`utils/covers`), canvas/QR backgrounds (`Player/Ruffle.vue`, `ShowQRCodeDialog`), and the virtualiser's pixel math (`Gallery/listColumns` reading `layout`).
|
||||
|
||||
v2 has **no Vuetify theme of its own.** `tokens.css` emits a palette block per theme under `.r-v2.r-v2-dark` / `.r-v2.r-v2-light`; `RomM.vue` toggles those classes on `<html>`. v2 surfaces never read Vuetify's runtime theme.
|
||||
|
||||
> Caveat: a wrapped Vuetify component still resolves `color="primary"` against Vuetify's *own* registered themes (`src/plugins/vuetify.ts`, sourced from v1's `@/styles/themes`). They mirror the brand tokens by hand (both `#8B74E8`), so they line up, but it's a parallel source. **Prefer `var(--r-...)` over the `color` prop.**
|
||||
> Caveat: a wrapped Vuetify component still resolves `color="primary"` against Vuetify's _own_ registered themes (`src/plugins/vuetify.ts`, sourced from v1's `@/styles/themes`). They mirror the brand tokens by hand (both `#8B74E8`), so they line up, but it's a parallel source. **Prefer `var(--r-...)` over the `color` prop.**
|
||||
|
||||
### Adding a new token
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ Run the checks that match what you touched. **Static checks don't prove a featur
|
||||
Run from `frontend/`:
|
||||
|
||||
1. `npm run typecheck` — zero errors (`vue-tsc --noEmit`).
|
||||
2. `npm run lint` *(if present)* / ESLint clean. Trunk also runs ESLint + Prettier in CI.
|
||||
2. `npm run lint` _(if present)_ / ESLint clean. Trunk also runs ESLint + Prettier in CI.
|
||||
3. `npm run test` — zero failures (Vitest + happy-dom; runs unit tests **and** every `/lib` story's `play()` via `composeStories`).
|
||||
4. `npm run build` — zero failures (CI sanity check).
|
||||
|
||||
|
||||
44
CLAUDE.md
44
CLAUDE.md
@@ -1,21 +1,23 @@
|
||||
# RomM — Repository Guide for Contributors & Agents
|
||||
|
||||
RomM is a self-hosted ROM manager and player: scan a game library off disk, enrich it with metadata from 10+ providers, browse it in a web UI, and play in the browser. This file orients anyone working in the repo — humans and AI agents alike. **Many features here are written by outside contributors using coding agents**, so this guide is written to be actioned without prior context.
|
||||
RomM is a self-hosted ROM manager and player: scan a game library off disk, enrich it with metadata from 10+ providers, browse it in a web UI, and play in the browser. This file orients anyone working in the repo — humans and AI agents alike.
|
||||
|
||||
> **Official language:** all code, comments, identifiers, `.md` files, and commit/PR messages are in **English**. Always.
|
||||
> **Official language:** outside of language files, all code, comments, identifiers, `.md` files, and commit/PR messages are in **English**. Always.
|
||||
>
|
||||
> **No em-dashes:** never use em-dashes (—) when writing comments or text. Use commas, parentheses, or separate sentences instead.
|
||||
|
||||
---
|
||||
|
||||
## The stack at a glance
|
||||
|
||||
| | Backend | Frontend |
|
||||
| --- | --- | --- |
|
||||
| Path | `backend/` | `frontend/` |
|
||||
| Language | Python 3.13+ | TypeScript 5.7 (Vue 3) |
|
||||
| Framework | FastAPI, SQLAlchemy 2.0, Alembic | Vue 3 + Vite, Vuetify, Pinia, Vue Router |
|
||||
| Infra | Redis + RQ (jobs/cache/sessions), Socket.IO | vue-i18n, Socket.IO client |
|
||||
| DB | MariaDB (default), MySQL, PostgreSQL | — |
|
||||
| Tooling | `uv`, pytest, Trunk (ruff/black/isort/mypy) | `npm`, vue-tsc, ESLint, Vitest, Storybook |
|
||||
| | Backend | Frontend |
|
||||
| --------- | ------------------------------------------- | ----------------------------------------- |
|
||||
| Path | `backend/` | `frontend/` |
|
||||
| Language | Python 3.13+ | TypeScript 5.7 (Vue 3) |
|
||||
| Framework | FastAPI, SQLAlchemy 2.0, Alembic | Vue 3 + Vite, Vuetify, Pinia, Vue Router |
|
||||
| Infra | Redis + RQ (jobs/cache/sessions), Socket.IO | vue-i18n, Socket.IO client |
|
||||
| DB | MariaDB (default), MySQL, PostgreSQL | — |
|
||||
| Tooling | `uv`, pytest, Trunk (ruff/black/isort/mypy) | `npm`, vue-tsc, ESLint, Vitest, Storybook |
|
||||
|
||||
The frontend talks to the backend over `/api/*` (REST) and `/ws` (Socket.IO). TypeScript types are **generated** from the backend's OpenAPI schema into `frontend/src/__generated__/` — the backend is the single source of truth for API shapes.
|
||||
|
||||
@@ -41,15 +43,15 @@ v2 has a detailed constitution, split across focused skills (below). **Read the
|
||||
|
||||
These live in `.claude/skills/` and carry the detailed rules. Invoke the one that matches what you're doing:
|
||||
|
||||
| Skill | When |
|
||||
| --- | --- |
|
||||
| `frontend-v2-components` | Building/editing any v2 component — tiers (lib/shared/feature), file & SFC conventions, barrels, anti-patterns. |
|
||||
| `frontend-v2-theming` | Colors, tokens, light/dark themes, visual language — and the **zero-hex-literal** policy. |
|
||||
| `frontend-v2-input` | Interactive components, focus/spatial navigation, gamepad/keyboard, breakpoints & responsive layout. |
|
||||
| `frontend-v2-patterns` | Feature behavior — errors/snackbars, loading, sockets, state persistence, pagination, forms, permissions, destructive confirmations. |
|
||||
| `frontend-i18n` | Any user-visible string or change under `frontend/src/locales/**`. |
|
||||
| `backend-development` | Endpoints, handlers, models, schemas, metadata adapters, tasks, migrations under `backend/`. |
|
||||
| `pre-pr-verification` | Before committing / opening a PR / declaring done — the checks that keep CI green. |
|
||||
| Skill | When |
|
||||
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `frontend-v2-components` | Building/editing any v2 component — tiers (lib/shared/feature), file & SFC conventions, barrels, anti-patterns. |
|
||||
| `frontend-v2-theming` | Colors, tokens, light/dark themes, visual language — and the **zero-hex-literal** policy. |
|
||||
| `frontend-v2-input` | Interactive components, focus/spatial navigation, gamepad/keyboard, breakpoints & responsive layout. |
|
||||
| `frontend-v2-patterns` | Feature behavior — errors/snackbars, loading, sockets, state persistence, pagination, forms, permissions, destructive confirmations. |
|
||||
| `frontend-i18n` | Any user-visible string or change under `frontend/src/locales/**`. |
|
||||
| `backend-development` | Endpoints, handlers, models, schemas, metadata adapters, tasks, migrations under `backend/`. |
|
||||
| `pre-pr-verification` | Before committing / opening a PR / declaring done — the checks that keep CI green. |
|
||||
|
||||
---
|
||||
|
||||
@@ -69,15 +71,17 @@ These live in `.claude/skills/` and carry the detailed rules. Invoke the one tha
|
||||
**Setup:** see `DEVELOPER_SETUP.md`. Docker path is `cp env.template .env` → `docker compose build` → `docker compose up -d` (app at `http://localhost:3000`).
|
||||
|
||||
**Backend** (`cd backend`):
|
||||
|
||||
```bash
|
||||
uv sync --all-extras --dev # install
|
||||
uv run python3 main.py # run (migrations auto-apply)
|
||||
uv run main.py # run (migrations auto-apply)
|
||||
uv run pytest [path/file] # test (subset) — or -vv for all
|
||||
uv run alembic revision --autogenerate -m "msg" # new migration (then HAND-REVIEW)
|
||||
uv run alembic upgrade head # apply migrations
|
||||
```
|
||||
|
||||
**Frontend** (`cd frontend`):
|
||||
|
||||
```bash
|
||||
npm install # install (Node 24)
|
||||
npm run dev # dev server :3000
|
||||
|
||||
Reference in New Issue
Block a user