Keywind is a component-based Keycloak Login Theme built with Tailwind CSS and Alpine.js.
- Error
- Login
- Login Config TOTP
- Login IDP Link Confirm
- Login OAuth Grant
- Login OTP
- Login Page Expired
- Login Password
- Login Recovery Authn Code Config
- Login Recovery Authn Code Input
- Login Reset Password
- Login Update Password
- Login Update Profile
- Login Username
- Login X.509 Info
- Logout Confirm
- Register
- Select Authenticator
- Terms and Conditions
- WebAuthn Authenticate
- WebAuthn Error
- WebAuthn Register
- Apple
- Bitbucket
- Discord
- GitHub
- GitLab
- Microsoft
- OpenID
- Red Hat OpenShift
- PayPal
- Slack
- Stack Overflow
Keywind has been designed with component-based architecture from the start, and you can customize as little or as much Keywind as you need:
- Deploy Keywind Login Theme
- Create your own Login Theme
- Specify parent theme in theme properties:
parent=keywind
- Brand and customize components with FreeMarker
When you do need to customize a palette, you can configure your colors under the colors key in the theme section of Tailwind config file:
tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
primary: colors.red,
},
},
},
};Read more about Tailwind CSS configuration in the documentation.
You can update Keywind components in your own child theme. For example, create a copy of the body component and change the background:
theme/mytheme/login/components/atoms/body.ftl
<#macro kw>
<body class="bg-primary-100">
<#nested>
</body>
</#macro>
You can verify every login page without a Keycloak server. FreeMarker templates are rendered with a mock data model into static HTML; Vite serves those pages and hot-reloads CSS/JS.
- Node.js 20+ (npm or pnpm)
- Java 21 + Maven, or Docker (used automatically if Maven is missing)
npm install # or: pnpm install
npm run mock:generate
npm run devThen open http://localhost:5173/ — an index lists every mock page (login, register, OTP, WebAuthn, …).
| Script | What it does |
|---|---|
npm run mock:generate |
Render theme/keywind/login/**/*.ftl → html/login/*.html + html/index.html |
npm run dev |
Start Vite on port 5173 (HMR for src/index.css / src/index.ts) |
npm run preview:ui |
Generate mocks, then start Vite |
npm test |
Same as mock:generate (Maven/Docker FreeMarker tests) |
After you change FreeMarker templates or mock data (src/test/java/.../LoginDataModel.java), re-run mock:generate. CSS/JS-only changes only need dev (HMR).
LoginThemeTest/AccountThemeTestload Keycloak base messages and each FreeMarker template.- Templates are processed with mock models (
LoginDataModel,AccountDataModel). - Output is written under
html/login/andhtml/account/with asset URLs pointing at Vite (/src/index.css,/src/index.ts). npm run devserves those pages so humans or agents can screenshot and click through the UI.
Mock generation uses local mvn test when Maven is installed; otherwise it runs the same tests in maven:3.9-eclipse-temurin-21 via Docker.
| Login | Account | |
|---|---|---|
| Production | FreeMarker templates (theme/keywind/login) |
Keycloak Account Console v3 SPA (parent=keycloak.v3) + CSS/JS overlays |
| Local mocks | Full page set under html/login/ |
FreeMarker Account Console under html/account/ (personal info, signing in, TOTP, sessions, applications, linked accounts) |
The Account FreeMarker pages share the Keywind design system for local UI work. In a real Keycloak deployment the account theme still restyles the official SPA via keywind-account.css / keywind-account.js.
When you're ready to deploy your own theme, run the build command to generate a static production build.
pnpm install
pnpm buildTo deploy a theme as an archive, create a JAR archive with the theme resources.
pnpm build:jar