diff --git a/apps/calendar/apps/web/src/routes/+layout.svelte b/apps/calendar/apps/web/src/routes/+layout.svelte
index 691524162..d964f4348 100644
--- a/apps/calendar/apps/web/src/routes/+layout.svelte
+++ b/apps/calendar/apps/web/src/routes/+layout.svelte
@@ -148,6 +148,12 @@
if (authStore.isAuthenticated) {
await calendarsStore.fetchCalendars();
await userSettings.load();
+
+ // Redirect to start page if on root and a custom start page is set
+ const currentPath = window.location.pathname;
+ if (currentPath === '/' && userSettings.startPage && userSettings.startPage !== '/') {
+ goto(userSettings.startPage, { replaceState: true });
+ }
}
// Initialize sidebar mode from localStorage
@@ -225,7 +231,10 @@
class:sidebar-mode={isSidebarMode && !isCollapsed}
class:floating-mode={!isSidebarMode && !isCollapsed}
>
-
+
{@render children()}
diff --git a/apps/chat/apps/web/src/routes/(protected)/+layout.svelte b/apps/chat/apps/web/src/routes/(protected)/+layout.svelte
index b910e07a4..320275e76 100644
--- a/apps/chat/apps/web/src/routes/(protected)/+layout.svelte
+++ b/apps/chat/apps/web/src/routes/(protected)/+layout.svelte
@@ -160,6 +160,12 @@
// Load user settings
await userSettings.load();
+ // Redirect to start page if on /chat and a custom start page is set
+ const currentPath = window.location.pathname;
+ if (currentPath === '/chat' && userSettings.startPage && userSettings.startPage !== '/chat') {
+ goto(userSettings.startPage, { replaceState: true });
+ }
+
isChecking = false;
});
diff --git a/apps/clock/apps/web/src/lib/stores/user-settings.svelte.ts b/apps/clock/apps/web/src/lib/stores/user-settings.svelte.ts
new file mode 100644
index 000000000..3b9727cdc
--- /dev/null
+++ b/apps/clock/apps/web/src/lib/stores/user-settings.svelte.ts
@@ -0,0 +1,19 @@
+/**
+ * User Settings Store for Clock
+ *
+ * This store syncs settings with mana-core-auth and provides:
+ * - Global settings that apply to all apps
+ * - Per-app overrides for customization
+ * - localStorage caching for offline support
+ */
+
+import { createUserSettingsStore } from '@manacore/shared-theme';
+import { authStore } from './auth.svelte';
+
+const MANA_AUTH_URL = 'http://localhost:3001';
+
+export const userSettings = createUserSettingsStore({
+ appId: 'clock',
+ authUrl: MANA_AUTH_URL,
+ getAccessToken: () => authStore.getAccessToken(),
+});
diff --git a/apps/clock/apps/web/src/routes/settings/+page.svelte b/apps/clock/apps/web/src/routes/settings/+page.svelte
index a1403bd24..6da6f40fe 100644
--- a/apps/clock/apps/web/src/routes/settings/+page.svelte
+++ b/apps/clock/apps/web/src/routes/settings/+page.svelte
@@ -1,8 +1,10 @@
@@ -160,4 +167,17 @@
Töne können für einzelne Wecker und Timer in deren Einstellungen angepasst werden.
+
+
+
diff --git a/apps/manacore/apps/web/src/routes/(app)/+layout.svelte b/apps/manacore/apps/web/src/routes/(app)/+layout.svelte
index 4bd318707..f9998bf9f 100644
--- a/apps/manacore/apps/web/src/routes/(app)/+layout.svelte
+++ b/apps/manacore/apps/web/src/routes/(app)/+layout.svelte
@@ -148,6 +148,16 @@
// Load user settings from server
if (authStore.isAuthenticated) {
await userSettings.load();
+
+ // Redirect to start page if on /dashboard and a custom start page is set
+ const currentPath = window.location.pathname;
+ if (
+ currentPath === '/dashboard' &&
+ userSettings.startPage &&
+ userSettings.startPage !== '/dashboard'
+ ) {
+ goto(userSettings.startPage, { replaceState: true });
+ }
}
loading = false;
diff --git a/apps/manadeck/apps/web/src/routes/(app)/+layout.svelte b/apps/manadeck/apps/web/src/routes/(app)/+layout.svelte
index 97fe87661..bed7b8437 100644
--- a/apps/manadeck/apps/web/src/routes/(app)/+layout.svelte
+++ b/apps/manadeck/apps/web/src/routes/(app)/+layout.svelte
@@ -139,6 +139,12 @@
// Load user settings
await userSettings.load();
+ // Redirect to start page if on root and a custom start page is set
+ const currentPath = window.location.pathname;
+ if (currentPath === '/decks' && userSettings.startPage && userSettings.startPage !== '/decks') {
+ goto(userSettings.startPage, { replaceState: true });
+ }
+
// Initialize sidebar mode from localStorage
const savedSidebar = localStorage.getItem('manadeck-nav-sidebar');
if (savedSidebar === 'true') {
diff --git a/apps/picture/apps/web/src/routes/app/+layout.svelte b/apps/picture/apps/web/src/routes/app/+layout.svelte
index 8f3c884a1..e19179eeb 100644
--- a/apps/picture/apps/web/src/routes/app/+layout.svelte
+++ b/apps/picture/apps/web/src/routes/app/+layout.svelte
@@ -68,7 +68,22 @@
// Load user settings when authenticated
$effect(() => {
if (authStore.initialized && authStore.user) {
- userSettings.load();
+ userSettings.load().then(() => {
+ // Redirect to start page if on /app and a custom start page is set
+ const currentPath = window.location.pathname;
+ if (
+ currentPath === '/app' &&
+ userSettings.startPage &&
+ userSettings.startPage !== '/' &&
+ userSettings.startPage !== '/app'
+ ) {
+ // Prepend /app if the start page doesn't include it
+ const targetPath = userSettings.startPage.startsWith('/app')
+ ? userSettings.startPage
+ : `/app${userSettings.startPage}`;
+ goto(targetPath, { replaceState: true });
+ }
+ });
}
});
diff --git a/apps/presi/apps/web/src/routes/+layout.svelte b/apps/presi/apps/web/src/routes/+layout.svelte
index e2a5d3db7..549166b6b 100644
--- a/apps/presi/apps/web/src/routes/+layout.svelte
+++ b/apps/presi/apps/web/src/routes/+layout.svelte
@@ -136,6 +136,12 @@
// Load user settings
await userSettings.load();
+ // Redirect to start page if on root and a custom start page is set
+ const currentPath = window.location.pathname;
+ if (currentPath === '/' && userSettings.startPage && userSettings.startPage !== '/') {
+ goto(userSettings.startPage, { replaceState: true });
+ }
+
// Initialize theme
const cleanup = theme.initialize();
diff --git a/apps/todo/apps/web/src/lib/stores/user-settings.svelte.ts b/apps/todo/apps/web/src/lib/stores/user-settings.svelte.ts
new file mode 100644
index 000000000..18af057b7
--- /dev/null
+++ b/apps/todo/apps/web/src/lib/stores/user-settings.svelte.ts
@@ -0,0 +1,10 @@
+import { createUserSettingsStore } from '@manacore/shared-theme';
+import { authStore } from './auth.svelte';
+
+const MANA_AUTH_URL = import.meta.env.PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
+
+export const userSettings = createUserSettingsStore({
+ appId: 'todo',
+ authUrl: MANA_AUTH_URL,
+ getAccessToken: () => authStore.getAccessToken(),
+});
diff --git a/apps/todo/apps/web/src/routes/+layout.svelte b/apps/todo/apps/web/src/routes/+layout.svelte
index edf2bb891..a19fb25dd 100644
--- a/apps/todo/apps/web/src/routes/+layout.svelte
+++ b/apps/todo/apps/web/src/routes/+layout.svelte
@@ -6,6 +6,7 @@
import { PillNavigation } from '@manacore/shared-ui';
import type { PillNavItem, PillDropdownItem } from '@manacore/shared-ui';
import { authStore } from '$lib/stores/auth.svelte';
+ import { userSettings } from '$lib/stores/user-settings.svelte';
import { projectsStore } from '$lib/stores/projects.svelte';
import { labelsStore } from '$lib/stores/labels.svelte';
import { theme } from '$lib/stores/theme';
@@ -137,7 +138,17 @@
// Load data if authenticated
if (authStore.isAuthenticated) {
- await Promise.all([projectsStore.fetchProjects(), labelsStore.fetchLabels()]);
+ await Promise.all([
+ projectsStore.fetchProjects(),
+ labelsStore.fetchLabels(),
+ userSettings.load(),
+ ]);
+
+ // Redirect to start page if on root and a custom start page is set
+ const currentPath = window.location.pathname;
+ if (currentPath === '/' && userSettings.startPage && userSettings.startPage !== '/') {
+ goto(userSettings.startPage, { replaceState: true });
+ }
}
// Initialize sidebar mode from localStorage
@@ -183,7 +194,7 @@
onModeChange={handleModeChange}
{isCollapsed}
onCollapsedChange={handleCollapsedChange}
- desktopPosition="bottom"
+ desktopPosition={userSettings.nav.desktopPosition}
showThemeToggle={true}
showThemeVariants={true}
{themeVariantItems}
diff --git a/apps/zitare/apps/web/src/routes/+layout.svelte b/apps/zitare/apps/web/src/routes/+layout.svelte
index dcd0251cb..4a33a368f 100644
--- a/apps/zitare/apps/web/src/routes/+layout.svelte
+++ b/apps/zitare/apps/web/src/routes/+layout.svelte
@@ -145,6 +145,12 @@
// Load user settings if authenticated
if (authStore.isAuthenticated) {
await userSettings.load();
+
+ // Redirect to start page if on root and a custom start page is set
+ const currentPath = window.location.pathname;
+ if (currentPath === '/' && userSettings.startPage && userSettings.startPage !== '/') {
+ goto(userSettings.startPage, { replaceState: true });
+ }
}
// Initialize sidebar mode from localStorage
diff --git a/packages/shared-theme/src/app-routes.ts b/packages/shared-theme/src/app-routes.ts
new file mode 100644
index 000000000..dcfa573c1
--- /dev/null
+++ b/packages/shared-theme/src/app-routes.ts
@@ -0,0 +1,201 @@
+/**
+ * App Routes Configuration
+ *
+ * Defines available start pages for each app in the ecosystem.
+ * Used by the start page selector in global settings.
+ */
+
+/**
+ * Route definition with i18n label
+ */
+export interface AppRoute {
+ /** Route path (e.g., '/stopwatch') */
+ path: string;
+ /** i18n key for the label (e.g., 'nav.stopwatch') */
+ labelKey: string;
+ /** Optional icon name */
+ icon?: string;
+}
+
+/**
+ * App route configuration
+ */
+export interface AppRouteConfig {
+ /** App identifier */
+ appId: string;
+ /** Default start route (used when no preference set) */
+ defaultRoute: string;
+ /** Available routes that can be set as start page */
+ availableRoutes: AppRoute[];
+}
+
+/**
+ * Route configurations for all apps
+ */
+export const APP_ROUTES: Record