{"id":15133,"library":"keycloakify","title":"Keycloakify","description":"Keycloakify is a framework designed to streamline the creation of custom Keycloak user interfaces using React. It acts as a build tool that compiles a React application into a Keycloak-compatible theme, abstracting away the complexities of FreeMarker (FTL) templating. The library is actively maintained, with the current stable version being 11.15.3, and exhibits a fairly rapid release cadence, often pushing several minor or patch updates within a short period. Keycloakify's primary differentiator is its ability to enable modern web development practices (like React) for Keycloak theming, supporting a broad range of Keycloak versions from 11 up to 26 and beyond. This allows developers to leverage familiar tooling and component-based architectures for login, registration, account management, and other Keycloak-provided pages, rather than directly interacting with FreeMarker templates.","status":"active","version":"11.15.3","language":"javascript","source_language":"en","source_url":"git://github.com/keycloakify/keycloakify","tags":["javascript","keycloak","react","theme","FreeMarker","ftl","login","register","account"],"install":[{"cmd":"npm install keycloakify","lang":"bash","label":"npm"},{"cmd":"yarn add keycloakify","lang":"bash","label":"yarn"},{"cmd":"pnpm add keycloakify","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"This is primarily a type definition for the Keycloak context object. It should be imported as a type.","wrong":"import { KcContext } from 'keycloakify';","symbol":"KcContext","correct":"import type { KcContext } from 'keycloakify';"},{"note":"This function is used to create a custom React hook (`useKcContext`) tailored for your theme's `KcContext` definition. You call `createUseKcContext` once to get your typed hook.","wrong":"import { useKcContext } from 'keycloakify';","symbol":"createUseKcContext","correct":"import { createUseKcContext } from 'keycloakify';"},{"note":"This hook provides access to Keycloak's internationalization (i18n) messages within your React components, allowing for locale-sensitive text rendering.","wrong":"import { useKcMessage } from 'keycloakify';","symbol":"useKcMessage","correct":"import { useKcMessage } from 'keycloakify/lib/i18n';"}],"quickstart":{"code":"import { lazy, Suspense } from 'react';\nimport type { PageProps } from 'keycloakify/lib/KcProps';\nimport { useKcMessage } from 'keycloakify/lib/i18n';\nimport { createUseKcContext, get } from 'keycloakify';\nimport type { KcContext } from 'keycloakify';\n\n// 1. Define your custom KcContext extension (optional)\n// This example extends the context for a custom 'my-custom-page.ftl'\nexport type KcContextExtension = {\n  customData: string;\n};\n\nexport type KcContextExtended = KcContext & KcContextExtension;\n\n// 2. Create your custom useKcContext hook\nexport const { useKcContext } = createUseKcContext<KcContextExtension>();\n\n// 3. Main application component that renders Keycloak pages\nexport default function KcApp(props: PageProps<KcContextExtended>) {\n  const { kcContext } = props;\n  const { msg } = useKcMessage();\n\n  // Dynamically set page title\n  if (kcContext) {\n    document.title = msg(\"doLogIn\"); // Example: set based on a common message key\n  }\n\n  // Lazy load page components based on Keycloak's pageId\n  const PageComponent = kcContext ? lazy(() => {\n    switch (kcContext.pageId) {\n      case 'login.ftl': return import('./pages/KcLogin');\n      case 'register.ftl': return import('./pages/KcRegister');\n      // Add more cases for other Keycloak pages you want to customize\n      // For custom pages (e.g., 'my-custom-page.ftl'), ensure they are handled\n      case 'my-custom-page.ftl': return import('./pages/MyCustomPage');\n      default: return import('./pages/KcDefaultPage'); // Fallback for unhandled pages\n    }\n  }) : null;\n\n  return (\n    <Suspense fallback={<div>Loading Keycloak page...</div>}>\n      {kcContext && PageComponent ? <PageComponent {...{ kcContext }} /> : <div>No Keycloak context available.</div>}\n    </Suspense>\n  );\n}\n\n// src/keycloak-theme/pages/KcLogin.tsx (Simplified example)\n// import React from 'react';\n// import type { PageProps } from 'keycloakify/lib/KcProps';\n// import type { KcContextExtended } from '../KcApp'; // Use your extended context\n// import { useKcMessage } from 'keycloakify/lib/i18n';\n\n// export default function KcLogin(props: PageProps<KcContextExtended>) {\n//   const { kcContext } = props;\n//   const { msg } = useKcMessage();\n\n//   return (\n//     <div>\n//       <h1>{msg('loginTitle')}</h1>\n//       <p>Welcome to the custom login page for {kcContext.realm.displayName}!</p>\n//       <form action={kcContext.url.loginAction} method='post'>\n//         <input type='text' id='username' name='username' placeholder={msg('username')} />\n//         <input type='password' id='password' name='password' placeholder={msg('password')} />\n//         <button type='submit'>{msg('doLogIn')}</button>\n//       </form>\n//     </div>\n//   );\n// }\n\n// package.json (add this script)\n/*\n{\n  \"name\": \"my-keycloak-theme\",\n  \"version\": \"1.0.0\",\n  \"scripts\": {\n    \"build-keycloak-theme\": \"keycloakify build\"\n  },\n  \"dependencies\": {\n    \"react\": \"^18.2.0\",\n    \"react-dom\": \"^18.2.0\",\n    \"keycloakify\": \"^11.0.0\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"^5.0.0\",\n    \"@types/react\": \"^18.2.0\",\n    \"@types/react-dom\": \"^18.2.0\"\n  }\n}\n*/\n","lang":"typescript","description":"This quickstart demonstrates the core structure of a Keycloakify theme: setting up an `KcApp` component to route Keycloak pages, defining a `KcContext` for type safety, and the build command to generate the `.jar` theme file. It includes a simplified `KcLogin` page as an example."},"warnings":[{"fix":"Upgrade Keycloakify to the latest version within your major release (v10 or v11 currently), and then rebuild your theme. Refer to the official documentation for specific upgrade guides.","message":"Themes built with Keycloakify versions prior to Keycloak 26 are incompatible with Keycloak 26. This is due to significant internal changes in Keycloak, including marshalling format, User Profile SPI, and FreeMarker template updates.","severity":"breaking","affected_versions":"<11.14.0"},{"fix":"Use the `npx keycloakify eject-page` command for common pages to get a customizable boilerplate. For entirely new pages introduced by Keycloak extensions, you will need to create the React component and declare its existence within your `KcContext` types.","message":"Keycloakify only supports out-of-the-box the most common user-facing Keycloak pages (login, registration, account). If a page you need to customize is not provided as a React component by Keycloakify, you might need to implement it yourself or 'eject' it.","severity":"gotcha","affected_versions":">=6.0.0"},{"fix":"If you need additional properties in the `KcContext` that are not officially typed, augment the `KcContext` type definition properly. For complex scenarios, consider taking ownership of the FreeMarker template that generates the `KcContext` using tools like `patch-package`.","message":"Directly modifying the `KcContext` type definitions or relying on implicit runtime properties can lead to issues, especially when Keycloak or Keycloakify updates.","severity":"gotcha","affected_versions":">=6.0.0"},{"fix":"Ensure you are using a recent version of Keycloakify (v8+ addressed many of these). Regularly check for updates and report persistent issues to the maintainers.","message":"Older versions of Keycloakify could produce numerous FTL (FreeMarker Template Language) errors in Keycloak logs, especially with Keycloak 15+. While often ignorable, they could indicate performance issues.","severity":"gotcha","affected_versions":"<8.0.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"After `keycloakify build`, copy the generated `.jar` file from `dist_keycloak/` to the Keycloak server's `providers` directory (e.g., `/opt/keycloak/providers/` in Docker). Ensure the `themeName` in your `package.json`'s `keycloakify` configuration matches what you select in the Keycloak admin console.","cause":"The generated JAR theme file was not correctly deployed to Keycloak or the theme name in Keycloak's admin console does not match the one configured in `package.json`.","error":"Error: Theme 'your-theme-name' not found"},{"fix":"Ensure `KcApp` is correctly conditionalized to only render your Keycloak theme components when `window.kcContext` is present. During Storybook development, `kcContext` is usually mocked.","cause":"This error typically occurs during development or when trying to access `kcContext` outside the Keycloak theme's runtime environment (e.g., in your main application bundle or if the Keycloakify theme is not correctly initialized).","error":"ReferenceError: kcContext is not defined"},{"fix":"Verify that your theme entry file (e.g., `src/keycloak-theme/KcApp.tsx`) exists and is correctly exporting your main theme component. Check your `package.json` for the `keycloakify` configuration and ensure `themeName` and other paths are correct.","cause":"Keycloakify could not find the expected entry point for your theme, typically `src/keycloak-theme/KcApp.tsx` or similar, or the `keycloakify` configuration in `package.json` is incorrect.","error":"Build failed: No theme entry point found."}],"ecosystem":"npm"}