From 12cad9d3fb9b2bf19b7ae81161564cb0b51e8955 Mon Sep 17 00:00:00 2001 From: ajnart Date: Mon, 24 Aug 2026 09:18:45 +0200 Subject: [PATCH] fix: preserve default header and login branding --- .../src/app/[locale]/auth/invite/[id]/page.tsx | 5 ++++- apps/nextjs/src/app/[locale]/auth/login/page.tsx | 4 ++++ .../mysql/0048_add_user_header_preferences.sql | 2 +- .../db/migrations/mysql/meta/0048_snapshot.json | 2 +- .../db/migrations/mysql/meta/0049_snapshot.json | 2 +- .../0014_add_user_header_preferences.sql | 2 +- .../migrations/postgresql/meta/0014_snapshot.json | 2 +- .../migrations/postgresql/meta/0015_snapshot.json | 2 +- .../sqlite/0046_add_user_header_preferences.sql | 2 +- .../db/migrations/sqlite/meta/0046_snapshot.json | 2 +- .../db/migrations/sqlite/meta/0047_snapshot.json | 2 +- packages/onboarding/src/onboarding-auth-shell.tsx | 8 ++++++-- packages/server-settings/src/index.ts | 14 ++++++++++++++ packages/validation/src/header-preferences.ts | 2 +- 14 files changed, 38 insertions(+), 13 deletions(-) diff --git a/apps/nextjs/src/app/[locale]/auth/invite/[id]/page.tsx b/apps/nextjs/src/app/[locale]/auth/invite/[id]/page.tsx index cf1af46bb..5f90f790e 100644 --- a/apps/nextjs/src/app/[locale]/auth/invite/[id]/page.tsx +++ b/apps/nextjs/src/app/[locale]/auth/invite/[id]/page.tsx @@ -7,7 +7,7 @@ import { isProviderEnabled } from "@homarr/auth/server"; import { and, db, eq } from "@homarr/db"; import { invites } from "@homarr/db/schema"; import { OnboardingAuthShell } from "@homarr/onboarding"; -import { defaultBrandingSettings } from "@homarr/server-settings"; +import { defaultBrandingSettings, getBrandingColorOverrides } from "@homarr/server-settings"; import { getI18n } from "@homarr/translation/server"; import { RegistrationForm } from "./_registration-form"; @@ -47,6 +47,7 @@ export default async function InviteUsagePage(props: InviteUsagePageProps) { const [t, serverSettings] = await Promise.all([getI18n("user.page.invite"), getRscServerSettingsAsync()]); const branding = serverSettings.branding; + const wordmarkColors = getBrandingColorOverrides(branding); const showCustomAppName = branding.authBranding.showAppName && branding.appName !== defaultBrandingSettings.appName; const showCustomGreeting = branding.authBranding.showGreeting && branding.greeting.length > 0; const title = showCustomAppName ? t("titleWithAppName", { appName: branding.appName }) : t("title"); @@ -65,6 +66,8 @@ export default async function InviteUsagePage(props: InviteUsagePageProps) { showAppLogo={branding.authBranding.showLogo} primaryColor={branding.primaryColor} secondaryColor={branding.secondaryColor} + wordmarkPrimaryColor={wordmarkColors.primaryColor} + wordmarkSecondaryColor={wordmarkColors.secondaryColor} logoImageUrl={branding.logoImageUrl ?? undefined} backgroundImageUrl={branding.signInBackgroundImageUrl ?? undefined} backgroundOverlay={branding.signInBackgroundOverlay} diff --git a/apps/nextjs/src/app/[locale]/auth/login/page.tsx b/apps/nextjs/src/app/[locale]/auth/login/page.tsx index 9aea9d931..c5bb4f050 100644 --- a/apps/nextjs/src/app/[locale]/auth/login/page.tsx +++ b/apps/nextjs/src/app/[locale]/auth/login/page.tsx @@ -6,6 +6,7 @@ import { getRscServerSettingsAsync } from "@homarr/api/server-settings-server"; import { env } from "@homarr/auth/env"; import { auth } from "@homarr/auth/next"; import { OnboardingAuthShell } from "@homarr/onboarding"; +import { getBrandingColorOverrides } from "@homarr/server-settings"; import { getI18n } from "@homarr/translation/server"; import { sanitizeRedirectionUrl } from "@homarr/validation/redirection-url"; @@ -28,6 +29,7 @@ export default async function Login(props: LoginProps) { const [t, serverSettings] = await Promise.all([getI18n("user.page.login"), getRscServerSettingsAsync()]); const branding = serverSettings.branding; + const wordmarkColors = getBrandingColorOverrides(branding); const showCustomGreeting = branding.authBranding.showGreeting && branding.greeting.length > 0; const description = showCustomGreeting ? branding.greeting : t("subtitle"); @@ -41,6 +43,8 @@ export default async function Login(props: LoginProps) { showAppLogo={branding.authBranding.showLogo} primaryColor={branding.primaryColor} secondaryColor={branding.secondaryColor} + wordmarkPrimaryColor={wordmarkColors.primaryColor} + wordmarkSecondaryColor={wordmarkColors.secondaryColor} logoImageUrl={branding.logoImageUrl ?? undefined} backgroundImageUrl={branding.signInBackgroundImageUrl ?? undefined} backgroundOverlay={branding.signInBackgroundOverlay} diff --git a/packages/db/migrations/mysql/0048_add_user_header_preferences.sql b/packages/db/migrations/mysql/0048_add_user_header_preferences.sql index b96a49e79..47411b784 100644 --- a/packages/db/migrations/mysql/0048_add_user_header_preferences.sql +++ b/packages/db/migrations/mysql/0048_add_user_header_preferences.sql @@ -1 +1 @@ -ALTER TABLE `user` ADD `header_preferences` text DEFAULT ('{"version":3,"visible":true,"searchDisplay":"input","zones":{"left":[{"type":"builtin","id":"logo"}],"center":[{"type":"builtin","id":"search"}],"right":[{"type":"builtin","id":"user"},{"type":"builtin","id":"boardEdit"},{"type":"builtin","id":"boardSettings"}]}}') NOT NULL; +ALTER TABLE `user` ADD `header_preferences` text DEFAULT ('{"version":3,"visible":true,"searchDisplay":"input","zones":{"left":[{"type":"builtin","id":"logo"}],"center":[{"type":"builtin","id":"search"}],"right":[{"type":"builtin","id":"boardEdit"},{"type":"builtin","id":"boardSettings"},{"type":"builtin","id":"user"}]}}') NOT NULL; diff --git a/packages/db/migrations/mysql/meta/0048_snapshot.json b/packages/db/migrations/mysql/meta/0048_snapshot.json index 2c00234cb..daa484a63 100644 --- a/packages/db/migrations/mysql/meta/0048_snapshot.json +++ b/packages/db/migrations/mysql/meta/0048_snapshot.json @@ -2656,7 +2656,7 @@ "primaryKey": false, "notNull": true, "autoincrement": false, - "default": "('{\"version\":3,\"visible\":true,\"searchDisplay\":\"input\",\"zones\":{\"left\":[{\"type\":\"builtin\",\"id\":\"logo\"}],\"center\":[{\"type\":\"builtin\",\"id\":\"search\"}],\"right\":[{\"type\":\"builtin\",\"id\":\"user\"},{\"type\":\"builtin\",\"id\":\"boardEdit\"},{\"type\":\"builtin\",\"id\":\"boardSettings\"}]}}')" + "default": "('{\"version\":3,\"visible\":true,\"searchDisplay\":\"input\",\"zones\":{\"left\":[{\"type\":\"builtin\",\"id\":\"logo\"}],\"center\":[{\"type\":\"builtin\",\"id\":\"search\"}],\"right\":[{\"type\":\"builtin\",\"id\":\"boardEdit\"},{\"type\":\"builtin\",\"id\":\"boardSettings\"},{\"type\":\"builtin\",\"id\":\"user\"}]}}')" }, "completed_manage_tour": { "name": "completed_manage_tour", diff --git a/packages/db/migrations/mysql/meta/0049_snapshot.json b/packages/db/migrations/mysql/meta/0049_snapshot.json index 62566588b..5d9e40211 100644 --- a/packages/db/migrations/mysql/meta/0049_snapshot.json +++ b/packages/db/migrations/mysql/meta/0049_snapshot.json @@ -2656,7 +2656,7 @@ "primaryKey": false, "notNull": true, "autoincrement": false, - "default": "('{\"version\":3,\"visible\":true,\"searchDisplay\":\"input\",\"zones\":{\"left\":[{\"type\":\"builtin\",\"id\":\"logo\"}],\"center\":[{\"type\":\"builtin\",\"id\":\"search\"}],\"right\":[{\"type\":\"builtin\",\"id\":\"user\"},{\"type\":\"builtin\",\"id\":\"boardEdit\"},{\"type\":\"builtin\",\"id\":\"boardSettings\"}]}}')" + "default": "('{\"version\":3,\"visible\":true,\"searchDisplay\":\"input\",\"zones\":{\"left\":[{\"type\":\"builtin\",\"id\":\"logo\"}],\"center\":[{\"type\":\"builtin\",\"id\":\"search\"}],\"right\":[{\"type\":\"builtin\",\"id\":\"boardEdit\"},{\"type\":\"builtin\",\"id\":\"boardSettings\"},{\"type\":\"builtin\",\"id\":\"user\"}]}}')" }, "completed_manage_tour": { "name": "completed_manage_tour", diff --git a/packages/db/migrations/postgresql/0014_add_user_header_preferences.sql b/packages/db/migrations/postgresql/0014_add_user_header_preferences.sql index 6f755e082..5684b7983 100644 --- a/packages/db/migrations/postgresql/0014_add_user_header_preferences.sql +++ b/packages/db/migrations/postgresql/0014_add_user_header_preferences.sql @@ -1 +1 @@ -ALTER TABLE "user" ADD COLUMN "header_preferences" text DEFAULT '{"version":3,"visible":true,"searchDisplay":"input","zones":{"left":[{"type":"builtin","id":"logo"}],"center":[{"type":"builtin","id":"search"}],"right":[{"type":"builtin","id":"user"},{"type":"builtin","id":"boardEdit"},{"type":"builtin","id":"boardSettings"}]}}' NOT NULL; +ALTER TABLE "user" ADD COLUMN "header_preferences" text DEFAULT '{"version":3,"visible":true,"searchDisplay":"input","zones":{"left":[{"type":"builtin","id":"logo"}],"center":[{"type":"builtin","id":"search"}],"right":[{"type":"builtin","id":"boardEdit"},{"type":"builtin","id":"boardSettings"},{"type":"builtin","id":"user"}]}}' NOT NULL; diff --git a/packages/db/migrations/postgresql/meta/0014_snapshot.json b/packages/db/migrations/postgresql/meta/0014_snapshot.json index a8dec36fa..fadb1457b 100644 --- a/packages/db/migrations/postgresql/meta/0014_snapshot.json +++ b/packages/db/migrations/postgresql/meta/0014_snapshot.json @@ -2521,7 +2521,7 @@ "type": "text", "primaryKey": false, "notNull": true, - "default": "'{\"version\":3,\"visible\":true,\"searchDisplay\":\"input\",\"zones\":{\"left\":[{\"type\":\"builtin\",\"id\":\"logo\"}],\"center\":[{\"type\":\"builtin\",\"id\":\"search\"}],\"right\":[{\"type\":\"builtin\",\"id\":\"user\"},{\"type\":\"builtin\",\"id\":\"boardEdit\"},{\"type\":\"builtin\",\"id\":\"boardSettings\"}]}}'" + "default": "'{\"version\":3,\"visible\":true,\"searchDisplay\":\"input\",\"zones\":{\"left\":[{\"type\":\"builtin\",\"id\":\"logo\"}],\"center\":[{\"type\":\"builtin\",\"id\":\"search\"}],\"right\":[{\"type\":\"builtin\",\"id\":\"boardEdit\"},{\"type\":\"builtin\",\"id\":\"boardSettings\"},{\"type\":\"builtin\",\"id\":\"user\"}]}}'" }, "completed_manage_tour": { "name": "completed_manage_tour", diff --git a/packages/db/migrations/postgresql/meta/0015_snapshot.json b/packages/db/migrations/postgresql/meta/0015_snapshot.json index 613a5ab85..431d54f14 100644 --- a/packages/db/migrations/postgresql/meta/0015_snapshot.json +++ b/packages/db/migrations/postgresql/meta/0015_snapshot.json @@ -2521,7 +2521,7 @@ "type": "text", "primaryKey": false, "notNull": true, - "default": "'{\"version\":3,\"visible\":true,\"searchDisplay\":\"input\",\"zones\":{\"left\":[{\"type\":\"builtin\",\"id\":\"logo\"}],\"center\":[{\"type\":\"builtin\",\"id\":\"search\"}],\"right\":[{\"type\":\"builtin\",\"id\":\"user\"},{\"type\":\"builtin\",\"id\":\"boardEdit\"},{\"type\":\"builtin\",\"id\":\"boardSettings\"}]}}'" + "default": "'{\"version\":3,\"visible\":true,\"searchDisplay\":\"input\",\"zones\":{\"left\":[{\"type\":\"builtin\",\"id\":\"logo\"}],\"center\":[{\"type\":\"builtin\",\"id\":\"search\"}],\"right\":[{\"type\":\"builtin\",\"id\":\"boardEdit\"},{\"type\":\"builtin\",\"id\":\"boardSettings\"},{\"type\":\"builtin\",\"id\":\"user\"}]}}'" }, "completed_manage_tour": { "name": "completed_manage_tour", diff --git a/packages/db/migrations/sqlite/0046_add_user_header_preferences.sql b/packages/db/migrations/sqlite/0046_add_user_header_preferences.sql index 243ceac11..a9db8f58e 100644 --- a/packages/db/migrations/sqlite/0046_add_user_header_preferences.sql +++ b/packages/db/migrations/sqlite/0046_add_user_header_preferences.sql @@ -1 +1 @@ -ALTER TABLE `user` ADD `header_preferences` text DEFAULT '{"version":3,"visible":true,"searchDisplay":"input","zones":{"left":[{"type":"builtin","id":"logo"}],"center":[{"type":"builtin","id":"search"}],"right":[{"type":"builtin","id":"user"},{"type":"builtin","id":"boardEdit"},{"type":"builtin","id":"boardSettings"}]}}' NOT NULL; +ALTER TABLE `user` ADD `header_preferences` text DEFAULT '{"version":3,"visible":true,"searchDisplay":"input","zones":{"left":[{"type":"builtin","id":"logo"}],"center":[{"type":"builtin","id":"search"}],"right":[{"type":"builtin","id":"boardEdit"},{"type":"builtin","id":"boardSettings"},{"type":"builtin","id":"user"}]}}' NOT NULL; diff --git a/packages/db/migrations/sqlite/meta/0046_snapshot.json b/packages/db/migrations/sqlite/meta/0046_snapshot.json index 3c60a7b18..7397a8052 100644 --- a/packages/db/migrations/sqlite/meta/0046_snapshot.json +++ b/packages/db/migrations/sqlite/meta/0046_snapshot.json @@ -2551,7 +2551,7 @@ "primaryKey": false, "notNull": true, "autoincrement": false, - "default": "'{\"version\":3,\"visible\":true,\"searchDisplay\":\"input\",\"zones\":{\"left\":[{\"type\":\"builtin\",\"id\":\"logo\"}],\"center\":[{\"type\":\"builtin\",\"id\":\"search\"}],\"right\":[{\"type\":\"builtin\",\"id\":\"user\"},{\"type\":\"builtin\",\"id\":\"boardEdit\"},{\"type\":\"builtin\",\"id\":\"boardSettings\"}]}}'" + "default": "'{\"version\":3,\"visible\":true,\"searchDisplay\":\"input\",\"zones\":{\"left\":[{\"type\":\"builtin\",\"id\":\"logo\"}],\"center\":[{\"type\":\"builtin\",\"id\":\"search\"}],\"right\":[{\"type\":\"builtin\",\"id\":\"boardEdit\"},{\"type\":\"builtin\",\"id\":\"boardSettings\"},{\"type\":\"builtin\",\"id\":\"user\"}]}}'" }, "completed_manage_tour": { "name": "completed_manage_tour", diff --git a/packages/db/migrations/sqlite/meta/0047_snapshot.json b/packages/db/migrations/sqlite/meta/0047_snapshot.json index ad39e66ca..c44989031 100644 --- a/packages/db/migrations/sqlite/meta/0047_snapshot.json +++ b/packages/db/migrations/sqlite/meta/0047_snapshot.json @@ -2551,7 +2551,7 @@ "primaryKey": false, "notNull": true, "autoincrement": false, - "default": "'{\"version\":3,\"visible\":true,\"searchDisplay\":\"input\",\"zones\":{\"left\":[{\"type\":\"builtin\",\"id\":\"logo\"}],\"center\":[{\"type\":\"builtin\",\"id\":\"search\"}],\"right\":[{\"type\":\"builtin\",\"id\":\"user\"},{\"type\":\"builtin\",\"id\":\"boardEdit\"},{\"type\":\"builtin\",\"id\":\"boardSettings\"}]}}'" + "default": "'{\"version\":3,\"visible\":true,\"searchDisplay\":\"input\",\"zones\":{\"left\":[{\"type\":\"builtin\",\"id\":\"logo\"}],\"center\":[{\"type\":\"builtin\",\"id\":\"search\"}],\"right\":[{\"type\":\"builtin\",\"id\":\"boardEdit\"},{\"type\":\"builtin\",\"id\":\"boardSettings\"},{\"type\":\"builtin\",\"id\":\"user\"}]}}'" }, "completed_manage_tour": { "name": "completed_manage_tour", diff --git a/packages/onboarding/src/onboarding-auth-shell.tsx b/packages/onboarding/src/onboarding-auth-shell.tsx index 5f7a85002..c06a6595b 100644 --- a/packages/onboarding/src/onboarding-auth-shell.tsx +++ b/packages/onboarding/src/onboarding-auth-shell.tsx @@ -16,6 +16,8 @@ interface OnboardingAuthShellProps { showAppLogo?: boolean; primaryColor?: string; secondaryColor?: string; + wordmarkPrimaryColor?: string; + wordmarkSecondaryColor?: string; logoImageUrl?: string; backgroundImageUrl?: string; backgroundOverlay?: number; @@ -33,6 +35,8 @@ export const OnboardingAuthShell = ({ showAppLogo = false, primaryColor, secondaryColor, + wordmarkPrimaryColor, + wordmarkSecondaryColor, logoImageUrl, backgroundImageUrl, backgroundOverlay = 0.55, @@ -66,8 +70,8 @@ export const OnboardingAuthShell = ({ appName={appName} showAppName={showAppName} showAppLogo={showAppLogo} - primaryColor={primaryColor} - secondaryColor={secondaryColor} + primaryColor={wordmarkPrimaryColor} + secondaryColor={wordmarkSecondaryColor} logoImageUrl={logoImageUrl} /> diff --git a/packages/server-settings/src/index.ts b/packages/server-settings/src/index.ts index 4d95d6466..1921e37d4 100644 --- a/packages/server-settings/src/index.ts +++ b/packages/server-settings/src/index.ts @@ -73,6 +73,20 @@ export const defaultBrandingSettings: BrandingSettings = { defaultRadius: "md", }; +const hasDefaultBrandingColors = (branding: Pick) => + branding.primaryColor.toLowerCase() === defaultBrandingSettings.primaryColor && + branding.secondaryColor.toLowerCase() === defaultBrandingSettings.secondaryColor; + +export const getBrandingColorOverrides = ( + branding: Pick, +): Partial> => { + if (hasDefaultBrandingColors(branding)) return {}; + return { + primaryColor: branding.primaryColor, + secondaryColor: branding.secondaryColor, + }; +}; + const legacyLoginBrandingSchema = z.object({ showCustomAppNameOnLogin: z.boolean().optional(), showCustomLogoOnLogin: z.boolean().optional(), diff --git a/packages/validation/src/header-preferences.ts b/packages/validation/src/header-preferences.ts index 36807960e..d0f147d2b 100644 --- a/packages/validation/src/header-preferences.ts +++ b/packages/validation/src/header-preferences.ts @@ -208,9 +208,9 @@ export const defaultHeaderPreferences = { left: [createBuiltinHeaderItem("logo")], center: [createBuiltinHeaderItem("search")], right: [ - createBuiltinHeaderItem("user"), createBuiltinHeaderItem("boardEdit"), createBuiltinHeaderItem("boardSettings"), + createBuiltinHeaderItem("user"), ], }, } satisfies HeaderPreferences;