129 lines
4.8 KiB
Markdown
129 lines
4.8 KiB
Markdown
# Frontend context
|
|
|
|
Read `ai/shared.md` first. This file covers frontend-specific rules.
|
|
|
|
## Project context
|
|
|
|
**Stack:** Vue 3.5, TypeScript 6, Vite 8, Vue Router 5, Pinia 4, npm.
|
|
|
|
**Location:** `frontend/website/`.
|
|
|
|
The frontend is a standalone application. Keep its source, dependencies,
|
|
development server, and production build independent from the backend unless
|
|
the user explicitly requests integration.
|
|
|
|
The scaffold uses:
|
|
|
|
- `src/App.vue` as the root component.
|
|
- `src/main.ts` to create the app and install the router and Pinia.
|
|
- `src/router/index.ts` for routes.
|
|
- `src/stores/` for Pinia stores.
|
|
- `@` as an alias for `src/` in both Vite and TypeScript.
|
|
|
|
There are no views, shared components, API layer, or configured test suite
|
|
yet. Cypress is installed as a frontend development dependency, but there is
|
|
no Cypress configuration or npm test script. Do not invent an architecture
|
|
before requested behavior establishes one.
|
|
|
|
## Package management and commands
|
|
|
|
Use npm and keep `package-lock.json` committed. Run commands from
|
|
`frontend/website/`.
|
|
|
|
Install dependencies in a fresh checkout or worktree:
|
|
|
|
```sh
|
|
direnv exec "$(git rev-parse --show-toplevel)" npm install
|
|
```
|
|
|
|
To start only the development server on the port assigned by the shell hook:
|
|
|
|
```sh
|
|
direnv exec "$(git rev-parse --show-toplevel)" \
|
|
npm run dev -- \
|
|
--host 127.0.0.1 \
|
|
--port "$VITE_PORT" \
|
|
--strictPort
|
|
```
|
|
|
|
`process-compose` starts the frontend as part of the full development stack.
|
|
The frontend remains directly accessible on `VITE_PORT`; Caddy does not proxy
|
|
it.
|
|
|
|
The available validation commands are:
|
|
|
|
```sh
|
|
direnv exec "$(git rev-parse --show-toplevel)" npm run format
|
|
direnv exec "$(git rev-parse --show-toplevel)" npm run lint
|
|
direnv exec "$(git rev-parse --show-toplevel)" npm run type-check
|
|
direnv exec "$(git rev-parse --show-toplevel)" npm run build
|
|
```
|
|
|
|
`npm run format` and `npm run lint` rewrite files. Review the resulting diff.
|
|
`npm run build` runs type checking and the production build. Build output
|
|
under `dist/` is generated and ignored.
|
|
|
|
## Vue conventions
|
|
|
|
- Use the Composition API and `<script setup lang="ts">`.
|
|
- Use PascalCase component and view filenames.
|
|
- Put reusable components under `src/components/`.
|
|
- Put route-level views under `src/views/` and register them in
|
|
`src/router/index.ts`.
|
|
- Keep page, component, composable, and store responsibilities distinct.
|
|
- Prefer small components with explicit props and emitted events.
|
|
- Keep component styles scoped until the project adopts a deliberate global
|
|
styling system.
|
|
- Use setup-style Pinia stores named `useXxxStore`.
|
|
- Inspect similar files before introducing a new component, composable,
|
|
store, or data-access pattern.
|
|
|
|
## TypeScript
|
|
|
|
- Preserve the strict TypeScript configuration and
|
|
`noUncheckedIndexedAccess`.
|
|
- Do not use `any`. Model unknown external values as `unknown`, then narrow or
|
|
validate them.
|
|
- Derive types from runtime schemas if the project adopts a schema library.
|
|
Do not maintain a hand-written type that can drift from its schema.
|
|
- Validate payloads at trust boundaries, especially backend responses and
|
|
user-submitted forms.
|
|
- Keep request and response types close to the API or store boundary that
|
|
owns them.
|
|
- Keep the `@` alias aligned across Vite, TypeScript, and any future test
|
|
configuration.
|
|
|
|
## State and API access
|
|
|
|
- Use Pinia for shared client state. Keep component-local state in components.
|
|
- Keep server requests and response transformation at an API or store
|
|
boundary, not scattered through presentation components.
|
|
- Represent loading, empty, success, validation-error, and unexpected-error
|
|
states explicitly.
|
|
- Do not cast unchecked JSON directly to an application interface.
|
|
- Keep read and write payload types separate when their shapes differ.
|
|
|
|
## Testing
|
|
|
|
Cypress is installed, but no frontend test configuration or test script
|
|
exists yet.
|
|
|
|
- Do not invent test commands or claim frontend tests passed.
|
|
- New frontend behavior must still follow the shared test-first workflow.
|
|
Establish the smallest appropriate test setup before implementing behavior
|
|
that needs it.
|
|
- Unit tests should cover pure transformations, composables, and store logic.
|
|
- Component tests should cover rendering, events, form behavior, and
|
|
conditional UI.
|
|
- End-to-end tests should cover routing, multi-page flows, and request wiring.
|
|
- Prefer the cheapest layer that proves the behavior.
|
|
- Mock backend requests in frontend tests. Do not retest backend persistence,
|
|
validation, authentication, or mail behavior through the frontend.
|
|
|
|
## Before completing frontend work
|
|
|
|
- Run the focused test while developing once test tooling exists.
|
|
- Run the formatter, linter, type checker, production build, and every
|
|
configured test script affected by the change.
|
|
- Do not claim a green gate when a command fails. Report a baseline or
|
|
environmental failure precisely.
|