diff --git a/docs/superpowers/specs/2026-07-02-astro-migration-design.md b/docs/superpowers/specs/2026-07-02-astro-migration-design.md
new file mode 100644
index 0000000..84b58ff
--- /dev/null
+++ b/docs/superpowers/specs/2026-07-02-astro-migration-design.md
@@ -0,0 +1,359 @@
+# Astro Migration — BETE Design System Implementation
+
+> Migrasi frontend React SPA ke Astro SSG dengan React islands, mengikuti design system di `design/`.
+
+**Date:** 2026-07-02
+**Status:** Draft
+**Owner:** @asephs
+
+---
+
+## 🎯 Ringkasan
+
+Migrasi frontend dari React 19 + Vite (+ Tailwind 4) ke **Astro SSG** dengan React islands untuk komponen interaktif. Mengganti `services/frontend` yang sekarang dengan struktur Astro yang baru. Semua desain dari `design/` (16 dokumen) diimplementasikan sebagai fondasi visual.
+
+---
+
+## 🔗 Referensi Desain
+
+Dokumen desain yang menjadi acuan implementasi:
+
+| Dokumen | Konsep Kunci |
+|---------|-------------|
+| `core/01-color-system.md` | OKLCH colors, glassmorphism, semantic tokens |
+| `core/02-typography.md` | Fluid type scale (clamp), Outfit + JetBrains Mono |
+| `core/03-spatial-system.md` | 4px baseline grid, spacing/radius/z-index tokens |
+| `core/04-motion-system.md` | Easing curves, duration tokens, micro-interactions |
+| `core/05-component-architecture.md` | Atomic design taxonomy |
+| `patterns/06-interaction-patterns.md` | Interaction feedback matrix, keyboard shortcuts |
+| `patterns/09-state-machines.md` | Quad-state pattern (loading/error/empty/success) |
+| `patterns/10-responsive-system.md` | Breakpoints, mobile-nav, container queries |
+| `services/11-frontend-ui.md` | Tech stack, Tailwind config, glass utilities |
+| `system/15-theme-architecture.md` | CSS vars, dark/light theme switching |
+
+---
+
+## 🛠️ Tech Stack
+
+| Tool | Versi | Peran |
+|------|-------|-------|
+| Astro | 5.x | Meta-framework, SSG, routing, component model |
+| React | 19.x | Interactive islands (WebSocket, canvas, state) |
+| TypeScript | 5.x | Type safety |
+| Tailwind CSS | 4.x | Utility-first CSS (`@theme` block) |
+| Zustand | 5.x | Client state (UI, voice, messages) |
+| TanStack Query | 5.x | Server state (API data fetching) |
+| Radix UI | — | Headless primitives (Modal, Dropdown, Tabs) |
+| Framer Motion | 11.x | Complex animations (islands only) |
+| Three.js | 0.170+ | Particle background (deferred island) |
+
+---
+
+## 🚧 Pendekatan: Astro-First + React Islands
+
+**Prinsip:**
+- Semua komponen **non-interaktif** → `.astro` (zero JavaScript)
+- Komponen **interaktif** → React islands (`src/islands/`) dengan client directives
+- Routing → file-based Astro pages
+- Data fetching → REST API dari browser (SSG tidak punya backend runtime)
+
+### React Islands per Fitur
+
+| Island | Client Directive | Alasan |
+|--------|-----------------|--------|
+| AuthGuard | `client:load` | Cek auth state on mount |
+| VoiceControls | `client:load` | WebSocket + voice interaction |
+| AudioVisualizer | `client:idle` | Canvas-based, bukan prioritas awal |
+| MessageFeed | `client:load` | WebSocket + infinite scroll |
+| MascotChat | `client:idle` | Secondary feature |
+| ThemeToggle | `client:idle` | Non-critical UI |
+| Particles | `client:idle` | Background decoration |
+| ActiveSpeakers | `client:idle` | WS-driven list |
+| NowPlaying | `client:idle` | Media state |
+
+---
+
+## 📁 Struktur Proyek
+
+```
+services/frontend/
+├── astro.config.ts
+├── package.json
+├── tsconfig.json
+├── src/
+│ ├── pages/
+│ │ ├── index.astro → Dashboard (Live tab sebagai default)
+│ │ ├── live.astro → Live panel
+│ │ ├── messages.astro → Message feed
+│ │ ├── settings.astro → Settings
+│ │ ├── login.astro → Auth page
+│ │ ├── recordings.astro → Recordings
+│ │ └── 404.astro
+│ │
+│ ├── layouts/
+│ │ ├── DashboardLayout.astro # Sidebar + Header +
+│ │ └── AuthLayout.astro # Minimal, centered card
+│ │
+│ ├── components/ # Astro components — zero JS
+│ │ ├── ui/
+│ │ │ ├── Button.astro
+│ │ │ ├── Badge.astro
+│ │ │ ├── SeverityBadge.astro
+│ │ │ ├── Card.astro
+│ │ │ ├── Skeleton.astro
+│ │ │ └── Spinner.astro
+│ │ ├── sidebar/
+│ │ │ ├── Sidebar.astro
+│ │ │ └── NavItem.astro
+│ │ ├── header/
+│ │ │ └── Header.astro
+│ │ └── states/
+│ │ ├── EmptyState.astro
+│ │ ├── ErrorState.astro
+│ │ └── LoadingSkeleton.astro
+│ │
+│ ├── islands/ # React components — interactive
+│ │ ├── AuthGuard.tsx # client:load
+│ │ ├── VoiceControls.tsx # client:load
+│ │ ├── AudioVisualizer.tsx # client:idle
+│ │ ├── MessageFeed.tsx # client:load
+│ │ ├── MascotChat.tsx # client:idle
+│ │ ├── ThemeToggle.tsx # client:idle
+│ │ ├── Particles.tsx # client:idle
+│ │ ├── ActiveSpeakers.tsx # client:idle
+│ │ └── NowPlaying.tsx # client:idle
+│ │
+│ ├── stores/ # Zustand stores
+│ │ ├── ui-store.ts
+│ │ ├── voice-store.ts
+│ │ └── message-store.ts
+│ │
+│ ├── shared/
+│ │ ├── api/client.ts # REST API calls
+│ │ ├── ws/socket.ts # WebSocket manager
+│ │ ├── hooks/
+│ │ │ ├── useMessages.ts
+│ │ │ ├── useVoiceStatus.ts
+│ │ │ ├── useMediaControl.ts
+│ │ │ ├── useUIState.ts
+│ │ │ └── useReducedMotion.ts
+│ │ └── lib/utils.ts # cn(), formatters
+│ │
+│ └── styles/
+│ └── base.css # Tailwind + design tokens + glass
+│
+└── public/
+ └── favicon.svg
+```
+
+---
+
+## 🎨 CSS Architecture
+
+### Layer Stack
+
+```
+base.css
+ ├── @import "tailwindcss"
+ ├── @theme {} → Tailwind 4 semantic tokens
+ ├── :root {} → Dark theme CSS vars (OKLCH)
+ ├── [data-theme="light"] {} → Light theme overrides
+ ├── @layer base → Reset, font-face, scrollbar styling
+ ├── @layer components → Glass, gradient-text, typography classes
+ └── @layer utilities → Animations keyframes
+```
+
+### CSS Variables: Prefix Categories
+
+| Kategori | Prefix | Contoh |
+|----------|--------|--------|
+| Warna | `--clr-*` | `--clr-surface-base`, `--clr-primary` |
+| Spacing | `--sp-*` | `--sp-3` (16px), `--sp-5` (32px) |
+| Typography | `--fs-*`, `--fw-*`, `--lh-*` | `--fs-base`, `--fw-semibold` |
+| Radius | `--rd-*` | `--rd-md` (8px), `--rd-xl` (16px) |
+| Shadow | `--sh-*` | `--sh-card`, `--sh-modal` |
+| Z-index | `--z-*` | `--z-header` (30), `--z-modal` (60) |
+| Timing | `--dur-*` | `--dur-fast` (150ms) |
+| Easing | `--ease-*` | `--ease-out`, `--ease-out-quint` |
+
+### Glass Utility Classes
+
+```css
+.glass {
+ background: oklch(from var(--clr-surface-elevated) l c h / 0.6);
+ backdrop-filter: blur(16px);
+ border: 1px solid oklch(from var(--clr-border) l c h / 0.2);
+}
+.gradient-text { /* ... */ }
+```
+
+---
+
+## 🧩 Component Design (Key Components)
+
+### Button (Astro)
+
+```astro
+---
+export interface Props {
+ variant?: 'primary' | 'secondary' | 'destructive' | 'outline' | 'ghost';
+ size?: 'sm' | 'default' | 'lg' | 'icon';
+ disabled?: boolean;
+ class?: string;
+}
+
+const { variant = 'primary', size = 'default', disabled = false, class: className = '' } = Astro.props;
+---
+
+
+
+
+```
+
+### Card (Astro — Slot-based)
+
+```astro
+---
+export interface Props {
+ variant?: 'default' | 'elevated' | 'glass' | 'interactive';
+ padding?: 'sm' | 'default' | 'lg' | 'none';
+ class?: string;
+}
+---
+
+
+
+
+
+```
+
+### MessageFeed (React Island — most complex)
+
+```tsx
+// islands/MessageFeed.tsx
+// Keeps the existing MessageFeed logic but imports types from @bete/shared
+// Uses useInfiniteQuery for cursor pagination
+// Subscribes to WebSocket via SocketManager for real-time updates
+// Integrates with Zustand message-store for optimistic updates
+// Renders: cards with severity badges, action buttons, attachment previews
+// States: loading → skeleton, error → retry, empty → mascot, success → list
+
+interface MessageFeedProps {
+ channelId?: string;
+}
+```
+
+---
+
+## 🔌 Data Flow
+
+### WebSocket Architecture
+
+```
+Browser → WebSocket → Backend (Express + ws)
+ ↑ ↓
+ └─────────────────────────┘
+ (real-time events via SocketManager)
+```
+
+- `SocketManager` singleton dengan exponential backoff reconnect
+- Events dipetakan ke Zustand stores → trigger React re-render
+- REST API untuk initial data fetch (TanStack Query)
+
+### Authentication
+
+- Password disimpan di localStorage
+- `X-Admin-Password` header di semua API calls
+- AuthGuard island: cek localStorage, verify via `/api/health`, redirect ke login
+
+---
+
+## 📱 Responsive Behavior
+
+| Viewport | Sidebar | Header | Grid | Navigation |
+|----------|---------|--------|------|------------|
+| < 640px | Bottom tab (56px) | Compact | 1 col | Tab bar |
+| 640–768px | Bottom tab | Compact | 1-2 col | Tab bar |
+| 768–1024px | Icon (64px) | Standard | 2-3 col | Sidebar icon |
+| 1024–1280px | Full (256px) | Standard | 3 col | Sidebar full |
+| 1280px+ | Full (256px) | Full | 3-4 col | Sidebar full |
+
+---
+
+## 📦 Fase Migrasi (5 Fase)
+
+### Fase 1: Foundation 🔧
+- Inisialisasi Astro + React integration
+- `base.css` dengan design tokens + Tailwind 4 `@theme`
+- DashboardLayout, Sidebar, Header (Astro komponen)
+- Theme switching (island)
+
+### Fase 2: UI Component Library 🧱
+- Semua Astro components: Button, Badge, Card, Skeleton, SeverityBadge
+- State components: EmptyState, ErrorState, LoadingSkeleton
+- Glass utilities + animation keyframes
+
+### Fase 3: Auth & Messages 📨
+- AuthGuard island (login, localStorage)
+- MessageFeed island (TanStack Query + WebSocket)
+- Infinite scroll + real-time updates
+
+### Fase 4: Live / Voice 🎤
+- VoiceControls island (connect/disconnect)
+- ActiveSpeakers, AudioVisualizer, NowPlaying islands
+- Recordings page
+
+### Fase 5: Polish ✨
+- 3D Particles (three.js, deferred)
+- MascotChat island
+- View Transitions
+- Settings page
+- Mobile bottom tab bar
+
+---
+
+## ⚠️ Known Risks & Mitigations
+
+| Risk | Dampak | Mitigasi |
+|------|--------|----------|
+| WebSocket reconnect di SSG | Koneksi terputus saat navigasi | SocketManager global singleton persist across islands |
+| Bundle size React islands | JS besar di halaman interaktif | Split per halaman, gunakan `client:idle` bila memungkinkan |
+| Auth check blocking render | Flash of login page | AuthGuard render spinner dulu, baru cek localStorage |
+| Design token mismatch | Warna/spasi berbeda dari desain | CSS variables sebagai single source of truth, verifikasi visual tiap fase |
+| react-three-fiber compatibility | Mungkin perlu workaround SSR | Island di-defer via `client:idle`, Three.js murni client-side |
+
+---
+
+## ✅ Spec Self-Review
+
+- **Placeholder scan:** All sections filled. No TBD/TODO left.
+- **Consistency:** All design tokens reference the same CSS variable naming from `design/`. Component architecture matches atomic taxonomy in `05-component-architecture.md`. State patterns follow `09-state-machines.md`.
+- **Scope:** Focused on frontend migration only. Backend/gateway unchanged. All existing features preserved.
+- **Ambiguity resolved:**
+ - Astro output mode: SSG (confirmed)
+ - React islands scope: only truly interactive components (confirmed)
+ - All existing features retained (confirmed)
+
+---
+
+*Spec ditulis berdasarkan brainstorming dan persetujuan 7 section design.*