Themes
What are Keycloak themes?
Section titled “What are Keycloak themes?”Keycloak renders several pages using its own HTML templates. Each page category is called a theme type:
| Theme type | What it controls |
|---|---|
login | The login, registration, password-reset, and OTP pages |
account | The self-service account management console |
email | Email templates (verification, password reset, etc.) |
admin | The Keycloak admin console itself |
The login theme is the one your end-users see. Customising it to match your brand makes the authentication experience feel native to your product.
Setting a realm’s login theme
Section titled “Setting a realm’s login theme”You can change the active login theme for any realm from the admin console:
- Open the admin console and select your realm from the top-left drop-down.
- Click Realm settings in the left sidebar.
- Click the Themes tab.
- Under Login theme, open the drop-down and choose your theme (e.g.,
keycloakfor the default, or your custom theme name). - Under Account theme, Email theme, and Admin console theme, choose accordingly.
- Click Save.
The change takes effect immediately — no restart required.
Structure of a custom theme
Section titled “Structure of a custom theme”A custom theme is a directory you place under Keycloak’s themes/ folder. The minimal structure for a login theme looks like this:
flowchart TD T["themes/"] --> B["my-brand/"] B --> L["login/"] L --> P["theme.properties"] L --> R["resources/"] R --> CSS["css/login.css"] R --> IMG["img/logo.png"] L --> M["messages/messages_en.properties"]
The theme.properties file declares which parent theme yours inherits from. Start by extending the built-in keycloak theme so you only need to override what you change:
parent=keycloak
import=common/keycloakWith this in place, Keycloak falls back to the parent for any template or resource you have not overridden.
Deploying a custom theme
Section titled “Deploying a custom theme”For the Quarkus-based Keycloak distribution, copy your theme directory into the container’s /opt/keycloak/themes/ folder. The simplest approach with Docker is a bind-mount:
docker run -p 8080:8080 \ -v "$(pwd)/themes/my-brand:/opt/keycloak/themes/my-brand" \ -e KC_BOOTSTRAP_ADMIN_USERNAME=admin \ -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \ quay.io/keycloak/keycloak:latest \ start-devAfter the container starts, your theme appears in the Login theme drop-down in Realm settings.
Keycloakify for React-based themes
Section titled “Keycloakify for React-based themes”If you prefer to build your login pages with React, Keycloakify (keycloakify.dev) is the recommended tool. It compiles your React components into a Keycloak-compatible theme JAR. The output is a .jar file you drop into /opt/keycloak/providers/ — Keycloak auto-discovers it on startup.
Keycloakify gives you full React component control over every login page while staying compatible with Keycloak’s internal message-passing and form-submission protocol.
Trade-offs
Section titled “Trade-offs”| Option | Benefit | Cost |
|---|---|---|
Custom theme that extends the keycloak parent | Overrides only the files you need to change, and automatically benefits from the parent theme’s fixes and new features | You must re-check every Keycloak upgrade to confirm your overridden templates are still compatible with the new parent version |
| Keycloakify (React-based theming) | Full UI control using React components your frontend team already knows | Adds a build step that packages the theme as a JAR, and you need to learn Keycloak’s internal protocol integration points |
Editing the built-in keycloak theme directly | Fast to see results because there’s no new theme structure to create | A Keycloak upgrade overwrites all built-in files, silently wiping out your changes |
Common mistakes
Section titled “Common mistakes”- Editing the built-in
keycloaktheme in place — a Keycloak upgrade overwrites every built-in file, silently discarding the customisation. Always create a separate custom theme that extends the parent instead. - Only testing the login theme type — customising the login page but forgetting that the
account,email, andadmintheme types deserve branding attention too, especially email templates, which users see just as often as the login page. - Deploying a custom theme and not restarting or clearing the cache in dev — Keycloak caches theme resources in production mode, so changes won’t appear until you restart or disable theme caching during development.
Real-world example
Keycloakify in production — many frontend teams use Keycloakify to compile the same React components used in their main app into Keycloak’s login pages, giving users one continuous brand experience from login through to the app itself.
Enterprise white-labelling — companies running a multi-tenant platform commonly create a separate custom theme per realm so each customer sees a login page with their own logo and colours, even though the same Keycloak instance runs behind the scenes.