Branding the Login UI

The login SPA is runtime-configurable via a branding.json file served from the web root. No rebuild is required — just mount your config and assets.

How It Works

On startup, the SPA fetches /branding.json. If the file doesn’t exist or is unreachable, defaults are used. The config controls:

Configuration

Place a branding.json file in the wwwroot/ directory (or mount it into the Docker container):

{
  "appName": "Acme Corp",
  "logoUrl": "/branding/logo.svg",
  "primaryColor": "#1a56db",
  "supportEmail": "help@acme.com",
  "showForgotPassword": true,
  "customCssUrl": "/branding/custom.css"
}

Options

Property Type Default Description
appName string "Authagonal" Displayed in the header and browser tab title
logoUrl string \| null null URL to a logo image. When set, replaces the text header.
primaryColor string "#2563eb" Hex color for buttons, links, and focus indicators
supportEmail string \| null null Support contact email (reserved for future use)
showForgotPassword boolean true Show/hide the “Forgot password?” link on the login page
showRegistration boolean false Show/hide the self-service registration link
customCssUrl string \| null null URL to a custom CSS file loaded after the default styles
welcomeTitle LocalizedString null Override the login page title (plain string or { "en": "...", "de": "..." })
welcomeSubtitle LocalizedString null Override the login page subtitle
languages array \| null null Language selector options ([{ "code": "en", "label": "English" }, ...])

Docker Example

Mount your branding files into the container:

docker run -p 8080:8080 \
  -v ./my-branding/branding.json:/app/wwwroot/branding.json \
  -v ./my-branding/logo.svg:/app/wwwroot/branding/logo.svg \
  -v ./my-branding/custom.css:/app/wwwroot/branding/custom.css \
  -e Storage__ConnectionString="..." \
  -e Issuer="https://auth.example.com" \
  authagonal

Or with docker-compose:

services:
  authagonal:
    build: .
    ports:
      - "8080:8080"
    volumes:
      - ./my-branding/branding.json:/app/wwwroot/branding.json
      - ./my-branding/assets:/app/wwwroot/branding
    environment:
      - Storage__ConnectionString=...
      - Issuer=https://auth.example.com

Custom CSS

The customCssUrl option loads an additional stylesheet after the default styles, so your rules take precedence. Useful for changing fonts, adjusting spacing, or restyling specific elements.

CSS Custom Properties

The login UI exposes several CSS custom properties for fine-grained control:

Property Default Description
--brand-primary #2563eb Primary color for buttons, links, focus rings
--auth-bg #f3f4f6 Page background color
--auth-card-bg white Card/form background color
--auth-radius 0.5rem Border radius for cards and inputs
--auth-font (system) Font family
--auth-heading #111827 Heading text color

Override them in your custom CSS:

:root {
  --brand-primary: #059669;
  --auth-bg: #0f172a;
  --auth-card-bg: #1e293b;
  --auth-heading: #f8fafc;
}

The login UI uses Tailwind CSS. Custom CSS can target standard HTML elements and Tailwind utility classes. The exported UI components (Button, Input, Card, Alert, etc.) use Tailwind internally.

Dark Mode

The login SPA ships with light, dark, and system themes. The theme toggle is always visible in the layout. User selection is persisted to localStorage under the auth-theme key.

How It Works

CSS Variables

Light values are declared at :root; dark-mode overrides are scoped to .dark, so tenant branding in customCssUrl always takes precedence when supplied.

Variable Light Dark
--auth-bg #f3f4f6 #030712
--auth-card-bg #ffffff #111827
--auth-heading #111827 #f9fafb
--brand-primary #2563eb #2563eb (tenant branding wins)

Disabling or Overriding

Tenant branding always wins. To force a single theme, set your own values in customCssUrl:

/* Force dark palette regardless of user choice */
:root {
  --auth-bg: #0f172a;
  --auth-card-bg: #1e293b;
  --auth-heading: #f8fafc;
}
.dark {
  --auth-bg: #0f172a;
  --auth-card-bg: #1e293b;
  --auth-heading: #f8fafc;
}

To remove the theme toggle entirely, use the npm package path — import AuthLayout and render without the toggle, or fork the SPA.

Data Attributes

All login form elements have data-auth attributes for CSS targeting and test automation:

Attribute Element
data-auth="page" Main page wrapper
data-auth="header" Header section
data-auth="logo" Logo image
data-auth="app-name" App name heading
data-auth="content" Main content area
data-auth="languages" Language selector

Target these in your custom CSS:

[data-auth="header"] {
  background: linear-gradient(135deg, #667eea, #764ba2);
}

Example: Custom Background and Font

/* custom.css */
body {
  font-family: 'Inter', sans-serif;
  background-color: #0f172a;
}

Customization Tiers

Level What You Do Update Path
Config only Mount branding.json + logo Seamless — update the Docker image, keep your mounts
Config + CSS Add customCssUrl with style overrides Same — CSS classes are stable
npm package npm install @authagonal/login, customize branding.json, build into wwwroot/ Updatable — npm update pulls new versions
Fork the SPA Clone login-app/, modify source, build your own You own the UI — server updates are independent
Write your own Build a completely custom frontend against the auth API Full control — see Auth API for the contract

See demos/custom-server/ for a working example with custom branding (green theme, “Acme Corp”).