[FE-4185] feat(studio): custom content key for auth page logo link (#49130)

Adds a `dashboard_auth:logo_link_url` custom content key so
white-labeled deployments can point the logged-out logo link at their
own marketing site instead of the hardcoded `https://supabase.com`.

**Added:**
- `dashboard_auth:logo_link_url` custom content key (schema, types,
default `null`, sample value)

**Changed:**
- `SignInLayout` and `ForgotPasswordLayout` now resolve the
marketing-site logo href from custom content, falling back to
`https://supabase.com` — these two shared layouts cover all auth pages
(sign-in, sign-in-sso, sign-in-mfa, sign-in-partner, forgot/reset
password) in both the Next and TanStack runtimes

## To test

- On a normal deployment (key `null`): visit `/sign-in` and
`/forgot-password` logged out — the logo should still link to
`https://supabase.com`
- Set `"dashboard_auth:logo_link_url": "https://example.com"` in
`apps/studio/hooks/custom-content/custom-content.json` locally — the
logo on those pages should link to `https://example.com`
- Signed-in contexts (`logoLinkToMarketingSite` unset) still link to
`/organizations`

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added support for configuring the URL linked from authentication-page
logos.
* Authentication logos now use the configured destination when
available.
* Added a default destination to ensure logo links remain functional
when no custom URL is set.
* **Documentation**
* Added sample configuration for the customizable authentication logo
link.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
This commit is contained in:
authored and GitHub committed 2026-08-17 09:15:53 +00:00
1 parent dfb0603a36
commit b044408e79
6 files changed
+19 -2

No files matched your search

@@ -4,6 +4,7 @@ import Link from 'next/link'
import { PropsWithChildren, useEffect, useState } from 'react'
import { cn } from 'ui'
import { useCustomContent } from '@/hooks/custom-content/useCustomContent'
import { BASE_PATH } from '@/lib/constants'
type ForgotPasswordLayoutProps = {
@@ -23,6 +24,8 @@ export const ForgotPasswordLayout = ({
children,
}: PropsWithChildren<ForgotPasswordLayoutProps>) => {
const { resolvedTheme } = useTheme()
const { dashboardAuthLogoLinkUrl } = useCustomContent(['dashboard_auth:logo_link_url'])
const marketingSiteUrl = dashboardAuthLogoLinkUrl ?? 'https://supabase.com'
// Addresses hydration issue with `resolvedTheme` as its undefined during SSR and the first (hydrating) client render
const [mounted, setMounted] = useState(false)
@@ -39,7 +42,7 @@ export const ForgotPasswordLayout = ({
<nav className="relative flex items-center justify-between sm:h-10">
<div className="flex shrink-0 grow items-center lg:grow-0">
<div className="flex w-full items-center justify-between md:w-auto">
<Link href={logoLinkToMarketingSite ? 'https://supabase.com' : '/organizations'}>
<Link href={logoLinkToMarketingSite ? marketingSiteUrl : '/organizations'}>
<Image
src={
mounted && resolvedTheme?.includes('dark')
@@ -16,6 +16,7 @@ import {
import { DocsButton } from '@/components/ui/DocsButton'
import { InlineLink } from '@/components/ui/InlineLink'
import { IdentityProviderIcon } from '@/components/ui/ProviderIcon'
import { useCustomContent } from '@/hooks/custom-content/useCustomContent'
import { useInboundBranding } from '@/hooks/misc/useInboundBranding'
import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
import { BASE_PATH, DOCS_URL } from '@/lib/constants'
@@ -65,6 +66,8 @@ export const SignInLayout = ({
const ongoingIncident = useFlag('ongoingIncident')
const { destination, focusProvider } = useInboundBranding(inboundFlow)
const { dashboardAuthLogoLinkUrl } = useCustomContent(['dashboard_auth:logo_link_url'])
const marketingSiteUrl = dashboardAuthLogoLinkUrl ?? 'https://supabase.com'
// Addresses hydration issue with `resolvedTheme` as its undefined during SSR and the first (hydrating) client render
const [mounted, setMounted] = useState(false)
@@ -204,7 +207,7 @@ export const SignInLayout = ({
<nav className="relative flex items-center justify-between sm:h-10">
<div className="flex items-center grow shrink-0 lg:grow-0">
<div className="flex items-center justify-between w-full md:w-auto">
<Link href={logoLinkToMarketingSite ? 'https://supabase.com' : '/organizations'}>
<Link href={logoLinkToMarketingSite ? marketingSiteUrl : '/organizations'}>
<img
src={
mounted && resolvedTheme?.includes('dark')
@@ -7,6 +7,8 @@ export type CustomContentTypes = {
dashboardAuthCustomProviders: string[]
dashboardAuthLogoLinkUrl: string
docsRowLevelSecurityGuidePath: string
organizationLegalDocuments: {
@@ -7,6 +7,8 @@
"dashboard_auth:custom_providers": null,
"dashboard_auth:logo_link_url": null,
"docs:row_level_security_guide_path": "/guides/auth/row-level-security",
"organization:legal_documents": null,
@@ -7,6 +7,8 @@
"dashboard_auth:custom_providers": ["Nimbus"],
"dashboard_auth:logo_link_url": "https://example.com",
"docs:row_level_security_guide_path": "/guides/database/postgres/row-level-security",
"organization:legal_documents": [
@@ -24,6 +24,11 @@
}
},
"dashboard_auth:logo_link_url": {
"type": ["string", "null"],
"description": "The URL for the logo on the auth pages (sign in, forgot password, etc.) links to. Defaults to https://supabase.com"
},
"docs:row_level_security_guide_path": {
"type": ["string"],
"description": "The path to the row level security guide in the docs"