import { createRouter, createWebHistory, createMemoryHistory } from 'vue-router' import SettingsView from './views/SettingsView.vue' import GalleryView from './views/GalleryView.vue' import ShowcaseView from './views/ShowcaseView.vue' import ExploreView from './views/ExploreView.vue' import BrowseView from './views/BrowseView.vue' import ArtistView from './views/ArtistView.vue' import SeriesView from './views/SeriesView.vue' import SeriesManageView from './views/SeriesManageView.vue' import SeriesReaderView from './views/SeriesReaderView.vue' import SubscriptionsView from './views/SubscriptionsView.vue' // The application's front door. `/` redirects here. Changing the front door // is a one-line edit (e.g. '/gallery' or '/tags'). export const FRONT_DOOR = '/showcase' const routes = [ // Root is a redirect only — no meta.title so it stays out of the nav. { path: '/', redirect: FRONT_DOOR }, // FC-2: image backbone { path: '/showcase', name: 'showcase', component: ShowcaseView, meta: { title: 'Showcase', navOrder: 10 } }, { path: '/gallery', name: 'gallery', component: GalleryView, meta: { title: 'Gallery', navOrder: 20 } }, // Explore: a 3-pane tagging workspace — walk an image's visual neighbours // (left) while tagging the focused image (center viewer + modal-parity tag // rail). Optional anchor param — the bare /explore nav entry SEEDS a random // image so the tab kick-starts a rabbit hole. navOrder pins it after Gallery. { path: '/explore/:imageId?', name: 'explore', component: ExploreView, meta: { title: 'Explore', navOrder: 25 } }, // Browse hub (operator-asked 2026-06-09): Posts / Artists / Tags as tabs — // the three "browse the library by an axis" surfaces. One nav entry; the old // standalone paths redirect into the matching tab (below). { path: '/browse', name: 'browse', component: BrowseView, meta: { title: 'Browse', navOrder: 30 } }, // Artist detail — no meta.title (reached by clicking an artist, not nav). { path: '/artist/:slug', name: 'artist', component: ArtistView }, // Series browse — a nav entry (meta.title). { path: '/series', name: 'series', component: SeriesView, meta: { title: 'Series', navOrder: 40 } }, // Series management — no meta.title (reached from a series card/tag). { path: '/series/:tagId', name: 'series-manage', component: SeriesManageView }, // Series reader — immersive (no top nav, no meta.title). { path: '/series/:tagId/read', name: 'series-read', component: SeriesReaderView, meta: { immersive: true } }, // FC-3: subscription backbone — purely management (sources/downloads), // distinct from the Browse hub. { path: '/subscriptions', name: 'subscriptions', component: SubscriptionsView, meta: { title: 'Subscriptions', navOrder: 50 } }, // Settings — config, pinned to the right of the nav (TopNav special-cases it). { path: '/settings', name: 'settings', component: SettingsView, meta: { title: 'Settings' } }, // The old standalone paths now redirect into the Browse hub, preserving any // deep-link query (e.g. /posts?post_id=N → /browse?tab=posts&post_id=N). The // route NAMES stay so existing { name: 'posts' | 'artists' | 'tags' } links // and path pushes keep resolving. { path: '/posts', name: 'posts', redirect: (to) => ({ name: 'browse', query: { ...to.query, tab: 'posts' } }) }, { path: '/artists', name: 'artists', redirect: (to) => ({ name: 'browse', query: { ...to.query, tab: 'artists' } }) }, { path: '/tags', name: 'tags', redirect: (to) => ({ name: 'browse', query: { ...to.query, tab: 'tags' } }) }, // Bookmark/back-button safety net for the routes that got folded into // /subscriptions (no meta.title — stay out of TopNav). { path: '/credentials', redirect: '/subscriptions?tab=settings' }, { path: '/downloads', redirect: '/subscriptions?tab=downloads' } ] // Browser uses HTML5 history; non-browser (Vitest/SSR) falls back to memory // history so the module is importable without `window`. const history = typeof window !== 'undefined' ? createWebHistory() : createMemoryHistory() const router = createRouter({ history, routes }) const DEFAULT_TITLE = 'FabledCurator' // Keep the tab title in sync with the route on EVERY navigation. List routes set // it from meta.title; detail routes (artist, series) have no meta.title, so they // reset to the default here and then overwrite it with their own dynamic title // (e.g. ArtistView sets " — FabledCurator"). Without this reset the // previous view's dynamic title stuck around — an artist name showing on the // Showcase tab, operator-flagged 2026-06-07. router.afterEach((to) => { if (typeof document === 'undefined') return document.title = to.meta?.title ? `${to.meta.title} — ${DEFAULT_TITLE}` : DEFAULT_TITLE }) export default router