49 lines
2.4 KiB
Markdown
49 lines
2.4 KiB
Markdown
# Frontend context
|
|
|
|
> Read `ai/shared.md` first. This file only covers frontend-specific rules.
|
|
|
|
## Project Context
|
|
|
|
**Stack:** vanilla PHP templates in `views/templates/`, plain ES JavaScript in
|
|
`public/js/`, no framework, no build step. Cypress 15 for E2E.
|
|
**Entry point:** `public/index.php` (Slim app); page templates are rendered
|
|
via the existing templating layer.
|
|
|
|
## Code patterns
|
|
|
|
- Look at existing pages (`home.php`/`home.js`, `text.php`/`text.js`,
|
|
`today.php`/`today.js`) for reference before writing anything
|
|
- **Templates:** `views/templates/<page>.php`, one file per page
|
|
- **Page JS:** `public/js/<page>.js`, one file per page, paired with the
|
|
matching template
|
|
- **Testing:** Cypress E2E only, mirror existing `cypress/e2e/*.cy.js` style
|
|
(note: this project uses `.cy.js`, not `.cy.ts`)
|
|
- **Imports / script tags:** keep at the top of the file
|
|
- **Variable names:** explicit, descriptive (e.g. `text` not `t`)
|
|
|
|
## Pre-commit
|
|
|
|
No JS formatter or linter is configured yet; format manually for consistency
|
|
with surrounding files. (TODO: wire up format/lint when added.)
|
|
|
|
## Note on commit granularity
|
|
|
|
Frontend changes are often a template plus its page-level JS counterpart -
|
|
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 texts — owner only` | `// loads texts - owner only` |
|
|
| Inline `<script>` in templates | `<script>doStuff()</script>` in a `.php` template | put logic in `public/js/<page>.js`, load via `<script src=...>` |
|
|
| Hardcoded admin URLs in user-facing JS | `fetch('/api/admin/...')` from a non-admin page JS | call user-scoped endpoints from user pages, admin endpoints only from admin pages |
|
|
| Cypress test logging in as the wrong role | `cy.loginAsAdmin()` in a non-admin spec | match the role to the page under test (`loginAsUser` for `/home`, `/texts`; `loginAsAdmin` for `/admin/*`) |
|
|
| `cy.request` in E2E tests | `cy.request('/api/...')` to set up state or assert | tests must exercise UI - drive via `cy.visit`/`cy.get`; if seeding is needed, add it to backend seed data |
|
|
|
|
When generating code, scan the diff for these patterns before writing it
|
|
to disk.
|