From 8525020e8a95b62812ae9019309571e6182a207b Mon Sep 17 00:00:00 2001 From: Till-JS <101404291+Till-JS@users.noreply.github.com> Date: Mon, 2 Feb 2026 14:53:51 +0100 Subject: [PATCH] feat(playground): integrate shared auth UI for consistent login experience - Add PlaygroundLogo to shared-branding package - Add playground to APP_BRANDING, APP_ICONS, and APP_URLS - Replace custom login/register pages with shared-auth-ui components - Update authStore with resendVerificationEmail and improved signUp - Add Caddy reverse proxy entry for playground.mana.how Co-Authored-By: Claude Opus 4.5 --- docker/caddy/Caddyfile.production | 7 + packages/shared-branding/src/app-icons.ts | 4 + packages/shared-branding/src/config.ts | 12 ++ packages/shared-branding/src/index.ts | 1 + .../src/logos/PlaygroundLogo.svelte | 13 ++ packages/shared-branding/src/logos/index.ts | 1 + packages/shared-branding/src/mana-apps.ts | 1 + packages/shared-branding/src/types.ts | 3 +- pnpm-lock.yaml | 15 ++ services/llm-playground/package.json | 7 +- .../src/lib/stores/auth.svelte.ts | 48 +++++- .../src/routes/(auth)/+layout.svelte | 7 +- .../src/routes/(auth)/login/+page.svelte | 131 +++++----------- .../src/routes/(auth)/register/+page.svelte | 145 ++++-------------- 14 files changed, 169 insertions(+), 226 deletions(-) create mode 100644 packages/shared-branding/src/logos/PlaygroundLogo.svelte diff --git a/docker/caddy/Caddyfile.production b/docker/caddy/Caddyfile.production index ed49864fe..ee020a1eb 100644 --- a/docker/caddy/Caddyfile.production +++ b/docker/caddy/Caddyfile.production @@ -78,6 +78,13 @@ contacts-api.mana.how { reverse_proxy localhost:3015 } +# ============================================ +# LLM Playground +# ============================================ +playground.mana.how { + reverse_proxy localhost:5090 +} + # ============================================ # Monitoring & Analytics # ============================================ diff --git a/packages/shared-branding/src/app-icons.ts b/packages/shared-branding/src/app-icons.ts index 56cb193b7..5a6e704a9 100644 --- a/packages/shared-branding/src/app-icons.ts +++ b/packages/shared-branding/src/app-icons.ts @@ -69,6 +69,9 @@ const questionsSvg = ``; +// Playground icon (code/terminal with cyan gradient) +const playgroundSvg = ``; + /** * App icons as data URLs * Use these directly in or CSS background-image @@ -94,6 +97,7 @@ export const APP_ICONS = { inventory: svgToDataUrl(inventorySvg), questions: svgToDataUrl(questionsSvg), matrix: svgToDataUrl(matrixSvg), + playground: svgToDataUrl(playgroundSvg), } as const; export type AppIconId = keyof typeof APP_ICONS; diff --git a/packages/shared-branding/src/config.ts b/packages/shared-branding/src/config.ts index d63da8518..4ed119918 100644 --- a/packages/shared-branding/src/config.ts +++ b/packages/shared-branding/src/config.ts @@ -259,6 +259,18 @@ export const APP_BRANDING: Record = { logoStroke: true, logoStrokeWidth: 1.5, }, + playground: { + id: 'playground', + name: 'Playground', + tagline: 'LLM Playground', + primaryColor: '#06b6d4', + secondaryColor: '#22d3ee', + // Code/terminal icon for LLM playground + logoPath: 'M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5', + logoViewBox: '0 0 24 24', + logoStroke: true, + logoStrokeWidth: 1.5, + }, }; /** diff --git a/packages/shared-branding/src/index.ts b/packages/shared-branding/src/index.ts index d316eb959..0458b0684 100644 --- a/packages/shared-branding/src/index.ts +++ b/packages/shared-branding/src/index.ts @@ -34,6 +34,7 @@ export { QuestionsLogo, SkillTreeLogo, PlantaLogo, + PlaygroundLogo, } from './logos'; // Configuration diff --git a/packages/shared-branding/src/logos/PlaygroundLogo.svelte b/packages/shared-branding/src/logos/PlaygroundLogo.svelte new file mode 100644 index 000000000..4053abe16 --- /dev/null +++ b/packages/shared-branding/src/logos/PlaygroundLogo.svelte @@ -0,0 +1,13 @@ + + + diff --git a/packages/shared-branding/src/logos/index.ts b/packages/shared-branding/src/logos/index.ts index b39f38e61..2b830052f 100644 --- a/packages/shared-branding/src/logos/index.ts +++ b/packages/shared-branding/src/logos/index.ts @@ -21,3 +21,4 @@ export { default as ClockLogo } from './ClockLogo.svelte'; export { default as QuestionsLogo } from './QuestionsLogo.svelte'; export { default as SkillTreeLogo } from './SkillTreeLogo.svelte'; export { default as PlantaLogo } from './PlantaLogo.svelte'; +export { default as PlaygroundLogo } from './PlaygroundLogo.svelte'; diff --git a/packages/shared-branding/src/mana-apps.ts b/packages/shared-branding/src/mana-apps.ts index 9076541bc..cdd74b0da 100644 --- a/packages/shared-branding/src/mana-apps.ts +++ b/packages/shared-branding/src/mana-apps.ts @@ -412,6 +412,7 @@ export const APP_URLS: Record = { inventory: { dev: 'http://localhost:5188', prod: 'https://inventory.manacore.app' }, questions: { dev: 'http://localhost:5111', prod: 'https://questions.manacore.app' }, matrix: { dev: 'http://localhost:5180', prod: 'https://matrix.mana.how' }, + playground: { dev: 'http://localhost:5190', prod: 'https://playground.mana.how' }, }; /** diff --git a/packages/shared-branding/src/types.ts b/packages/shared-branding/src/types.ts index 7e12a5b36..1b1d72f37 100644 --- a/packages/shared-branding/src/types.ts +++ b/packages/shared-branding/src/types.ts @@ -21,7 +21,8 @@ export type AppId = | 'inventory' | 'questions' | 'skilltree' - | 'planta'; + | 'planta' + | 'playground'; /** * App branding configuration diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7fbdf0645..f0e582ce1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5361,9 +5361,24 @@ importers: '@manacore/shared-auth': specifier: workspace:* version: link:../../packages/shared-auth + '@manacore/shared-auth-ui': + specifier: workspace:* + version: link:../../packages/shared-auth-ui + '@manacore/shared-branding': + specifier: workspace:* + version: link:../../packages/shared-branding + '@manacore/shared-i18n': + specifier: workspace:* + version: link:../../packages/shared-i18n + '@manacore/shared-icons': + specifier: workspace:* + version: link:../../packages/shared-icons marked: specifier: ^17.0.0 version: 17.0.1 + svelte-i18n: + specifier: ^4.0.1 + version: 4.0.1(svelte@5.44.0) devDependencies: '@sveltejs/adapter-node': specifier: ^5.4.0 diff --git a/services/llm-playground/package.json b/services/llm-playground/package.json index ff7b6d12c..5727598a8 100644 --- a/services/llm-playground/package.json +++ b/services/llm-playground/package.json @@ -25,6 +25,11 @@ }, "dependencies": { "@manacore/shared-auth": "workspace:*", - "marked": "^17.0.0" + "@manacore/shared-auth-ui": "workspace:*", + "@manacore/shared-branding": "workspace:*", + "@manacore/shared-i18n": "workspace:*", + "@manacore/shared-icons": "workspace:*", + "marked": "^17.0.0", + "svelte-i18n": "^4.0.1" } } diff --git a/services/llm-playground/src/lib/stores/auth.svelte.ts b/services/llm-playground/src/lib/stores/auth.svelte.ts index 46e893de1..d5d26090e 100644 --- a/services/llm-playground/src/lib/stores/auth.svelte.ts +++ b/services/llm-playground/src/lib/stores/auth.svelte.ts @@ -82,10 +82,31 @@ export const authStore = { return result; }, - async signUp(email: string, password: string, name?: string) { + async signUp(email: string, password: string) { const authService = getAuthService(); - if (!authService) throw new Error('Auth not initialized'); - return authService.signUp(email, password, name); + if (!authService) { + return { success: false, error: 'Auth not available', needsVerification: false }; + } + + try { + const sourceAppUrl = browser ? window.location.origin : undefined; + const result = await authService.signUp(email, password, undefined, sourceAppUrl); + + if (!result.success) { + return { success: false, error: result.error || 'Signup failed', needsVerification: false }; + } + + if (result.needsVerification) { + return { success: true, needsVerification: true }; + } + + // Auto sign in after successful signup + const signInResult = await this.signIn(email, password); + return { ...signInResult, needsVerification: false }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unknown error'; + return { success: false, error: errorMessage, needsVerification: false }; + } }, async signOut() { @@ -102,4 +123,25 @@ export const authStore = { if (!authService) return null; return authService.getAppToken(); }, + + async resendVerificationEmail(email: string) { + const authService = getAuthService(); + if (!authService) { + return { success: false, error: 'Auth not available' }; + } + + try { + const sourceAppUrl = typeof window !== 'undefined' ? window.location.origin : undefined; + const result = await authService.resendVerificationEmail(email, sourceAppUrl); + + if (!result.success) { + return { success: false, error: result.error || 'Failed to resend verification email' }; + } + + return { success: true }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unknown error'; + return { success: false, error: errorMessage }; + } + }, }; diff --git a/services/llm-playground/src/routes/(auth)/+layout.svelte b/services/llm-playground/src/routes/(auth)/+layout.svelte index 967466d63..fd5e639d7 100644 --- a/services/llm-playground/src/routes/(auth)/+layout.svelte +++ b/services/llm-playground/src/routes/(auth)/+layout.svelte @@ -3,9 +3,4 @@ let { children }: { children: Snippet } = $props(); -
- {@render children()} -
+{@render children()} diff --git a/services/llm-playground/src/routes/(auth)/login/+page.svelte b/services/llm-playground/src/routes/(auth)/login/+page.svelte index bdcd35a8a..394c1c3bf 100644 --- a/services/llm-playground/src/routes/(auth)/login/+page.svelte +++ b/services/llm-playground/src/routes/(auth)/login/+page.svelte @@ -1,109 +1,48 @@ -
-

LLM Playground

-

- Melde dich an, um den Playground zu nutzen. -

+ + {translations.title} | LLM Playground + - {#if error} -
- {error} -
- {/if} - -
-
- - -
- -
- - -
- - -
- -

- Noch kein Konto? Registrieren -

-
+ diff --git a/services/llm-playground/src/routes/(auth)/register/+page.svelte b/services/llm-playground/src/routes/(auth)/register/+page.svelte index 340e47029..4cfec7ce2 100644 --- a/services/llm-playground/src/routes/(auth)/register/+page.svelte +++ b/services/llm-playground/src/routes/(auth)/register/+page.svelte @@ -1,129 +1,36 @@ -
-

Registrieren

+ + {translations.title} | LLM Playground + - {#if success} -
-

- Registrierung erfolgreich! Du kannst dich jetzt anmelden. -

- Zum Login -
- {:else} - {#if error} -
- {error} -
- {/if} - -
-
- - -
- -
- - -
- -
- - -
- - -
- -

- Bereits ein Konto? Anmelden -

- {/if} -
+