| # Frontend β Vue 3 SPA |
|
|
| Single-page application for the PhD-research demo site. Vue 3 + Vite + Pinia + Fomantic UI; talks to the Django backend at `/api/v1/*`. Built once into `dist/` at image-build time and served by WhiteNoise on the same origin as the API in production. |
|
|
| ## Tech stack |
|
|
| - **Vue 3** (`^3.5.32`) β composition-API components. |
| - **Vite 8** β dev server and production bundler. |
| - **Vue Router 4** β `createWebHistory` mode, lazy-loaded demo views, wildcard 404. |
| - **Pinia 3** β store-per-feature. |
| - **axios** β JSON HTTP client for discovery / non-streaming endpoints. |
| - **Fomantic UI CSS** β visual primitives (buttons, segments, dropdowns, etc.). |
|
|
| ## Quick start |
|
|
| From this directory: |
|
|
| ```bash |
| npm install |
| npm run dev |
| ``` |
|
|
| Vite serves on `http://localhost:5173`. The Django backend must also be running on `http://localhost:8000` (see [the local-development guide](../../docs/guides/local-development.md)). |
|
|
| Production build: |
|
|
| ```bash |
| npm run build |
| # emits dist/, copied into the Docker image at /app/backend/dist |
| ``` |
|
|
| ## Project layout |
|
|
| ``` |
| src/frontend/src/ |
| βββ main.js # bootstrap (Pinia, router, theme) |
| βββ App.vue # shell: NavBar, RouterView, GraphBackground |
| βββ api/ # axios client + per-method API wrappers |
| β βββ client.js |
| β βββ coins.js |
| β βββ graphGeneration.js |
| β βββ kgAnomaly.js |
| β βββ health.js |
| βββ composables/ |
| β βββ useSseStream.js # SSE client for streaming inference |
| βββ stores/ # Pinia stores |
| β βββ coinsDemo.js |
| β βββ multiproxanDemo.js |
| β βββ kgAnomalyDemo.js |
| β βββ theme.js |
| βββ router/index.js # routes + lazy demo loading + wildcard 404 |
| βββ views/ # page-level components |
| β βββ HomeView.vue |
| β βββ CVView.vue |
| β βββ NotFoundView.vue |
| β βββ demos/{Coins,MultiProxAn,KgAnomaly}View.vue |
| βββ components/ # feature-grouped components (coins/, multiproxan/, kganomaly/, cv/, home/, layout/, common/, background/) |
| βββ data/cv.js # static CV data |
| βββ styles/ # tokens, theme, responsive helpers |
| ``` |
|
|
| For a full walk-through of every store, composable and component group, see [`docs/reference/frontend-modules.md`](../../docs/reference/frontend-modules.md). |
|
|
| ## Environment variables |
|
|
| | File | Purpose | Value | |
| |---|---|---| |
| | `.env.development` | Dev β Vite reads this when running `npm run dev`. | `VITE_API_BASE_URL=http://localhost:8000` | |
| | `.env.production` | Prod β Vite reads this when running `npm run build`. | `VITE_API_BASE_URL=` (empty β same-origin) | |
|
|
| Both `src/api/client.js` and `src/composables/useSseStream.js` compute their base URL as: |
|
|
| ```js |
| `${import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:8000'}/api/v1` |
| ``` |
|
|
| The `??` (not `||`) is intentional β an empty string from `.env.production` must survive so the deployed SPA hits a same-origin `/api/v1`. |
|
|
| ## API conventions |
|
|
| - Discovery endpoints return JSON; the wrappers in `src/api/*.js` parse the response and return `data` directly. |
| - Streaming endpoints (`/graph-generation/{generate,continue}`, `/kg-anomaly/{correct,continue}`) are consumed via `useSseStream`. Stores wire its `onProgress` / `onPreview` / `onResult` callbacks to mutate state. |
| - Errors come back as `{ error: { code, message, details } }`. `apiError(error)` (in `client.js`) extracts that envelope from an axios error. |
|
|
| The exact event protocol is in [`docs/reference/sse-protocol.md`](../../docs/reference/sse-protocol.md). |
|
|
| ## Routing |
|
|
| | Path | Name | View | |
| |---|---|---| |
| | `/` | `home` | `HomeView.vue` | |
| | `/cv` | `cv` | `CVView.vue` | |
| | `/demos/coins` | `demo-coins` | `CoinsView.vue` (lazy) | |
| | `/demos/multiproxan` | `demo-multiproxan` | `MultiProxAnView.vue` (lazy) | |
| | `/demos/kganomaly` | `demo-kganomaly` | `KgAnomalyView.vue` (lazy) | |
| | `/:pathMatch(.*)*` | `not-found` | `NotFoundView.vue` (Lara Croft 404) | |
|
|
| In production, the Django backend serves `dist/index.html` for any non-API path so the SPA's history mode keeps working on hard refreshes. |
|
|
| ## Theming |
|
|
| `stores/theme.js` toggles a `data-theme` attribute on `<html>` between `light` and `dark`, persists the choice to `localStorage`, and falls back to `prefers-color-scheme`. The actual colors live in `styles/tokens.css` and `styles/theme.css` as CSS custom properties. |
|
|
| ## Background animation |
|
|
| `components/background/GraphBackground.vue` renders the floating-graph motif behind every page (the project's visual signature). It's mounted once in `App.vue` and respects `prefers-reduced-motion`. |
|
|
| ## See also |
|
|
| - [`docs/reference/frontend-modules.md`](../../docs/reference/frontend-modules.md) β full module reference. |
| - [`docs/reference/sse-protocol.md`](../../docs/reference/sse-protocol.md) β the streaming protocol the demo stores parse. |
| - [`docs/guides/local-development.md`](../../docs/guides/local-development.md) β running both servers together. |
| - [`docs/explanation/architecture.md`](../../docs/explanation/architecture.md) β how the SPA is served by the deployed container. |
|
|