🚀 A starter/demo project for Keycloakify v9 🚀
Authenticated React SPA
This repo constitutes an easily reusable setup for a Keycloak theme project OR for a Vite SPA React App that generates a
Keycloak theme that goes along with it.
If you are only looking to create a Keycloak theme (and not a Keycloak theme and an App that share the same codebase) there are a lot of things that you can remove from this starter: Please read this section of the README.
This starter is based on Vite. There is also a Webpack based starter.
📣 Looking for a library for redirecting your user to Keycloak when they click on the 'Login' button?
Check out oidc-spa It's made by us and it's used in the src/App of this starter.
git clone https://github.com/keycloakify/keycloakify-starter
cd keycloakify-starter
yarn # install dependencies (it's like npm install)
yarn storybook # Start Storybook
# This is by far the best way to develop your theme
# This enable to quickly see your pages in isolation and in different states.
# You can create stories even for pages that you haven't explicitly overloaded. See src/keycloak-theme/login/pages/LoginResetPassword.stories.tsx
# See Keycloakify's storybook for if you need a starting point for your stories: https://github.com/keycloakify/keycloakify/tree/main/stories
yarn dev # See the Hello World app
# Uncomment line 97 of src/keycloak-theme/login/kcContext where it reads: `mockPageId: "login.ftl"`, reload https://localhost:3000
# You can now see the login.ftl page with the mock data. (Don't forget to comment it back when you're done)
# Install mvn (Maven) if not already done. On mac it's 'brew install maven', on Ubuntu/Debian it's 'sudo apt-get install maven'
yarn build-keycloak-theme # Actually build the theme (generates the .jar to be imported in Keycloak)
# Read the instruction printed on the console to see how to test
# your theme on a real Keycloak instance.
npx eject-keycloak-page # Prompt that let you select the pages you want to customize
# This CLI tools is not guaranty to work, you can always copy paste pages
# from the Keycloakify repo.
# After you ejected a page you need to edit the src/keycloak-theme/login(or admin)/KcApp.tsx file
# You need to add a case in the switch for the page you just imported in your project.
# Look how it's done for the Login page and replicate for your new page.
npx initialize-email-theme # For initializing your email theme
# Note that Keycloakify does not feature React integration for email yet.
npx download-builtin-keycloak-theme # For downloading the default theme (as a reference)
# Look for the files in dist_keycloak/src/main/resources/theme/{base,keycloak}
Keycloakify enables you to create different variant for a single theme.
This enable you to have a single jar that embed two or more theme variant.
You can enable this feature by providing multiple theme name in the Keycloakify build option.
See documentation
- To release don't create a tag manually, the CI do it for you. Just update the
package.json
's version field and push. - The
.jar
files that bundle the Keycloak theme will be attached as an asset with every GitHub release. Example. The permalink to download the latest version is:https://github.com/USER/PROJECT/releases/latest/download/keycloak-theme.jar
. For this demo repo it's here - This CI is configured to publish the app on GitHub Pages and on DockerHub (as a Ngnix based docker image). In practice you probably want one or the other but not both... or neither if you are just building a theme (and not a theme + an app).
If you want to enable the CI to publish on DockerHub on your behalf go to repositorySettings
tab, thenSecrets
you will need to add two new secrets:DOCKERHUB_TOKEN
, you Dockerhub authorization token.
DOCKERHUB_USERNAME
, Your Dockerhub username. We deploy the demo app at starter.keycloakify.dev using GitHub page on the branchgh-pages
(you have to enable it).
To configure your own domain name update the homepage field of thepackage.json
and potentially thebase
option in thevite.config.ts
. Regarding DNS configuration you can refer to this documentation. - The CI publishes the app docker image on DockerHub.
<org>/<repo>:main
for each commit onmain
,<org>/<repo>:<feature-branch-name>
for each pull-request onmain
and when releasing a new version:<org>/<repo>:latest
and<org>/<repo>:X.Y.Z
See on DockerHub
yarn
yarn storybook
Instructions for building and running the react app (src/App
) that is collocated with our Keycloak theme.
docker build -f Dockerfile -t keycloakify/keycloakify-starter:main .
docker run -it -dp 8083:80 keycloakify/keycloakify-starter:main
# You can access the app at http://localhost:8083
If you are only looking to create a Keycloak theme and not a Theme + a React app, you can run theses few commands to refactor the template and remove unnecessary files.
cd path/to/keycloakify-starter
rm -r src/App
mv src/keycloak-theme/* src/
rm -r src/keycloak-theme
cat << EOF > src/main.tsx
import { createRoot } from "react-dom/client";
import { StrictMode, lazy, Suspense } from "react";
import { kcContext as kcLoginThemeContext } from "./login/kcContext";
import { kcContext as kcAccountThemeContext } from "./account/kcContext";
const KcLoginThemeApp = lazy(() => import("./login/KcApp"));
const KcAccountThemeApp = lazy(() => import("./account/KcApp"));
createRoot(document.getElementById("root")!).render(
<StrictMode>
<Suspense>
{(()=>{
if( kcLoginThemeContext !== undefined ){
return <KcLoginThemeApp kcContext={kcLoginThemeContext} />;
}
if( kcAccountThemeContext !== undefined ){
return <KcAccountThemeApp kcContext={kcAccountThemeContext} />;
}
throw new Error(
"This app is a Keycloak theme" +
"It isn't meant to be deployed outside of Keycloak"
);
})()}
</Suspense>
</StrictMode>
);
EOF
rm .dockerignore Dockerfile nginx.conf
cat << EOF > .github/workflows/ci.yaml
name: ci
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: bahmutov/npm-install@v1
- run: yarn build
- run: npx keycloakify
check_if_version_upgraded:
name: Check if version upgrade
if: github.event_name == 'push'
runs-on: ubuntu-latest
needs: test
outputs:
from_version: \${{ steps.step1.outputs.from_version }}
to_version: \${{ steps.step1.outputs.to_version }}
is_upgraded_version: \${{ steps.step1.outputs.is_upgraded_version }}
steps:
- uses: garronej/ts-ci@v2.1.0
id: step1
with:
action_name: is_package_json_version_upgraded
branch: \${{ github.head_ref || github.ref }}
create_github_release:
runs-on: ubuntu-latest
needs: check_if_version_upgraded
# We create a release only if the version have been upgraded and we are on a default branch
if: needs.check_if_version_upgraded.outputs.is_upgraded_version == 'true' && github.event_name == 'push'
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: bahmutov/npm-install@v1
- run: yarn build
- run: npx keycloakify
- run: mv dist_keycloak/target/retrocompat-*.jar retrocompat-keycloak-theme.jar
- run: mv dist_keycloak/target/*.jar keycloak-theme.jar
- uses: softprops/action-gh-release@v1
with:
name: Release v\${{ needs.check_if_version_upgraded.outputs.to_version }}
tag_name: v\${{ needs.check_if_version_upgraded.outputs.to_version }}
target_commitish: \${{ github.head_ref || github.ref }}
generate_release_notes: true
draft: false
files: |
retrocompat-keycloak-theme.jar
keycloak-theme.jar
env:
GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
EOF
You can also remove oidc-spa
, powerhooks
, zod
and tsafe
from your dependencies.