- Nunjucks 33.2%
- HTML 28.4%
- CSS 18.8%
- PHP 13.4%
- JavaScript 3.1%
- Andere 3.1%
- promote.php: server-side endpoint dat via de Gitea-API een PR van de ene omgevingsbranch naar de volgende aanmaakt en merget (dev -> test -> acc -> prod) - admin/promote.html: promotiepaneel in de CMS met wachtwoord-guard en confirm op productie - Decap CMS commit nu naar de dev-branch - config.local.example en docker-compose: JEMA_GITEA_TOKEN en JEMA_PROMOTE_SECRET - README: OTAP-sectie met Coolify-, Gitea- en promotie-instructies - promote.php meegekopieerd in de Eleventy-build Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| docker | ||
| src | ||
| .dockerignore | ||
| .eleventy.js | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| package.json | ||
| README.md | ||
Je-Ma ICT Beheer website
Statische site gebouwd met Eleventy, met content
beheerd via Decap CMS. Source-bestanden staan in
src/, de gebouwde site komt in _site/.
Structuur
.
├── .eleventy.js Eleventy-configuratie
├── package.json Node-dependencies en build-scripts
├── src/
│ ├── _data/ YAML data-files (site-config, navigatie, footer)
│ ├── _includes/ Layouts en partials
│ │ ├── base.njk Basis-HTML met head + header + footer
│ │ ├── article.njk Layout voor een nieuws-artikel
│ │ └── partials/ Header en footer partials
│ ├── _news/ Markdown-bestanden, één per nieuwsbericht
│ ├── admin/ Decap CMS (index.html + config.yml)
│ ├── assets/ Afbeeldingen, fonts, logos, badges
│ ├── css/ Stylesheet
│ ├── js/ JS (inclusief vendored captcha-widget)
│ ├── *.html Pagina-templates (gebruiken base.njk via frontmatter)
│ ├── *.php Server-side endpoints (contact + altcha)
│ ├── .htaccess Apache-config (security-headers + CSP)
│ ├── robots.txt
│ └── sitemap.xml
└── _site/ Build-output (gitignored)
Lokaal werken
Eenmalig:
npm install
Daarna voor lokaal ontwikkelen:
npm run serve
Eleventy serveert op http://localhost:8080 en watcht wijzigingen in src/.
Voor een productie-build:
npm run build
De gebouwde site staat in _site/.
Deployment
De aanbevolen route is Docker via Coolify. De Dockerfile in de
repo-root bouwt Eleventy en zet daarna een PHP 8.3 + Apache image klaar
met _site/ als document-root, msmtp voor mail-relay en een
volume-mount voor rate-limit state.
Coolify
- Nieuw project in Coolify, Type "Dockerfile". Koppel deze repo
(Gitea-source). Branch:
main. - Build settings: geen extra build args nodig; Coolify pakt het
Dockerfileautomatisch. - Environment variables (zie
docker-compose.ymlvoor het complete overzicht):JEMA_ALTCHA_KEY(secret, vereist) — genereer metopenssl rand -hex 32JEMA_MAIL_TO— geadresseerde, defaultsupport@je-ma.comJEMA_MAIL_FROM— afzender, defaultno-reply@je-ma.comSMTP_HOST,SMTP_PORT,SMTP_USER,SMTP_PASS,SMTP_FROM— SMTP-relay voor uitgaande mail (verplicht voor werkende contactformulier)
- Persistent storage: mount een volume op
/var/lib/jema-statezodat rate-limit- en replay-cache een container-restart overleven. - Domain:
je-ma.com, met automatische HTTPS via Coolify (Caddy of Traefik labels). - Health-check zit al in het image (
HEALTHCHECK ... curl /), Coolify pakt die automatisch op. - Deploy. Coolify bouwt het image, start de container en koppelt
het domein. Bij elke push naar
mainherbouwt Coolify automatisch (mits Auto Deploy aan staat).
Lokaal testen
# Bouw en draai in één:
docker compose up --build
# Of zonder compose:
docker build -t jema-web .
docker run --rm -p 8080:80 \
-e JEMA_ALTCHA_KEY=$(openssl rand -hex 32) \
-e SMTP_HOST=smtp.example.com -e SMTP_PORT=587 \
-e SMTP_USER=u -e SMTP_PASS=p \
-v jema-state:/var/lib/jema-state \
jema-web
De site is dan beschikbaar op http://localhost:8080.
Build buiten Docker (legacy / handmatig)
Als je liever zonder Docker werkt, draait de oude flow ook nog:
npm install
npm run build # output in _site/
rsync -a --delete _site/ /var/www/jema-html/
Documentroot = _site/. Mail-config via src/config.local.php.
OTAP (dev, test, acc, prod)
De site gebruikt een OTAP-branchmodel. Content en code stromen door de keten van laag naar hoog:
dev -> test -> acc -> prod
- dev: de werkbranch. Decap CMS commit hier naartoe (zie
backend.branch: devinsrc/admin/config.yml). - test: interne verificatie.
- acc: acceptatie/klant-review.
- prod: productie, gekoppeld aan
je-ma.com.
main blijft bestaan als de repo-default (waar code-PR's op landen), maar
de deploys draaien op de OTAP-branches. Wil je main niet meer gebruiken,
dan kun je de default-branch in Gitea op dev zetten.
Deploy-topologie (Coolify)
Maak in Coolify vier deploys van dit Dockerfile, elk gekoppeld aan een
branch met een eigen subdomein:
| Branch | Coolify-app | Domein |
|---|---|---|
| dev | jema-dev | dev.je-ma.com |
| test | jema-test | test.je-ma.com |
| acc | jema-acc | acc.je-ma.com |
| prod | jema-prod | je-ma.com |
Zet op elke app dezelfde env-vars als de bestaande productie-app (zie
docker-compose.yml). Elke omgeving heeft eigen state en eigen secrets.
Zet dev, test en acc bij voorkeur achter HTTP Basic Auth of een
IP-allowlist, zodat alleen productie publiek is.
Promoveren vanuit de CMS
In de CMS-omgeving zit een promotiepaneel op /admin/promote.html met
drie knoppen: dev -> test, test -> acc en acc -> prod. Een klik roept het
server-side endpoint promote.php aan, dat via de Gitea-API een pull
request van de ene branch naar de volgende aanmaakt en direct merget.
Benodigde server-config (per omgeving van waaruit je wilt promoveren, dus minimaal dev, test en acc):
- Gitea PAT: maak in Gitea onder Settings -> Applications -> Generate
New Token een token met schrijfrechten op de repo. Zet die als
env-var
JEMA_GITEA_TOKEN(of inconfig.local.phpalsgitea_token). - Promotie-wachtwoord: kies een geheim en zet dat als
JEMA_PROMOTE_SECRET(ofpromote_secret). Dit wachtwoord vul je in op/admin/promote.html; zonder juist wachtwoord weigert het endpoint. - Zonder beide waarden is
promote.phpfail-closed (weigert alles).
Omdat promote.php naar productie kan mergen: geef het Gitea-token alleen
aan vertrouwde beheerders, en stel branch-protection in op acc en
prod (in Gitea onder Settings -> Branches), zodat er geen directe
push buiten deze flow om plaatsvindt.
Promoveren zonder de CMS (handmatig)
Promotie is gewoon een merge, dus het kan ook via git of via de Gitea-UI
(open een PR van bijvoorbeeld test naar acc en merge die). Het
CMS-paneel is enkel een gemak bovenop diezelfde merges.
Decap CMS opzetten
Decap CMS authentiseert via Gitea OAuth. Setup-stappen:
1. OAuth-app aanmaken in Gitea
- Log in op
code.securityasaservice.orgmet een admin-account. - Ga naar Settings → Applications → Manage OAuth2 Applications.
- Klik op Create a new OAuth2 Application en vul in:
- Application Name: Je-Ma CMS
- Redirect URI:
https://je-ma.com/admin/ - Confidential Client: uitvinken (Decap gebruikt implicit grant)
- Klik op Create Application. Kopieer de Client ID.
2. Client ID invullen in config.yml
Open src/admin/config.yml en vervang
PLAK_HIER_DE_CLIENT_ID_VAN_DE_GITEA_OAUTH_APP door je Client ID.
3. CSP toestaan
De .htaccess zet een strikte Content-Security-Policy. Decap CMS heeft
toegang nodig tot Gitea en jsDelivr. Pas de policy aan in src/.htaccess:
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline'; font-src 'self'; img-src 'self' data: blob: https://code.securityasaservice.org; connect-src 'self' https://code.securityasaservice.org; worker-src 'self' blob:; frame-ancestors 'none'; form-action 'self' https://code.securityasaservice.org; base-uri 'self'; object-src 'none'"
Of beperk dit alleen tot /admin/ via een aparte <Location> block,
zodat de rest van de site een strikte CSP houdt.
4. Inloggen
Ga naar https://je-ma.com/admin/. Decap stuurt je naar Gitea voor
autorisatie. Na akkoord land je in de CMS-omgeving met:
- Site-instellingen — bedrijfsnaam, contact, navigatie, footer
- Nieuws — alle persberichten, nieuwe artikelen aanmaken
Elke wijziging wordt als commit naar main gepusht.
5. Lokaal CMS testen (zonder Gitea)
npm run cms # Decap proxy server op poort 8081
npm run serve # in een tweede terminal
local_backend: true in config.yml zorgt dat Decap met de lokale
proxy praat en wijzigingen direct op je filesystem schrijft.
Een nieuwsbericht aanmaken (handmatig, zonder CMS)
Maak een bestand in src/_news/ met YYYY-MM-DD-slug.md als naam:
---
layout: article.njk
title: 'Titel <span class="gradient-text">met accent</span>'
intro: "Korte inleiding."
date: 2026-06-15
category: "Persbericht"
heroImage: "/assets/badges/example.svg"
heroImageAlt: "Beschrijving"
---
Hier komt de inhoud. **Markdown** of HTML mag.
Eleventy bouwt automatisch /nieuws/2026-06-15-slug.html en neemt het
bericht op in de lijst op /nieuws.html.
Pagina-content uitbreiden naar CMS
De fundering staat. Site-instellingen, navigatie, footer en nieuws zijn
volledig CMS-bewerkbaar. Pagina-content (home, diensten, etc.) zit nu
nog hard in de HTML-templates onder src/.
Om een specifiek veld bewerkbaar te maken:
- Verplaats de hard-gecodeerde tekst naar een data-bestand
(bv.
src/_data/pages/home.yml). - Vervang in de template de tekst door
{{ pages.home.veld_naam }}. - Voeg een collection-entry toe in
src/admin/config.yml(de stub staat onderaan, uncomment en pas aan).
Doe dit incrementeel per veld of per pagina.
Wat niet via Eleventy gaat
contact.phpenchallenge.phpworden 1:1 mee gekopieerd vanuitsrc/. Inhoud bewerken doe je door het PHP-bestand zelf aan te passen.config.local.phpstaat op je server (gitignored).- De security-headers in
.htaccessworden 1:1 mee gekopieerd.
Veiligheidsaandachtspunten
- Geheimen (zoals de Altcha HMAC-key) blijven in
config.local.php, buiten git. - Decap CMS commit als de ingelogde gebruiker. Geef alleen vertrouwde gebruikers schrijfrechten op de repo.
- Overweeg een aparte branch (bv.
cms-edits) waar Decap naartoe pusht, met code review voor merges naarmain.