From bcd9a23501cf253f52960b73647e16fcb610e10e Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Thu, 14 May 2026 07:36:01 -0400 Subject: [PATCH] feat: add SPA app shell, router, system store, and route placeholders Nav lists every FC-2 and FC-3 surface with a placeholder view that names the sub-project that will fill it. System store polls /api/health on mount and renders a status pip in the nav footer. Favicon uses Curator's aged amber accent (#A87338). Co-Authored-By: Claude Opus 4.7 (1M context) --- frontend/public/favicon.svg | 5 ++ frontend/src/components/AppShell.vue | 78 ++++++++++++++++++++++++++ frontend/src/router.js | 20 +++++++ frontend/src/stores/system.js | 18 ++++++ frontend/src/views/PlaceholderView.vue | 34 +++++++++++ 5 files changed, 155 insertions(+) create mode 100644 frontend/public/favicon.svg create mode 100644 frontend/src/components/AppShell.vue create mode 100644 frontend/src/router.js create mode 100644 frontend/src/stores/system.js create mode 100644 frontend/src/views/PlaceholderView.vue diff --git a/frontend/public/favicon.svg b/frontend/public/favicon.svg new file mode 100644 index 0000000..6b07fb4 --- /dev/null +++ b/frontend/public/favicon.svg @@ -0,0 +1,5 @@ + + + + diff --git a/frontend/src/components/AppShell.vue b/frontend/src/components/AppShell.vue new file mode 100644 index 0000000..ce71c61 --- /dev/null +++ b/frontend/src/components/AppShell.vue @@ -0,0 +1,78 @@ + + + + + diff --git a/frontend/src/router.js b/frontend/src/router.js new file mode 100644 index 0000000..d60b5e5 --- /dev/null +++ b/frontend/src/router.js @@ -0,0 +1,20 @@ +import { createRouter, createWebHistory } from 'vue-router' +import PlaceholderView from './views/PlaceholderView.vue' + +const routes = [ + // FC-2: image backbone + { path: '/', name: 'gallery', component: PlaceholderView, meta: { title: 'Gallery' } }, + { path: '/showcase', name: 'showcase', component: PlaceholderView, meta: { title: 'Showcase' } }, + { path: '/tags', name: 'tags', component: PlaceholderView, meta: { title: 'Tags' } }, + { path: '/settings', name: 'settings', component: PlaceholderView, meta: { title: 'Settings' } }, + + // FC-3: subscription backbone + { path: '/subscriptions', name: 'subscriptions', component: PlaceholderView, meta: { title: 'Subscriptions' } }, + { path: '/credentials', name: 'credentials', component: PlaceholderView, meta: { title: 'Credentials' } }, + { path: '/downloads', name: 'downloads', component: PlaceholderView, meta: { title: 'Downloads' } } +] + +export default createRouter({ + history: createWebHistory(), + routes +}) diff --git a/frontend/src/stores/system.js b/frontend/src/stores/system.js new file mode 100644 index 0000000..4412640 --- /dev/null +++ b/frontend/src/stores/system.js @@ -0,0 +1,18 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' + +export const useSystemStore = defineStore('system', () => { + const healthy = ref(null) // null=unknown, true=ok, false=down + + async function refreshHealth() { + try { + const r = await fetch('/api/health') + const body = await r.json() + healthy.value = r.ok && body.status === 'ok' + } catch { + healthy.value = false + } + } + + return { healthy, refreshHealth } +}) diff --git a/frontend/src/views/PlaceholderView.vue b/frontend/src/views/PlaceholderView.vue new file mode 100644 index 0000000..5c53509 --- /dev/null +++ b/frontend/src/views/PlaceholderView.vue @@ -0,0 +1,34 @@ + + + + +