From f1b98fe8d7ca9f8bd18a136ef953de06a9018740 Mon Sep 17 00:00:00 2001 From: Serreau Jovann Date: Fri, 10 Apr 2026 09:17:49 +0200 Subject: [PATCH] Add neo-brutalist Keycloak login theme 'ecosplay' - Custom theme under themes/ecosplay/login (extends keycloak parent) with template.ftl and login.ftl matching the e-cosplay.fr style: thick black borders, hard offset shadows, italic uppercase, indigo accent, hover translate effect, marquee header, watermark. - Tailwind via Play CDN for utility classes (no build step). - Mount the theme dir read-only into the Keycloak container. - Init container now also sets loginTheme=ecosplay on master realm alongside the SMTP config; service renamed keycloak-init. Co-Authored-By: Claude Opus 4.6 (1M context) --- docker-compose.yml | 14 +-- themes/ecosplay/login/login.ftl | 95 ++++++++++++++++++++ themes/ecosplay/login/template.ftl | 120 +++++++++++++++++++++++++ themes/ecosplay/login/theme.properties | 3 + 4 files changed, 227 insertions(+), 5 deletions(-) create mode 100644 themes/ecosplay/login/login.ftl create mode 100644 themes/ecosplay/login/template.ftl create mode 100644 themes/ecosplay/login/theme.properties diff --git a/docker-compose.yml b/docker-compose.yml index 8744e35..51d720c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -35,15 +35,17 @@ services: KEYCLOAK_ADMIN_PASSWORD: admin ports: - "9450:8080" + volumes: + - ./themes/ecosplay:/opt/keycloak/themes/ecosplay:ro depends_on: postgres: condition: service_healthy networks: - keycloak-net - keycloak-smtp-init: + keycloak-init: image: quay.io/keycloak/keycloak:26.0 - container_name: ecosplay-auth-smtp-init + container_name: ecosplay-auth-init depends_on: keycloak: condition: service_started @@ -57,6 +59,7 @@ services: SMTP_FROM_DISPLAY_NAME: E-Cosplay SMTP_USER: AKIAWTT2T22CWBRBBDYN SMTP_PASSWORD: BBdgb6KxRQ8mNcpWFJsZCJxbSGNdgLhKFiITMErfBlQP + LOGIN_THEME: ecosplay entrypoint: ["/bin/bash", "-c"] command: - | @@ -69,7 +72,7 @@ services: echo "Waiting for Keycloak to be ready..." sleep 5 done - echo "Keycloak ready, configuring SMTP on master realm..." + echo "Keycloak ready, configuring master realm (SMTP + theme)..." /opt/keycloak/bin/kcadm.sh update realms/master \ -s "smtpServer.host=$$SMTP_HOST" \ -s "smtpServer.port=$$SMTP_PORT" \ @@ -79,8 +82,9 @@ services: -s "smtpServer.starttls=true" \ -s "smtpServer.ssl=false" \ -s "smtpServer.user=$$SMTP_USER" \ - -s "smtpServer.password=$$SMTP_PASSWORD" - echo "SMTP configuration applied to master realm." + -s "smtpServer.password=$$SMTP_PASSWORD" \ + -s "loginTheme=$$LOGIN_THEME" + echo "Master realm configured." networks: - keycloak-net restart: "no" diff --git a/themes/ecosplay/login/login.ftl b/themes/ecosplay/login/login.ftl new file mode 100644 index 0000000..3060d88 --- /dev/null +++ b/themes/ecosplay/login/login.ftl @@ -0,0 +1,95 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout displayMessage=!messagesPerField.existsError('username','password') displayInfo=realm.password && realm.registrationAllowed && !registrationDisabled??; section> + <#if section = "header"> + ${msg("loginAccountTitle")} + <#elseif section = "form"> + <#if realm.password> +
+ + <#if !usernameHidden??> +
+ + + <#if messagesPerField.existsError('username','password')> + + ${kcSanitize(messagesPerField.getFirstError('username','password'))?no_esc} + + +
+ + +
+ +
+ +
+ <#if usernameHidden?? && messagesPerField.existsError('username','password')> + + ${kcSanitize(messagesPerField.getFirstError('username','password'))?no_esc} + + +
+ +
+ <#if realm.rememberMe && !usernameHidden??> + + + <#if realm.resetPasswordAllowed> + + ${msg("doForgotPassword")} + + +
+ + value="${auth.selectedCredential}"/> + + +
+ + + <#elseif section = "info"> + <#if realm.password && realm.registrationAllowed && !registrationDisabled??> +

+ ${msg("noAccount")} + + ${msg("doRegister")} + +

+ + + <#elseif section = "socialProviders"> + <#if realm.password && social?? && social.providers?? && social.providers?has_content> +
+

// ${msg("identity-provider-login-label")}

+
+ <#list social.providers as p> + + <#if p.iconClasses?has_content> + ${p.displayName!} + + +
+
+ + + diff --git a/themes/ecosplay/login/template.ftl b/themes/ecosplay/login/template.ftl new file mode 100644 index 0000000..b47ebd6 --- /dev/null +++ b/themes/ecosplay/login/template.ftl @@ -0,0 +1,120 @@ +<#macro registrationLayout bodyClass="" displayInfo=false displayMessage=true displayRequiredFields=false showAnotherWayIfPresent=true> + + + + + + + ${msg("loginTitle",(realm.displayName!''))} + + + + + + + + + +
+
+ <#list 1..6 as i> + + Authentification // E-Cosplay // Communauté Inclusive // Hauts-de-France + + +
+
+ +
+
+ + +
+ + +
+

// ${realm.displayName!"E-Cosplay"}

+

+ <#nested "header"> +

+
+ + + <#if displayMessage && message?has_content && (message.type != 'warning' || !isAppInitiatedAction??)> +
+ ${kcSanitize(message.summary)?no_esc} +
+ + + + <#if displayRequiredFields> +

+ * ${msg("requiredFields")} +

+ + + +
+ <#nested "form"> +
+ + + <#nested "socialProviders"> + + + <#if displayInfo> +
+ <#nested "info"> +
+ +
+ + + <#if realm.internationalizationEnabled && locale.supported?size gt 1> +
+ // Langue + <#list locale.supported as l> + + ${l.label} + + +
+ +
+
+ + +
+

+ © E-Cosplay // Créer la réalité +

+
+ + + + diff --git a/themes/ecosplay/login/theme.properties b/themes/ecosplay/login/theme.properties new file mode 100644 index 0000000..b7251ec --- /dev/null +++ b/themes/ecosplay/login/theme.properties @@ -0,0 +1,3 @@ +parent=keycloak +import=common/keycloak +locales=en,fr