# [DEF:ADR-0006:ADR]
# @STATUS ACTIVE
# @PURPOSE Define the frontend architecture for ss-tools: Svelte 5 runes reactivity model, SvelteKit routing, component composition rules, state management patterns, API client conventions, and UX contract expectations for C4/C5 components.
# @RELATION DEPENDS_ON -> [ADR-0001:ADR]
# @RELATION DEPENDS_ON -> [ADR-0002:ADR]
# @RATIONALE Svelte 5 introduces a fundamentally different reactivity model (runes: `$state`, `$derived`, `$effect`, `$props`) compared to Svelte 4's `$:` reactive statements. This ADR locks in the Svelte 5 runes approach and prevents backsliding into legacy patterns when new developers or AI agents contribute code.
# @RATIONALE SvelteKit with static adapter (`@sveltejs/adapter-static`) was chosen over SvelteKit SSR because: (a) ss-tools is a Docker‑deployed SPA behind nginx — server‑side rendering provides no latency benefit, (b) static SPA simplifies Docker deployment (no Node.js server needed, just nginx serving static files), (c) all data is fetched via REST API, not server‑side load functions.
# @RATIONALE Svelte 5 runes (`$state`, `$derived`, `$effect`) are mandated over Svelte 4 `$:` reactivity and `writable` stores because: (a) runes are the forward path — Svelte 4 patterns are deprecated, (b) runes provide fine‑grained reactivity without subscription boilerplate, (c) `$state` can be used outside `.svelte` files in `.svelte.js` modules, enabling reusable reactive logic.
# @REJECTED React/Next.js — rejected by ADR-0003 (technology stack independence from Superset). Svelte 5 was chosen for its compile‑time approach, smaller bundle size, and superior DX for this project's scale.
# @REJECTED Svelte 4 legacy patterns (`$:`, `writable`/`readable` stores) — rejected because Svelte 5 runes are the actively maintained reactivity model. Mixing two models creates confusion and potential reactivity bugs.
# @REJECTED Server‑Side Rendering (SSR) with SvelteKit — rejected because the data is entirely API‑driven (no server‑side page data loading), and SSR adds deployment complexity (Node.js process) without latency benefit for authenticated SPA users.

## Decision

### Technology Stack

| Layer | Choice | Version |
|-------|--------|---------|
| Framework | SvelteKit | 2.x |
| UI Library | Svelte | 5.x (runes mode) |
| Build | Vite | 7.x |
| Styling | Tailwind CSS | 3.x |
| Adapter | @sveltejs/adapter-static | 3.x (SPA mode) |
| Testing | vitest + @testing-library/svelte | 4.x / 5.x |

### Reactivity Model (Svelte 5 Runes)

```
Legacy (FORBIDDEN)              Svelte 5 Runes (REQUIRED)
────────────────────────        ──────────────────────────
let count = 0;                  let count = $state(0);
$: doubled = count * 2;         let doubled = $derived(count * 2);
$: { /* side effect */ }        $effect(() => { /* side effect */ });
export let name;                let { name } = $props();
import { writable } from ...    ❌ stores are .svelte.js modules with $state
```

### State Management Pattern

Three tiers of state, strictly separated:

1. **Component‑local state**: `$state()` inside `.svelte` files. Never exported.
2. **Shared reactive state**: `.svelte.js` modules exporting `$state` objects. Imported by components.
   ```js
   // frontend/src/lib/stores/dashboard.svelte.js
   export const dashboardState = $state({
       dashboards: [],
       selectedId: null,
       isLoading: false
   });
   ```
3. **Server state**: Fetched via API client, held in `$state` variables locally. No global cache — each route fetches what it needs.

### API Client Convention

API client modules live under `frontend/src/lib/api/`. Each module wraps `fetch` calls to the FastAPI backend, attaches the JWT access token from the auth store, and normalises errors into a typed `ApiError`. Contract annotations follow the rules defined in the `semantics-core` and `semantics-contracts` skills.

### Component Complexity & UX Contracts

Svelte components with side effects (API calls, WebSocket subscriptions, file operations) MUST carry UX contract tags as defined by the `semantics-frontend` skill (`.opencode/skills/semantics-frontend/SKILL.md`). The skill is the canonical source for tag inventory, syntax, and per‑complexity requirements.

### Component File Structure

```
frontend/src/lib/components/
├── DashboardGrid.svelte          # C4: complex data grid with WebSocket updates
├── MappingTable.svelte           # C3: migration mapping table
├── PluginExecutionCard.svelte    # C4: plugin runner with progress feedback
├── RoleBadge.svelte              # C1: simple role display
└── ...
```

### Routing

- SvelteKit file‑based routing under `frontend/src/routes/`
- Protected routes check auth in `+layout.svelte` (redirect to `/login` if no token)
- Route structure: `/` (dashboard list), `/envs/[id]` (environment detail), `/migration` (migration wizard), `/plugins` (plugin management), `/admin` (user/role management)

# [/DEF:ADR-0006:ADR]
