Conversation
There was a problem hiding this comment.
Pull request overview
Adds a self-contained Keycloak theme project (built with Keycloakify + React/Vite) to the frontend repo so Keycloak can load a custom “jucaneat” login experience.
Changes:
- Introduces a new
keycloak-theme/subproject with its own build tooling and dependencies to produce a Keycloak theme JAR. - Implements custom UI for multiple Keycloak login-related pages (login/register/reset/update password/verify email/error).
- Minor formatting-only change in the existing
app/routes/not-found.tsx.
Reviewed changes
Copilot reviewed 9 out of 12 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| keycloak-theme/vite.config.ts | Vite config including Keycloakify plugin + theme name. |
| keycloak-theme/tsconfig.json | TypeScript config for the theme subproject. |
| keycloak-theme/src/vite-env.d.ts | Vite client type references. |
| keycloak-theme/src/main.tsx | React entrypoint wiring kcContext into the theme pages (includes mock context). |
| keycloak-theme/src/login/styles.css | Theme styling for the login-related pages. |
| keycloak-theme/src/login/KcPage.tsx | Page router + implementations for Keycloak login flows. |
| keycloak-theme/src/kc.gen.tsx | Keycloakify auto-generated theme wiring/types. |
| keycloak-theme/package.json | Theme subproject scripts/dependencies (build + keycloakify build). |
| keycloak-theme/package-lock.json | Lockfile for the theme subproject. |
| keycloak-theme/index.html | Vite HTML entry. |
| keycloak-theme/.gitignore | Ignores node_modules and build outputs for theme. |
| app/routes/not-found.tsx | Whitespace/indentation fix at EOF. |
Files not reviewed (1)
- keycloak-theme/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
| } as any; | ||
|
|
||
| const kcContext = window.kcContext ?? mockKcContext; |
There was a problem hiding this comment.
kcContext falls back to mockKcContext unconditionally. In a real Keycloak render, missing window.kcContext usually indicates misconfiguration; using mock data can mask the issue (and results in forms posting to #). Consider only using the mock in dev mode (e.g., import.meta.env.DEV) and otherwise throwing/rendering a clear error when window.kcContext is undefined.
| /** | ||
| * NOTE: Do not import this type except maybe in your entrypoint. | ||
| * If you need to import the KcContext import it either from src/login/KcContext.ts or src/account/KcContext.ts. | ||
| * Depending on the theme type you are working on. | ||
| */ | ||
| export type KcContext = | ||
| | import("./login/KcContext").KcContext | ||
| ; |
There was a problem hiding this comment.
This generated type references ./login/KcContext, but there is no keycloak-theme/src/login/KcContext.ts(x) in the repo. Even if it’s type-only, this makes the guidance in the comment block inaccurate and can confuse consumers of the generated API. Either commit the missing src/login/KcContext file (if keycloakify expects it) or regenerate/configure kc.gen.tsx so it references the actual keycloakify/login/KcContext type you’re using elsewhere.
| <label>Email</label> | ||
| <input | ||
| type="text" | ||
| name="username" | ||
| autoComplete="username" | ||
| required | ||
| /> |
There was a problem hiding this comment.
The label isn’t associated with its input (no htmlFor + matching input id, and the input isn’t nested inside the label). This reduces screen-reader usability and click-to-focus behavior. Add id to the input and htmlFor to the label (same pattern applies to other fields in this file).
| <a className="btn primary" style={{ display: "block", textAlign: "center" }} href={url.loginAction}> | ||
| Resend Email | ||
| </a> |
There was a problem hiding this comment.
url.loginAction is generally intended to be used as a form POST action. Using it as an <a href> will issue a GET and may not trigger the resend action. Consider switching this to a <form method="post" action={url.loginAction}> with a submit button so it matches Keycloak’s expected flow.
| function RegisterPage({ kcContext }: { kcContext: KcContext & { pageId: "register.ftl" } }) { | ||
| const { url, message, profile, messagesPerField } = kcContext as any; | ||
| const attrs = profile?.attributesByName ?? {}; |
There was a problem hiding this comment.
kcContext as any drops type safety for the register page and makes it easier to accidentally access non-existent properties. Prefer using the page-specific Keycloakify context type for register.ftl (or a type guard) so url.registrationAction, profile, and messagesPerField are typed without any.
| // NOTE: This is exported here only because in Webpack environnement it works differently | ||
| export const BASE_URL = import.meta.env.BASE_URL |
There was a problem hiding this comment.
Typo: "environnement" should be "environment".
| {message && ( | ||
| <div className={message.type === "error" ? "error" : "error"}> | ||
| {message.summary} | ||
| </div> | ||
| )} |
There was a problem hiding this comment.
The conditional for the message class is currently redundant (message.type === "error" ? "error" : "error") and will style non-error messages as errors. Use distinct classes (or at least different styling) based on message.type, or simplify if only errors are expected on this page.
|
From my understanding, these changes are already in prod. When I created an account and tried to remind password, this fails with HTTP 500: Is this due sth on backend not merged yet or a real issue? This happens still after your Keycloak backend PR merge. Please investigate and lmk. @cssma Locally I do not see the error message but I am not getting any emails. |
|
Btw, it says "invalid username or password" but requests email on login @cssma this seems inconsistent |
|
Light theme is looking cool, and responsive, gj on that |
|
The correct directory to put .jar is |
Locally it works after filling in the SMTP app password in Keycloak admin. The issue on prod is just the missing password. |
Fixed:) removed the Username field from registration (email is used as login), and changed the error message to 'Invalid email or password.' to be consistent with the UI. |
I'll open a separate PR on the backend repo with the compose.yaml change. |
kingazm
left a comment
There was a problem hiding this comment.
Thank you for fixing error messages




📄 Pull Request Description
🧩 What was changed?
Added a custom Keycloak theme to the frontend repository under keycloak-theme/.
💡 Why was it changed?
JUCanEat/documentation#17
⚙️ How was it implemented?
The theme was built using Keycloakify — a library that allows writing Keycloak pages in React. It compiles to a JAR file that Keycloak loads as a provider.
To build the theme locally:
(once the backend PR with the updated volume mount is merged)
✅ Checklist