diff --git a/.claude/guidelines/authentication.md b/.claude/guidelines/authentication.md
index d0f9a5dae..34d9c3dda 100644
--- a/.claude/guidelines/authentication.md
+++ b/.claude/guidelines/authentication.md
@@ -202,7 +202,206 @@ APP_ID=your-app-id
## Client Integration (Web)
-### Setup
+### Runtime URL Injection (Recommended for Docker)
+
+For Docker deployments, use runtime URL injection instead of build-time environment variables:
+
+**Step 1: Server Hook (`hooks.server.ts`)**
+
+```typescript
+// src/hooks.server.ts
+import type { Handle } from '@sveltejs/kit';
+import { env } from '$env/dynamic/private';
+
+export const handle: Handle = async ({ event, resolve }) => {
+ return resolve(event, {
+ transformPageChunk: ({ html }) =>
+ html.replace(
+ '%RUNTIME_ENV%',
+ ``
+ ),
+ });
+};
+```
+
+**Step 2: Update `app.html`**
+
+```html
+
+
+
+ %sveltekit.head%
+ %RUNTIME_ENV%
+
+
+ %sveltekit.body%
+
+
+```
+
+**Step 3: URL Helper (`url.ts`)**
+
+```typescript
+// src/lib/config/url.ts
+import { browser } from '$app/environment';
+import { PUBLIC_MANA_CORE_AUTH_URL, PUBLIC_BACKEND_URL } from '$env/static/public';
+
+declare global {
+ interface Window {
+ __PUBLIC_AUTH_URL__?: string;
+ __PUBLIC_BACKEND_URL__?: string;
+ }
+}
+
+export function getAuthUrl(): string {
+ if (browser && window.__PUBLIC_AUTH_URL__) {
+ return window.__PUBLIC_AUTH_URL__;
+ }
+ return PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
+}
+
+export function getBackendUrl(): string {
+ if (browser && window.__PUBLIC_BACKEND_URL__) {
+ return window.__PUBLIC_BACKEND_URL__;
+ }
+ return PUBLIC_BACKEND_URL || 'http://localhost:3000';
+}
+```
+
+### Standard Auth Store Pattern (Svelte 5)
+
+```typescript
+// src/lib/stores/auth.svelte.ts
+import { browser } from '$app/environment';
+import { goto } from '$app/navigation';
+import { initializeWebAuth } from '@manacore/shared-auth';
+import { getAuthUrl } from '$lib/config/url';
+
+// Lazy initialization - only create when needed (browser only)
+let _authService: ReturnType['authService'] | null = null;
+
+function getAuthService() {
+ if (!browser) return null;
+ if (!_authService) {
+ const auth = initializeWebAuth({ baseUrl: getAuthUrl() });
+ _authService = auth.authService;
+ }
+ return _authService;
+}
+
+// Svelte 5 reactive state
+let user = $state(null);
+let accessToken = $state(null);
+let loading = $state(true);
+let initialized = $state(false);
+
+// Initialize auth on app start
+async function initialize() {
+ if (!browser || initialized) return;
+
+ const authService = getAuthService();
+ if (!authService) {
+ loading = false;
+ return;
+ }
+
+ try {
+ const currentUser = await authService.getCurrentUser();
+ if (currentUser) {
+ user = currentUser;
+ // Use getValidToken() for auto-refresh, NOT getAccessToken()
+ accessToken = await authService.getValidToken();
+ }
+ } catch (error) {
+ console.error('Auth initialization failed:', error);
+ user = null;
+ accessToken = null;
+ } finally {
+ loading = false;
+ initialized = true;
+ }
+}
+
+// Get a valid token (with auto-refresh if expired)
+async function getValidToken(): Promise {
+ const authService = getAuthService();
+ if (!authService) return null;
+
+ try {
+ return await authService.getValidToken();
+ } catch {
+ // Token refresh failed, user needs to re-login
+ await logout();
+ return null;
+ }
+}
+
+// DEPRECATED: Use getValidToken() instead
+function getAccessToken(): string | null {
+ console.warn('getAccessToken() is deprecated. Use getValidToken() for auto-refresh.');
+ return accessToken;
+}
+
+async function login(email: string, password: string): Promise {
+ const authService = getAuthService();
+ if (!authService) return false;
+
+ try {
+ const result = await authService.signIn({ email, password });
+ user = result.user;
+ accessToken = result.accessToken;
+ return true;
+ } catch {
+ return false;
+ }
+}
+
+async function logout() {
+ const authService = getAuthService();
+ if (authService) {
+ try {
+ await authService.signOut();
+ } catch {
+ // Ignore logout errors
+ }
+ }
+ user = null;
+ accessToken = null;
+ goto('/login');
+}
+
+export const authStore = {
+ // Getters (reactive)
+ get user() { return user; },
+ get loading() { return loading; },
+ get isAuthenticated() { return !!accessToken && !!user; },
+ get initialized() { return initialized; },
+
+ // Methods
+ initialize,
+ login,
+ logout,
+ getValidToken, // RECOMMENDED
+ getAccessToken, // DEPRECATED
+};
+```
+
+### Key Best Practices
+
+| Practice | Description |
+|----------|-------------|
+| **Lazy Initialization** | Only create auth service when needed (browser check) |
+| **Use `getValidToken()`** | Auto-refreshes expired tokens, unlike `getAccessToken()` |
+| **Runtime URL Injection** | Enables Docker deployments without rebuild |
+| **SSR Guard** | Always check `browser` before accessing auth service |
+| **Initialized Flag** | Prevents double initialization |
+
+### Basic Setup (Static URLs)
+
+For simpler deployments without Docker, use static environment variables:
```typescript
// src/lib/stores/auth.svelte.ts
diff --git a/docker-compose.macmini.yml b/docker-compose.macmini.yml
index baa70a8af..cbf9c42ee 100644
--- a/docker-compose.macmini.yml
+++ b/docker-compose.macmini.yml
@@ -1258,7 +1258,7 @@ services:
condition: service_healthy
environment:
NODE_ENV: production
- PORT: 3023
+ PORT: 3033
TZ: Europe/Berlin
MATRIX_HOMESERVER_URL: http://synapse:8008
MATRIX_ACCESS_TOKEN: ${MATRIX_TTS_BOT_TOKEN}
@@ -1270,9 +1270,9 @@ services:
volumes:
- matrix_tts_bot_data:/app/data
ports:
- - "3023:3023"
+ - "3033:3033"
healthcheck:
- test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3023/health"]
+ test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3033/health"]
interval: 30s
timeout: 10s
retries: 3
diff --git a/docs/CONSISTENCY_REPORT.md b/docs/CONSISTENCY_REPORT.md
index daf947ed0..50888ec13 100644
--- a/docs/CONSISTENCY_REPORT.md
+++ b/docs/CONSISTENCY_REPORT.md
@@ -13,7 +13,7 @@ Nach eingehender Analyse aller Web-Apps im Monorepo wurden folgende Bereiche auf
| Toast System | ✅ Gut | ~~Hoch~~ | ✅ Erledigt |
| API Client Patterns | ✅ Gut | ~~Hoch~~ | ✅ Erledigt |
| i18n Implementation | ✅ Gut | ~~Mittel~~ | ✅ Erledigt |
-| Auth Implementation | ✅ Gut | Niedrig | - |
+| Auth Implementation | ✅ Gut | ~~Niedrig~~ | ✅ Dokumentiert |
| Styling & Tailwind | ✅ Sehr gut | Niedrig | - |
| Komponenten & Layouts | ✅ Gut | ~~Mittel~~ | ✅ Erledigt |
@@ -28,6 +28,7 @@ Nach eingehender Analyse aller Web-Apps im Monorepo wurden folgende Bereiche auf
7. ✅ **AuthGateModal zentralisiert** - `@manacore/shared-auth-ui` für 4 Apps (chat, todo, contacts, calendar)
8. ✅ **Global Error Handler zentralisiert** - `@manacore/shared-ui` für 7 Apps (calendar, chat, clock, contacts, matrix, picture, storage)
9. ✅ **AppLoadingSkeleton zentralisiert** - `@manacore/shared-ui` für 3 Apps (contacts, todo, questions) - Apps mit spezifischen Layouts (calendar, clock) behalten lokale Version
+10. ✅ **Auth Store Pattern dokumentiert** - `.claude/guidelines/authentication.md` erweitert mit Runtime URL Injection, getValidToken(), Best Practices
---
@@ -268,6 +269,7 @@ Alle Apps nutzen **Mana Core Auth** mit `@manacore/shared-auth`.
| ~~i18n zu 6 Apps hinzufügen~~ | ✅ Erledigt |
| ~~AuthGateModal zentralisieren~~ | ✅ Erledigt (4 Apps migriert) |
| ~~Global Error Handler extrahieren~~ | ✅ Erledigt (7 Apps migriert) |
+| ~~Auth Store Pattern dokumentieren~~ | ✅ Erledigt |
### 🔴 Hohe Priorität
@@ -282,7 +284,7 @@ _(Keine offenen Aufgaben mit mittlerer Priorität)_
| Aufgabe | Aufwand | Impact |
|---------|---------|--------|
| ~~App-Skeletons vereinheitlichen~~ | ~~Niedrig~~ | ✅ Erledigt |
-| Auth Store Pattern dokumentieren | Niedrig | Onboarding |
+| ~~Auth Store Pattern dokumentieren~~ | ~~Niedrig~~ | ✅ Erledigt |
---
@@ -293,7 +295,7 @@ _(Keine offenen Aufgaben mit mittlerer Priorität)_
3. ~~**AuthGateModal** in Shared Package extrahieren~~ ✅ Erledigt (4 Apps)
4. ~~**Global Error Handler** extrahieren~~ ✅ Erledigt (7 Apps)
5. ~~**App-Skeletons vereinheitlichen**~~ ✅ Erledigt (3 Apps)
-6. **Auth Store Pattern dokumentieren** (niedrige Priorität)
+6. ~~**Auth Store Pattern dokumentieren**~~ ✅ Erledigt
---