Sets up web/ Vue 3 SPA skeleton for issue #8, synthesizing all 15 gotchas from avocet's Vue port testbed. Key fixes baked in before any component work: - App.vue root uses .app-root class (not id="app") — gotcha #1 - overflow-x: clip on html (not hidden) — gotcha #3 - UnoCSS presetAttributify with prefixedOnly: true — gotcha #4 - peregrine.css alias map for theme variable names — gotcha #5 - useHaptics guards navigator.vibrate — gotcha #9 - Pinia setup store pattern documented — gotcha #10 - test-setup.ts stubs matchMedia, vibrate, ResizeObserver — gotcha #12 - min-height: 100dvh throughout — gotcha #13 Includes: - All 7 Peregrine views as stubs (ready to port from Streamlit) - AppNav with all routes - useApi (fetch + SSE), useMotion, useHaptics, useEasterEgg composables - Konami hacker mode easter egg + confetti + cursor trail - docs/vue-spa-migration.md: full migration guide + implementation order - Build verified clean (0 errors) - .gitleaks.toml: allowlist web/package-lock.json (sha512 integrity hashes)
24 lines
757 B
TypeScript
24 lines
757 B
TypeScript
import { createApp } from 'vue'
|
|
import { createPinia } from 'pinia'
|
|
import { router } from './router'
|
|
|
|
// Self-hosted fonts — no Google Fonts CDN (privacy requirement)
|
|
import '@fontsource/fraunces/400.css'
|
|
import '@fontsource/fraunces/700.css'
|
|
import '@fontsource/atkinson-hyperlegible/400.css'
|
|
import '@fontsource/atkinson-hyperlegible/700.css'
|
|
import '@fontsource/jetbrains-mono/400.css'
|
|
|
|
import 'virtual:uno.css'
|
|
import './assets/theme.css'
|
|
import './assets/peregrine.css'
|
|
|
|
import App from './App.vue'
|
|
|
|
// Manual scroll restoration — prevents browser from jumping to last position on SPA nav
|
|
if ('scrollRestoration' in history) history.scrollRestoration = 'manual'
|
|
|
|
const app = createApp(App)
|
|
app.use(createPinia())
|
|
app.use(router)
|
|
app.mount('#app')
|