Remove Livewire docs, add Vue SPA frontend docs, document log-masking runbook
- Delete `.claude/rules/livewire.md` (Livewire is vestigial – only starter-kit auth screens remain) - Add `.claude/rules/frontend.md` documenting Vue 3 SPA stack, router, composables, search-URL mirroring, and Leaflet integration - Add `docs/ops/nginx-log-masking.md` runbook for redacting lat/lng from Nginx access/error logs and PHP-FPM on IONOS VPS - Update `CLAUDE.md` and `architecture.md` to reflect Vue SPA as primary frontend, REST API as backend contract, and Livewire's reduced role - Note stale service names in legacy domain docs (`scoring.md`, `prediction.md`, `notifications.md`) now refactored into `Services/Forecasting/`, `Services/StationSearch/`, and `PlanFeatures`
This commit is contained in:
74
.claude/rules/frontend.md
Normal file
74
.claude/rules/frontend.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Frontend — Vue 3 SPA
|
||||
|
||||
The entire user-facing app (landing, station search, dashboard, settings) is a
|
||||
**Vue 3 single-page application** under `resources/js/`. It is served from the
|
||||
Blade shell `resources/views/app.blade.php` via the SPA catch-all in
|
||||
`routes/web.php` and consumes the REST API (`routes/api.php`). There is **no
|
||||
Livewire in the product UI** — do not add Livewire / Volt / Alpine components for
|
||||
new features. Build Vue.
|
||||
|
||||
## Stack
|
||||
|
||||
- Vue 3.5 with `<script setup>` (Composition API), Vue Router 4 (`createWebHistory`)
|
||||
- Vite 8 (`npm run dev` / `npm run build`), `@vitejs/plugin-vue`
|
||||
- Tailwind CSS v4 (`@tailwindcss/vite`)
|
||||
- Leaflet for maps, iconify-icon + Lucide for icons, axios for HTTP
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
resources/js/
|
||||
├── app.js # Entry — createApp(App).use(router).mount('#app')
|
||||
├── App.vue # Root — <RouterView/>, fetches the user on mount
|
||||
├── axios.js # Configured axios instance (baseURL '/api', XSRF + credentials)
|
||||
├── router/index.js # Routes + requiresAuth guard (redirects to /login)
|
||||
├── views/
|
||||
│ ├── Home.vue # Landing + station search (mirrors state to the URL query)
|
||||
│ └── dashboard/ # Overview, SavedStations, Preferences, settings/{Profile,Security,Appearance}
|
||||
├── components/ # LeafletMap, StationCard, StationList, PredictionCard/Full,
|
||||
│ # PostSearchFilters, UpsellBanner, landing/*
|
||||
├── composables/ # useAuth, useStations, useSavedStations
|
||||
└── constants/ # fuelTypes.js — shared fuel-type source of truth (front + back)
|
||||
```
|
||||
|
||||
## Conventions
|
||||
|
||||
- **Composition API + `<script setup>` only.** No Options API.
|
||||
- **All server state goes through composables** that call the configured `api`
|
||||
axios instance (`axios.js`) — never `fetch()` or a bare `axios` call inside a
|
||||
component.
|
||||
- **Auth is cookie/session (Sanctum SPA mode).** axios is configured with
|
||||
`withCredentials` + `withXSRFToken`; don't add bearer-token handling.
|
||||
- Route guards live in `router/index.js` (`meta.requiresAuth`). Hard navigations
|
||||
(`/login`, `/logout`) use `window.location.href`, not the router.
|
||||
- Keep business logic in the API / Services. Vue components render and orchestrate.
|
||||
|
||||
## Search & the shareable URL
|
||||
|
||||
`Home.vue` is the search surface. Search params (postcode **or** lat/lng,
|
||||
`fuel_type`, `radius`, `sort`) are mirrored into the **URL query** via
|
||||
`router.push` (`queryFromParams`) so searches are shareable and bookmarkable, and
|
||||
restored on load (`paramsFromQuery`). Because the URL is shareable, **any
|
||||
coordinates written to it must be coarsened** — a precise GPS pair from "Use my
|
||||
location" (`HeroSearch.vue` → browser Geolocation) would otherwise broadcast the
|
||||
sharer's exact position to everyone they send the link to.
|
||||
|
||||
## Maps (Leaflet)
|
||||
|
||||
`components/LeafletMap.vue` wraps Leaflet directly (Leaflet is a plain JS library,
|
||||
not a Vue plugin). Station and user markers and the Google-Maps directions links
|
||||
are built from `station.lat` / `station.lng`; the user marker comes from the
|
||||
browser Geolocation API.
|
||||
|
||||
## Prediction
|
||||
|
||||
The fuel prediction ships **inside** the `/api/stations` response under the
|
||||
`prediction` key and is rendered by `PredictionCard.vue` / `PredictionFull.vue`
|
||||
(`useStations` reads `response.data.prediction`). See `prediction.md` for the
|
||||
payload shape and the tier gate.
|
||||
|
||||
---
|
||||
paths:
|
||||
- "resources/js/**/*.vue"
|
||||
- "resources/js/**/*.js"
|
||||
---
|
||||
Reference in New Issue
Block a user