Landing: add marketing page at /, move the app to /app/

Multi-page Vite build: index.html serves a new standalone landing
(src/landing), app/index.html serves the app at /app/. The PWA service
worker and manifest are scoped to /app/, so the landing stays
uncontrolled and always-fresh; hash view-state routing is unchanged.

The landing reuses src/core and the chart-renderer service only (never
stores/orchestration/modals/components) and lazy-loads Vega. Its demos
drive the real core: a hero snippet switcher over CHART_EXAMPLES, an
interactive Chart Builder over a new profiled core fixture
(sample-dataset), and a Theme Builder gallery with three from-scratch
custom themes plus built-in presets.
This commit is contained in:
2026-06-17 16:43:01 +03:00
parent d8a7bcb7c1
commit 223646398e
11 changed files with 1645 additions and 4 deletions
+18
View File
@@ -20,6 +20,13 @@ export default defineConfig({
},
build: {
rollupOptions: {
// Multi-page: the marketing landing is served at `/` (index.html → the
// lightweight `src/landing` entry); the app at `/app/` (app/index.html →
// src/main.tsx). The app is hash-routed, so it runs unchanged under /app/.
input: {
main: fileURLToPath(new URL('./index.html', import.meta.url)),
app: fileURLToPath(new URL('./app/index.html', import.meta.url)),
},
output: {
// Split the heavy vendors so the chunk graph stays legible and the PWA
// can precache/update them independently of app code. Monaco and the
@@ -35,10 +42,18 @@ export default defineConfig({
react(),
VitePWA({
registerType: 'prompt',
// The app lives at /app/; scope the service worker there so it never
// controls the marketing landing at / (which stays uncontrolled and
// always-fresh). A /sw.js narrowing its scope to /app/ needs no
// Service-Worker-Allowed header — narrowing is always permitted.
scope: '/app/',
includeAssets: ['favicon.svg', 'icon-maskable.svg', 'icon-mono.svg', 'apple-touch-icon.png'],
manifest: {
id: '/app/',
name: 'Astrolabe',
short_name: 'Astrolabe',
scope: '/app/',
start_url: '/app/',
description: 'A browser-based snippet manager for Vega-Lite visualizations.',
// theme_color tints the OS/browser chrome; background_color is the splash
// behind the icon. theme_color is the app accent (`--accent`, light theme);
@@ -62,6 +77,9 @@ export default defineConfig({
],
},
workbox: {
// Client-side navigations under /app/ fall back to the app shell when
// offline; the SW's /app/ scope means / (the landing) is never matched.
navigateFallback: '/app/index.html',
// Precache the app, plus the font woff2 the offline-first UI and the
// common chart path need:
// - the bare `latin` subset of every family (`*-latin-[0-9]*` — the