3 KiB
Frontend context
Read
ai/shared.mdfirst. 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
.vuefiles 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.
elementnotel) - 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 usecy.requestto 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.