Theme development
The branded login theme lives in keycloakify/. It's a
Keycloakify 11 project (React 18 + Vite + Tailwind CSS 4,
with shadcn-style UI components under src/components/ui). The Vite config names the
theme schuly and builds only the login theme (accountThemeImplementation: "none").
Toolchain
- Bun is the package manager (a
bun.lockis committed). Install deps withbun install. - Node engine:
^18 || >=20(the build image uses Node 22). - Maven is required by Keycloakify to package the provider jar (the Docker theme stage installs it).
Scripts (keycloakify/package.json):
| Script | What it does |
|---|---|
bun run dev | Vite dev server for fast iteration on the theme. |
bun run build | tsc && vite build. |
bun run build-keycloak-theme | build then keycloakify build — produces the provider jar(s). |
bun run storybook | Storybook (-p 6006) for previewing login pages in isolation. |
bun run format | Prettier. |
Storybook config is under
keycloakify/.storybook/. Use it to develop login pages without a running Keycloak.
Local theme iteration
cd keycloakify
bun install
bun run dev # or: bun run storybook
How the theme reaches the image
The theme is not a runtime dependency you install separately — it's baked into
the image. In the Dockerfile's first stage (node:22 + Maven), the theme is built
with npm run build-keycloak-theme, and the resulting
dist_keycloak/keycloak-theme-for-kc-all-other-versions.jar is copied into the
Keycloak builder stage as
/opt/keycloak/providers/schuly-keycloak-theme.jar. The optimized
kc.sh build then bakes it into the final image. The realm selects it via
loginTheme: "schuly".
The Docker theme stage uses
npm install/npm run build-keycloak-theme. The committedbun.lockis for local development; the image build does not rely on it.
After changing the theme, rebuild the image (docker compose -f compose.dev.yml up --build) to see it in the running console.