Build-time tenant config via VITE_TENANT env var (--mode loop42/dev).
Content pages moved to tenants/{name}/pages/ with dynamic imports and
loop42 fallback. Feature-gated routing (viewer/devTools per tenant).
Dockerfile parameterized with TENANT build arg. Deployed to separate
K8s namespaces: loop42.de → ns/loop42, loop42.dev → ns/dev.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
47 lines
2.1 KiB
TypeScript
47 lines
2.1 KiB
TypeScript
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router';
|
|
import LoginView from './views/LoginView.vue';
|
|
import { THEME_NAMES, useTheme } from './composables/useTheme';
|
|
import tenant from './tenant';
|
|
import { HomePage, ImpressumPage, DatenschutzPage } from './tenantPages';
|
|
|
|
const routes: RouteRecordRaw[] = [
|
|
{ path: '/', name: 'home', component: HomePage, meta: { suffix: '' } },
|
|
{ path: '/impressum', name: 'impressum', component: ImpressumPage, meta: { suffix: 'Impressum' } },
|
|
{ path: '/datenschutz', name: 'datenschutz', component: DatenschutzPage, meta: { suffix: 'Datenschutz' } },
|
|
{ path: '/login', name: 'login', component: LoginView, meta: { suffix: 'Login' } },
|
|
{ path: '/nyx', name: 'nyx', component: () => import('./views/AgentsView.vue'), meta: { suffix: 'nyx', requiresAuth: true } },
|
|
{ path: '/agents', redirect: '/nyx' },
|
|
{ path: '/chat', redirect: '/nyx' },
|
|
];
|
|
|
|
if (tenant.features.viewer) {
|
|
routes.push({ path: '/viewer', name: 'viewer', component: () => import('./views/ViewerView.vue'), meta: { suffix: 'Viewer', requiresAuth: true } });
|
|
}
|
|
|
|
routes.push({ path: '/:pathMatch(.*)*', redirect: '/' });
|
|
|
|
const router = createRouter({
|
|
history: createWebHistory(),
|
|
routes,
|
|
});
|
|
|
|
// Auth guard — redirect to /login for protected routes
|
|
router.beforeEach((to) => {
|
|
if (to.meta?.requiresAuth) {
|
|
const token = localStorage.getItem('nyx_session');
|
|
if (!token) {
|
|
sessionStorage.setItem('auth_return_path', to.fullPath);
|
|
return { name: 'login' };
|
|
}
|
|
}
|
|
});
|
|
|
|
router.afterEach((to) => {
|
|
const { theme } = useTheme();
|
|
const brand = THEME_NAMES[theme.value] || 'loop42';
|
|
const suffix = (to.meta?.suffix as string) || '';
|
|
document.title = suffix ? `${brand} - ${suffix}` : brand;
|
|
});
|
|
|
|
export default router;
|