Keycloakify: build Keycloak login themes with React instead of FreeMarker
🔏 Keycloak theming for the modern web
At a glance
- What is it?
- Keycloakify is an MIT-licensed build tool that compiles a React, Angular or plain TypeScript app into a Keycloak theme. It is aimed at teams that already own a frontend codebase and do not want to hand-write FreeMarker templates.
- Who is it for?
- Adopt Keycloakify if your team already writes React or Angular and your login pages must match an existing design system; skip it if you only need a logo swap on the stock theme, since that is a CSS override you can ship without a build step.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 9 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 8, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Keycloakify replaces, and for whom
Keycloak ships its login, registration, password reset and account pages as FreeMarker templates, with .ftl files and a theme.properties file that decides which stylesheets and scripts load. Changing anything beyond colours means editing those templates, and the FreeMarker context is not the same as the data your application already has. Keycloakify targets that gap. Its package description calls it a "Framework to create custom Keycloak UIs", and the README describes it as a build tool that "generates a Keycloak theme". The audience is a team with an existing single-page application: the login page becomes another page in that codebase, written in TypeScript, with the same components, the same i18n setup and the same lint rules. The repository topics list freemarker and ftl alongside keycloak-theme, which is a fair summary of the split. The project does not remove FreeMarker. It generates the templates and the theme bundle for you, so the artefacts Keycloak loads are still .ftl files, but you stop editing them by hand.
How the build turns a React app into a Keycloak theme
The mechanism is a compiler plus a Vite plugin. The package exposes a bin entry, keycloakify, mapped to dist/bin/main.js, and a separate Vite plugin at dist/vite-plugin/index.js. Both are listed in the published files array, so they ship with the npm package. In a typical setup the Vite plugin participates in the dev server and in the production build, and the CLI produces the theme archive that you drop into Keycloak. The theme itself is a directory with the .ftl templates, a theme.properties, and the compiled JavaScript and CSS assets. Keycloak then serves those pages from its own origin, which is why the app inside a theme cannot assume it is running on your application's domain. The README states compatibility with Keycloak from version 11 to 26 and beyond, and points at a compiler option called keycloakVersionTargets that controls which target version ranges the build emits for. That option is the seam between your theme and the Keycloak release you deploy against, and it is the first thing to look at when a theme that worked on one server misbehaves on another.
Installing Keycloakify and getting a first theme out
The README points at a starter project, codegouvfr/keycloakify-starter, and at the documentation site, docs.keycloakify.dev, for setup steps. This article has not run any of it, so treat the commands below as the shape of the workflow rather than a verified transcript. The package is installed from npm under the name keycloakify, and the CLI binary has the same name.
yarn add keycloakifyThe package.json in the repository defines the bin entry as keycloakify pointing to dist/bin/main.js, so after installation a keycloakify command is available in your project's node_modules/.bin. The repository's own scripts show how the maintainers drive the toolchain, which is a useful reference for what a working setup looks like:
yarn build
yarn storybookThe first builds the package, the second starts Storybook. Storybook matters more than it first appears. Because a Keycloak theme runs inside Keycloak's origin and is loaded through its FreeMarker templates, iterating on a login page against a live Keycloak instance is slow. The repository keeps a .storybook/ directory and a stories/ directory at the top level, and the README links a hosted Storybook at storybook.keycloakify.dev, so the intended loop is to develop the pages as ordinary components and only assemble the theme when you are ready to test it in Keycloak. Once the theme is built, you install it into Keycloak the same way as any other theme, then select it for the realm.
The Keycloak 26 compatibility break
The README carries a release note that is easy to skim past and expensive to ignore: themes built with Keycloakify versions prior to Keycloak 26 are incompatible with Keycloak 26. The fix is to upgrade to the latest Keycloakify version for your major release line, v10 or v11, and rebuild. The note says no breaking changes were introduced and that the target version ranges were updated. That is a small sentence with a large operational consequence. A theme is a build artefact that lives in your repository, and the Keycloak server it runs against is often upgraded on a different schedule by a different team. If the server moves to 26 before your theme is rebuilt, the login page breaks, and the failure happens on the one page every user must pass through. The keycloakVersionTargets compiler option is the documented lever here. The README points to a guide on the documentation site rather than explaining the ranges inline, so the practical step is to read that page and pin the target to the versions you actually run. Two major lines being supported at once, v10 and v11, also means upgrade advice depends on which line you are on.
Where Keycloakify is the wrong tool
If you want a different logo, a background image and a brand colour on the stock Keycloak login page, Keycloakify is overkill. That is a CSS override on an existing theme, and it needs no Node build, no theme archive pipeline and no compatibility tracking against Keycloak releases. The cost of Keycloakify is not the install. It is that you now own a frontend build that must be rebuilt and redeployed whenever Keycloak's target version range moves. There is a second boundary worth naming. A Keycloak theme runs in Keycloak's origin, and the FreeMarker templates are what Keycloak renders, so anything that depends on your application's runtime, its session handling or its client-side routing does not automatically carry over. The README does not document rollback of a deployed theme, and it does not describe what happens to an in-flight login when you replace the theme files under a running server. If your login page needs deep integration with application state, that integration has to be rebuilt inside the theme's constraints, not reused. Finally, the project is TypeScript-centric. The related searches include Keycloakify angular, and the package keywords list react, but the README and package metadata do not spell out a support matrix across frontend frameworks, so check the documentation before assuming your framework is a first-class path.
Keycloakify compared with hand-written FreeMarker themes
The real alternative is not another npm package. It is writing the .ftl templates and theme.properties yourself, which is what Keycloak's own theming documentation describes. The difference is where the work sits. A hand-written theme is a set of template files and static assets that Keycloak reads directly; there is no compiler between you and the server, so a change is a file edit and a redeploy, and there is nothing to upgrade when Keycloak changes except the templates themselves. Keycloakify inverts that: you get components, type checking, hot reload through the Vite plugin and a Storybook to preview pages without a running Keycloak, and in exchange you accept a build step and a version-target contract with Keycloak. For a team already fluent in React, the second trade is usually the better one, because the login page stops being an island maintained by whoever last touched FreeMarker. For a team without a frontend build, it adds a toolchain to maintain for a page that changes once a year. The repository also keeps a test/ directory and a vitest.config.ts, and its test script runs a type check before the test suite, which tells you the project expects typed theme code rather than loose templates.
Licence, maintenance and the cost of keeping up
Keycloakify is MIT licensed, and the LICENSE file sits at the repository root. MIT is permissive: you can use it commercially, modify it and redistribute it, provided the copyright notice and permission notice are kept. That is a statement about the licence text, not legal advice for your situation. The repository is not archived, and the last push was on 2026-09-03, with releases at v11.16.0 on 2026-08-30 and v11.16.1-rc.1 on 2026-09-02. The maintenance cost that matters is not the library's release cadence, it is the coupling described above. Every Keycloak upgrade is a potential theme rebuild, and the README's own note about Keycloak 26 shows what that looks like in practice: a server upgrade that requires a library upgrade and a rebuild before logins work again. Budget for that as a recurring task tied to your Keycloak upgrade cycle, not as a one-time setup. A renovate.json at the repository root suggests the maintainers automate dependency updates on their side, which does not reduce your side of the work.
Editorial conclusion
Adopt Keycloakify if your team already writes React or Angular and your login pages must match an existing design system; skip it if you only need a logo swap on the stock theme, since that is a CSS override you can ship without a build step. Before committing, check which Keycloak version you run against the keycloakVersionTargets compiler option, and confirm your theme rebuilds cleanly after bumping Keycloakify, because themes built with versions prior to Keycloak 26 are documented as incompatible with Keycloak 26.
Frequently asked questions
What is Keycloakify?
It is a build tool that generates a Keycloak theme from a frontend application, described in its package metadata as a framework to create custom Keycloak UIs. It ships a CLI at dist/bin/main.js and a Vite plugin, and the README states it is compatible with Keycloak from version 11 to 26 and beyond.
What are the alternatives to Keycloakify?
The practical alternative is writing the FreeMarker .ftl templates and theme.properties yourself, which Keycloak reads directly with no compiler in between. Keycloakify keeps FreeMarker as the output format, so the difference is the authoring experience and the added build step, not the artefacts Keycloak loads.
Which Keycloak versions does Keycloakify work with?
The README states compatibility with Keycloak from version 11 to 26 and beyond, and points to a compiler option named keycloakVersionTargets for controlling the target version ranges. Note that themes built with Keycloakify versions prior to Keycloak 26 are documented as incompatible with Keycloak 26.
How do I install Keycloakify and build a theme?
It is published on npm as keycloakify and installs with your package manager; the package defines a keycloakify bin entry. The README points to the codegouvfr/keycloakify-starter project and to docs.keycloakify.dev for the setup steps and the build command.
Can I preview a Keycloakify theme without running Keycloak?
Yes. The repository keeps a .storybook directory and a stories directory, and the README links a hosted Storybook at storybook.keycloakify.dev. Developing the pages as components first avoids iterating against a live Keycloak instance, which is slower because the theme runs inside Keycloak's own origin.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/keycloakify-keycloakify)