# Frontend context

> Read `ai/shared.md` first. This file only covers frontend-specific rules.

## Project Context

**Stack:** Vue 3 (beta) + Vite + TypeScript + Pinia + vue-router. Tooling:
oxlint, oxfmt, eslint. Cypress 15 for E2E (provided by the Nix devshell;
project-level config still to be wired up - see Testing below).
**Entry point:** `frontend/rabbi_gerzi/src/main.ts`; root component
`src/App.vue`; routes in `src/router/`; stores in `src/stores/`.

All frontend paths below are relative to `frontend/rabbi_gerzi/`.

## Code patterns

- Look at existing files for reference before writing anything
- **Components:** SFC `.vue` files using `<script setup lang="ts">` and
  `<style scoped>`
- **Stores:** Pinia, one per domain area, under `src/stores/`
- **Routes:** declared in `src/router/index.ts`
- **Imports:** keep at the top of the file
- **Variable names:** explicit, descriptive (e.g. `element` not `el`)
- **Line width:** 80 columns, same as PHP

## Testing

- Cypress E2E only, at `frontend/rabbi_gerzi/cypress/e2e/*.cy.ts`
- Cypress is available via the Nix devshell; project-level config
  (`cypress.config.ts`, `cypress/` folder) still needs to be wired up.
  Add it when the first E2E test lands and remove this note.
- Tests must exercise the UI - drive via `cy.visit` / `cy.get`. Do not
  use `cy.request` to set up state or assert; if seeding is needed, add
  it via backend seed data.
- Role matching: log in as the role appropriate to the page under test
  (e.g. admin spec uses admin login, user spec uses user login).

## Pre-commit

Run from `frontend/rabbi_gerzi/`:

- `npm run format` (oxfmt)
- `npm run lint` (oxlint + eslint)
- `npm run type-check` (vue-tsc)

All three must pass before committing.

## Note on commit granularity

A new view is often a `.vue` SFC plus a Pinia store plus a route entry -
commit them together as a single logical unit, per the "one logical
change per commit" rule in `shared.md`.

## LLM anti-patterns

Constructs LLMs default to that this project forbids on the frontend.

| Anti-pattern | Forbidden | Required |
|---|---|---|
| Short variable name | `t`, `n`, `res`, `req`, `e`, `el`, `ev` | `text`, `node`, `response`, `request`, `submitEvent`, `element`, `clickEvent` |
| Em dash in code/comments | `// loads sets — owner only` | `// loads sets - owner only` |
| Options API | `export default { data() { ... } }` | `<script setup lang="ts">` with composition API |
| `any` type | `const value: any = ...` | concrete type, or `unknown` with a narrowing guard |
| Default parameter value | `function load(limit: number = 10)` | `function load(limit: number)` - every call site passes it |
| Unscoped styles | `<style>` (leaks globally) | `<style scoped>` |
| `cy.request` in E2E | `cy.request('/api/...')` to set up state | drive via UI; seed via backend |
| Cypress login role mismatch | logging in as wrong role for the page | match the role to the page under test |

When generating code, scan the diff for these patterns before writing it
to disk.
