State of your codebase after bringin in the Keycloakify boilerplate code.
Note thate the keycloak-theme (or keycloak_theme) directory can be located anywhere under your src directory.
Now you want to modify your entry point so that:
If the kcContext global is defined, render your Keycloakify theme
Else, reder your App as usual.
src/main.tsx
/* eslint-disable react-refresh/only-export-components */
import { createRoot } from "react-dom/client";
import {
StrictMode,
lazy,
Suspense
} from "react";
import { KcPage, type KcContext } from "./keycloak-theme/kc.gen";
const App = lazy(() => import("./App"));
// The following block can be uncommented to test a specific page with `yarn dev`
// Don't forget to comment back or your bundle size will increase
/*
import { getKcContextMock } from "./keycloak-theme/login/KcPageStory";
if (import.meta.env.DEV) {
window.kcContext = getKcContextMock({
pageId: "register.ftl",
overrides: {}
});
}
*/
createRoot(document.getElementById("root")!).render(
<StrictMode>
{window.kcContext ? (
<KcPage kcContext={window.kcContext} />
) : (
<Suspense>
<App />
</Suspense>
)}
</StrictMode>
);
declare global {
interface Window {
kcContext?: KcContext;
}
}
Question:
Why do my main application and Keycloak theme share the same entry point?
Answer:
To simplify the build process. If you don't want it to negatively impact the performance of your application, it's essential to understand the following points:
Different Contexts: The application (App) and Keycloak page (KcPage) are mounted in very different contexts. Avoid sharing providers between the two at the main.tsx file level. The true entry point of your application is the App component, while the entry point for your Keycloak theme is the KcPage component. Be careful about what code is shared between them.
Responsibility of main.tsx: The main.tsx file should only determine the context (either the application or Keycloak) and mount the appropriate component (App or KcPage). It should not contain any substantial logic or dependencies.
Performance Considerations: Keep main.tsx as lightweight as possible to avoid increasing the initial load time of both your main application and login pages. For example, do not load any state management libraries like redux-toolkit at this level.
You also need to use Keycloakify's Vite plugin. Here we don't provide any build options but you probably at least want to define keycloakVersionTargets.
vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { keycloakify } from "keycloakify/vite-plugin";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
react(),
keycloakify({
accountThemeImplementation: "none"
})
],
})
Leave accountThemeImplementation set to "none" for now.
To initialize the account theme refer to this guide.
Finally you want to add to your package.json a script for building the theme and another one to start storybook.
You can run npm run build-keycloak-theme, the JAR distribution of your Keycloak theme will be generated in dist_keycloak.
You're now able to use all the Keycloakify commands (npx keycloakify --help) from the root of your project.
If you're currently using keycloak-js or react-oidc-context to manage user authentication in your app you might want to checkout oidc-spa, the alternative from the Keycloakify team.