Local development stack for Jahia (Prism), fronted by Traefik with TLS, backed by Postgres, with Mailpit for catching outbound email.
- Template Set: GladTek Prism (
gladtek-prism) - Modern Jahia 8+ JavaScript Template Set & Component Library built with React 19 (Server-Side Rendering + Client-Side Islands), TypeScript, and Vite. - Framework: Jahia JavaScript Modules Engine (
@jahia/javascript-modules-library) - Rendering Model: Server-side React components (
.server.tsx) with client-side interactive islands (.client.tsx) - Styling & Themes: Dynamic site-level themes (
corporate,editorial,ecommerce,portfolio,gov) driven byglobal.cssdesign tokens and mixins - Form Builder: Integration with multi-step wizard forms (
fmdb:form,fmdb:step,fmdb:fieldList) and custom components (gtf:*)
- Base Layout:
Layout.tsxhandling dynamic<head>, SEO meta tags, Google Fonts, theme CSS variables, and Jahia edit-mode scripts. - Page Layouts:
PageLayout.tsxwith configurable JCR areas (header,main,footer,sidebar). - Global Design System:
global.cssdefining HSL color tokens, typography rules, dark mode, and responsive layout primitives.
- Navigation & Layout: MegaMenu (Panels, Link Groups, Cards, NavLinks), Navbar, Footer, Breadcrumbs, Sticky Anchor Nav, Section, Row, ContentBlock, Tabs.
- Hero & CTAs: HeroBanner, CTABanner, CallToAction, BannerStrip, BeforeAfter comparison sliders.
- Grids, Cards & Data: BentoGrid, FeatureGrid, ServiceGrid, IconList, ComparisonTable, CsvTable.
- Media & Visuals: Video, AudioPlayer, ImageGallery, LightboxGallery, LogoShowcase (animated infinite marquee loop).
- Social Proof & Metrics: Stats counters, Testimonials grid, Team grid, Timeline, ProcessSteps, Pricing tables.
- Dynamic JCR Query Views: Blog (BlogPost, BlogQuery, RelatedBlogPosts), Case Studies (CaseStudy, CaseStudyQuery), Events (Event, EventQuery), Resources (Resource, ResourceQuery).
- Interactive Widgets: Accordion, HorizontalAccordion, Modal, CountdownTimer, MapEmbed, ShareBar, ReadingProgress, JsonLd, EditButton.
| Component | Node Type | Submitted Value | Notes |
|---|---|---|---|
| Rating (stars) | gtf:inputRating |
"1" - "N" |
maxStars property controls range |
| Phone | gtf:inputPhone |
+33612345678 |
Dial-code selector + local number |
| Consent checkbox | gtf:inputConsent |
Boolean | Rich-text label via consentText |
| Budget slider | gtf:inputBudgetSlider |
Number string | minValue, maxValue, stepValue |
| Image choice | gtf:inputImageChoice |
String | Child nodes of type gtf:imageChoiceOption |
| Matrix | gtf:inputMatrix |
One value per row | Grid of radio buttons; rows × columns properties |
| Ranking | gtf:inputRanking |
Ordered list | Drag-to-rank; child nodes of type gtf:rankingOption |
| Component | Node Type | Purpose |
|---|---|---|
| Form section | gtf:formSection |
Visual grouping block - no submission |
| Form recap | gtf:formRecap |
Summary step showing all entered values |
| CSS injector | gtf:formStyle |
Injects a JCR CSS file globally via <AddResources> |
The Prism template site includes 13 pre-configured Formidable forms embedded across its pages for landing flows, user interaction, and component demonstrations:
- Page Path:
/sites/prism/home/events/vaadin-developer-day - Fields: Full Name (
fmdb:inputText), Registration Type (fmdb:select), Sponsorship Budget (gtf:inputBudgetSlider), Form Style (gtf:formStyle) - Actions: Saves to JCR (
fmdb:save2jcrAction) - Purpose: Collects corporate sponsorship inquiries and estimated budget tiers for Vaadin Developer Day.
- Page Path:
/sites/prism/home/events/astro-cms-workshop - Fields: Full Name (
fmdb:inputText), Attendance Type (fmdb:select), Guest Count (fmdb:select), Notes (fmdb:textarea), Form Style (gtf:formStyle) - Actions: Saves to JCR (
fmdb:save2jcrAction) - Purpose: Manages workshop RSVPs, attendance preferences, and guest count tracking for technical workshops.
- Page Path:
/sites/prism/home/resources/ai-cms-whitepaper - Fields: Gated download step (
step-1), Form Style (gtf:formStyle) - Actions: Saves to JCR (
fmdb:save2jcrAction) & triggers Automated Email (gtf:emailDownloadNotificationAction) - Purpose: Captures lead information and sends an automated whitepaper access link via email.
- Page Path:
/sites/prism/home/contact - Fields: Multi-step branching setup (
details,support,project-request,general-inquiry,billing,recap), Form Style (gtf:formStyle) - Actions: Saves to JCR (
fmdb:save2jcrAction) - Purpose: Comprehensive contact center routing visitor requests dynamically by department with a dynamic recap step.
- Page Path:
/sites/prism/home/forms-catalog/newsletter-subscription - Fields: Email (
fmdb:inputEmail), Topics (fmdb:checkbox), Consent (gtf:inputConsent), Form Style (gtf:formStyle) - Actions: Saves to JCR (
fmdb:save2jcrAction) - Purpose: Single-step catalog demonstration for collecting email subscriptions and GDPR marketing consents.
- Page Path:
/sites/prism/home/forms-catalog/contact-form - Fields: Full Name (
fmdb:inputText), Email (fmdb:inputEmail), Subject (fmdb:select), Message (fmdb:textarea), File Attachment (fmdb:inputFile), Form Style (gtf:formStyle) - Actions: Saves to JCR (
fmdb:save2jcrAction) - Purpose: Demonstrates conditional field visibility (file upload input appears only when Support subject is selected).
- Page Path:
/sites/prism/home/forms-catalog/meeting-booking - Fields: Full Name (
fmdb:inputText), Email (fmdb:inputEmail), Phone (gtf:inputPhone), Preferred Date & Time (fmdb:inputDatetimeLocal), Backup Date (fmdb:inputDate), Meeting Format (fmdb:select), Campaign Source (fmdb:inputHidden), Form Style (gtf:formStyle) - Actions: Saves to JCR (
fmdb:save2jcrAction) - Purpose: Demonstrates date/time pickers, international phone inputs, and hidden tracking fields.
- Page Path:
/sites/prism/home/forms-catalog/event-registration - Fields: 2 Steps (
personal→preferences), Form Style (gtf:formStyle) - Actions: Saves to JCR (
fmdb:save2jcrAction) - Purpose: Multi-step registration flow showing guest options and conditional dietary/accessibility questions.
- Page Path:
/sites/prism/home/forms-catalog/product-survey - Fields: Product (
fmdb:select), Satisfaction (gtf:inputRating), Liked Features (fmdb:checkbox), Aspect Rating Matrix (gtf:inputMatrix), Main Complaint (fmdb:select), Improvements (fmdb:textarea), Recommendation (fmdb:radio), Follow-up (fmdb:textarea), Form Style (gtf:formStyle) - Actions: Saves to JCR (
fmdb:save2jcrAction) - Purpose: Feedback & NPS evaluation showcasing custom star ratings and rating matrices.
- Page Path:
/sites/prism/home/forms-catalog/ux-research-survey - Fields: 2 Steps (
discovery→preferences), Form Style (gtf:formStyle) - Actions: Saves to JCR (
fmdb:save2jcrAction) - Purpose: Multi-step survey featuring interactive drag-to-rank feature prioritization (
gtf:inputRanking) and color selection.
- Page Path:
/sites/prism/home/forms-catalog/job-application - Fields: 3 Steps (
profile→details→confirmation), Form Style (gtf:formStyle) - Actions: Saves to JCR (
fmdb:save2jcrAction) & triggers dual emails (gtf:emailTemplateActionto candidate and HR) - Purpose: Multi-step job application funnel with role-based branching and automated notification dispatch.
- Page Path:
/sites/prism/home/forms-catalog/insurance-quote - Fields: 4 Steps (
your-situation→coverage→budget-priorities→confirmation), Form Style (gtf:formStyle) - Actions: Saves to JCR (
fmdb:save2jcrAction) - Purpose: Advanced insurance risk wizard utilizing image options (
gtf:inputImageChoice), budget sliders, summary recap, and sub-form embedding.
- Page Path:
/sites/prism/home/pricing/quote - Fields: Service (
fmdb:select), Pages (fmdb:inputText), CMS (fmdb:select), Site URL (fmdb:inputText), Project Goals (fmdb:textarea), Form Style (gtf:formStyle) - Actions: Saves to JCR (
fmdb:save2jcrAction) - Purpose: Commercial pricing estimation form for prospective web projects.
| Service | URL | Purpose |
|---|---|---|
jahia |
https://prism.localhost | Jahia application |
mailpit |
https://mailpit.localhost | Mail catcher (web UI) — SMTP on :1025 |
reverse-proxy |
https://traefik.localhost/dashboard/ | Traefik dashboard (note the trailing slash) |
postgres |
internal only | Jahia database |
provisioning-render |
one-shot, exits after rendering | Builds the final provisioning script |
All *.localhost hosts resolve locally without any /etc/hosts changes on most systems (Chrome, Firefox, and modern OSes resolve .localhost to 127.0.0.1 automatically).
- Docker and Docker Compose v2
- Ports
80,443,8080,8025,1025,9229free on the host
cp env.example .env
# edit .env: set MCP_API_TOKEN, adjust MCP_ENABLED/passwords as needed
docker compose upThen visit https://prism.localhost. The self-signed dev certificate will trigger a browser warning the first time — that's expected for local TLS.
Every value below has a sane default baked into docker-compose.yml — .env only needs to override what you actually care about. env.example lists all of them explicitly for discoverability.
Jahia
| Variable | Default | Description |
|---|---|---|
SUPER_USER_PASSWORD |
root1234 |
Jahia root/admin password |
TIMEZONE |
Europe/Paris |
Container timezone |
MCP_ENABLED |
false |
When true, installs the MCP module and creates an API token on startup |
MCP_API_TOKEN |
— | Token value used when creating the MCP API token (only used if MCP enabled) |
JPDA |
true |
Enables the Java remote debugger (separate from JAHIA_DEBUG_PORT, which is the Node/Chrome inspector) |
Database
| Variable | Default | Description |
|---|---|---|
DB_NAME |
jahia |
Postgres database name |
DB_USER |
jahia |
Postgres user |
DB_PASS |
dbpassword |
Postgres password |
Mail (internal Docker network hostnames — different from MAILPIT_HOST, which is the external Traefik-routed host)
| Variable | Default | Description |
|---|---|---|
MAIL_SMTP_HOST |
mailpit |
SMTP host Jahia connects to (Compose service name) |
MAIL_SMTP_PORT |
1025 |
SMTP port Jahia connects to (container-internal port) |
Hostnames (all resolve locally without /etc/hosts changes on most systems)
| Variable | Default | Description |
|---|---|---|
JAHIA_HOST |
prism.localhost |
Host routed to the Jahia UI |
MAILPIT_HOST |
mailpit.localhost |
Host routed to the Mailpit UI |
TRAEFIK_HOST |
traefik.localhost |
Host routed to the Traefik dashboard |
Ports
| Variable | Default | Description |
|---|---|---|
HTTP_PORT |
80 |
Traefik HTTP entrypoint |
HTTPS_PORT |
443 |
Traefik HTTPS entrypoint |
JAHIA_HTTP_PORT |
8080 |
Jahia HTTP port (also exposed directly) |
JAHIA_DEBUG_PORT |
9229 |
Node/Chrome DevTools inspector port (chrome://inspect) |
MAILPIT_UI_PORT |
8025 |
Mailpit web UI |
MAILPIT_SMTP_PORT |
1025 |
Mailpit SMTP listener |
Image versions
| Variable | Default |
|---|---|
JAHIA_IMAGE |
achaabni/jahia-prism:0.1.1 |
POSTGRES_IMAGE |
postgres:16 |
MAILPIT_IMAGE |
axllent/mailpit:latest |
TRAEFIK_IMAGE |
traefik:v3.7.6 |
ALPINE_IMAGE |
alpine:3.20 |
.env is gitignored — never commit real credentials. Use env.example as the template for what needs to be set.
Jahia's Provisioning API has no built-in conditionals, so this project renders the final provisioning.yaml at container startup instead of using a static file:
provisioning-render(a one-shot Alpine container) readsjahia/provisioning/base.yamland, ifMCP_ENABLED=true, appendsjahia/provisioning/mcp.yaml.- It writes the result — plus the Groovy scripts from
jahia/provisioning/scripts/— into a sharedprovisioningnamed volume. - The
jahiaservice waits forprovisioning-renderto complete, then mounts that volume and runsEXECUTE_PROVISIONING_SCRIPTagainst the renderedprovisioning.yaml.
To change what gets provisioned, edit base.yaml / mcp.yaml (always-run vs. MCP-gated steps) rather than a single flat file.
.
├── docker-compose.yml
├── .env # local secrets (gitignored)
├── env.example # template for .env
├── jahia/
│ ├── render-provisioning.sh # builds provisioning.yaml from fragments
│ └── provisioning/
│ ├── base.yaml # steps that always run
│ ├── mcp.yaml # steps run only when MCP_ENABLED=true
│ └── scripts/
│ ├── activate-mail-server.groovy
│ └── create-token.groovy # reads MCP_API_TOKEN from env
└── traefik/
├── tls.yaml # TLS store config for traefik
└── certs/
├── generate.sh # regenerates the self-signed localhost cert
├── localhost.crt
└── localhost.key # gitignored
docker compose up -d # start the stack in the background
docker compose logs -f jahia # tail Jahia logs
docker compose down # stop the stack
docker compose down -v # stop and wipe volumes (Postgres data, rendered provisioning)To toggle MCP after the stack has already been provisioned once, update MCP_ENABLED in .env and recreate the jahia container:
docker compose up -d --force-recreate jahia provisioning-render