- Jinja 35.8%
- JavaScript 32.8%
- Python 15.2%
- CSS 14.9%
- Dockerfile 0.7%
- Andere 0.6%
| _data | ||
| _templates | ||
| admin | ||
| assets | ||
| content | ||
| .dockerignore | ||
| .gitignore | ||
| build.py | ||
| Dockerfile | ||
| nginx.conf | ||
| pentest-rapport-sekondant.pdf | ||
| README.md | ||
| requirements.txt | ||
Sekondant — statische site + CMS
Deze repo bevat de website sekondant.je-ma.com: een set statische HTML-pagina's die uit content-bestanden gegenereerd wordt, met een web-admin (Decap CMS) zodat de content zonder code-kennis bewerkt kan worden. Gedeployed via Coolify.
SekWebsite/
├── content/ ← *** wat je bewerkt *** (YAML + Markdown)
│ ├── index.yml ← homepage
│ ├── welkom.yml
│ ├── voor-wie-werken-wij.yml
│ ├── zaalhuur.yml
│ ├── vacatures.yml
│ ├── route.yml
│ ├── contact.yml
│ ├── pagina/ ← extra pagina's (zelf aanmaken via CMS)
│ ├── juridisch/ ← juridische pagina's (folder-collectie)
│ └── nieuws/ ← nieuwsberichten (folder-collectie)
├── _data/site.yml ← menu's, logo, footer, copyright, badges
├── _templates/
│ ├── base.html.j2 ← gedeelde HTML-skelet (nav + footer)
│ ├── _blocks.html.j2 ← block-render-macro (tekst, foto, kaarten…)
│ ├── _icons.html.j2 ← SVG-iconenset
│ └── *.html.j2 ← per pagina-type
├── assets/ ← CSS, JS, afbeeldingen
├── admin/ ← Decap CMS web-admin (op /admin/)
│ ├── index.html ← laadt decap-cms + marked + preview.js
│ ├── config.yml ← schema voor alle pagina's
│ └── preview.js ← live preview (huisstijl + per-pagina rendering)
├── build.py ← genereert _site/ uit content/ + templates
├── requirements.txt ← Python-deps
├── Dockerfile ← multi-stage build: Python → nginx
└── .dockerignore
Wat je via de web-admin kan
Open https://sekondant.je-ma.com/admin/, log in via Forgejo. Linkerzijbalk:
| Collectie | Wat erin staat |
|---|---|
| Hoofdpagina's | De zeven vaste pagina's met hun eigen layout (homepage, welkom, voor wie, zaalhuur, vacatures, route, contact). Elk veld heeft uitleg-hint en list-summary. |
| Extra pagina's | Maak nieuwe pagina's met een vrij in te delen layout via blokken. Zie hieronder. |
| Nieuws | Nieuwsberichten met datum, samenvatting en body. URL automatisch /nieuws/2026-06-01-titel.html. Archief op /nieuws.html regenereert zichzelf. |
| Juridische pagina's | Cookieverklaring, privacy, toegankelijkheid, CVD. Folder-collectie: nieuwe disclosures toevoegen kan met "New". |
| Site-instellingen | Logo, slogan, footer-copyright, badges (meerdere mogelijk), hoofdmenu, juridische footer-links. |
Live preview
Rechts van het formulier verschijnt een echte preview van de pagina met de huisstijl (blauwe kleuren, Open Sans, info-cards, etc.). De preview update terwijl je typt voor:
- Alle Hoofdpagina's (homepage met hero + 4 kaarten, welkom met media-split + service-grid, voor wie werken wij met partner-blokken, zaalhuur met vergaderzaaltabel, etc.)
- Extra pagina's (met of zonder blokken)
- Nieuws-berichten
- Juridische pagina's
Block-based content (Extra pagina's)
Bij het bewerken zie je een Pagina-indeling-veld waarin je losse blokken plakt en sleept om de volgorde te bepalen. 19 blok-types beschikbaar:
| Categorie | Blok | Wanneer gebruiken |
|---|---|---|
| Basis | Tekst, Lead, Tussenkop | Doorlopende paragrafen, intro-zin, of H2/H3 om een sectie te beginnen. |
| Media | Afbeelding, Galerij, Video | Foto's of YouTube/Vimeo-embed. |
| Layout | Tekst + foto, Kaarten-grid, Tabel | Media-split, 2/3/4 kaarten met icoon, of een eigen tabel. |
| Interactie | CTA, Formulier, FAQ | Knop-rij, Formspree-formulier, of openklap-vragen. |
| Storytelling | Timeline, Testimonial | Mijlpalen op een tijdlijn of een citaat. |
| Commercieel | Prijstabel | Pakketten met prijs, kenmerken en knop. |
| Accenten | Aandachtsblok, Scheidingslijn | Gekleurd kader voor aankondiging, of horizontale scheiding. |
| Downloads | PDF-download | Klikbare kaart met PDF-icoon en download-pijl. |
| Escape | Eigen HTML | Embeds (Google Maps iframe etc.) — pas op met onbekende bronnen. |
Voor simpele pagina's kun je in plaats van blokken het "Simpele tekst"-veld gebruiken (alleen actief als er géén blokken zijn).
Nieuws-functies
- Tags: per bericht meerdere tags. Verschijnen als chips bovenaan; klikken
filtert het archief op
/nieuws/tag/<tag>.html. - Vastpinnen: bericht blijft altijd bovenaan in het archief.
- Downloads onderaan: lijst van PDFs in een aparte download-sectie.
- Gerelateerde berichten: automatisch onder elk bericht op basis van overlappende tags (top 3).
- RSS-feed op
/nieuws/feed.xmlmet de laatste 50 berichten.
Concept / verbergen
Elke pagina, juridische pagina en nieuwsbericht heeft een Gepubliceerd?-toggle. Zet uit → niet zichtbaar op de site (ook niet in archief, RSS of sitemap). Handig om een bericht voor te bereiden en later te publiceren.
SEO per pagina
- SEO-beschrijving (
<meta description>) op elke pagina - Sociale-media voorbeeldafbeelding (Open Graph
og:image) — wordt getoond bij delen op LinkedIn/Twitter/Facebook - Verbergen voor zoekmachines (
noindex) per pagina - Auto-gegenereerd:
/sitemap.xml,/robots.txt, JSON-LD voor Organization- BreadcrumbList op elke pagina
Meerdere badges in de footer
Naast ISO 27001 kun je via Site-instellingen → Badges in de footer logo's toevoegen — lidmaatschappen, partnerschappen, andere certificeringen. Per badge: afbeelding, alt-tekst, en optionele klikbare link.
Meerdere badges in de footer
Naast ISO 27001 kun je via Site-instellingen → Badges in de footer logo's toevoegen — lidmaatschappen, partnerschappen, andere certificeringen. Per badge: afbeelding, alt-tekst, en optionele klikbare link.
Content lokaal bewerken
pip install -r requirements.txt # eerste keer
python3 build.py # output -> _site/
python3 -m http.server 8080 -d _site
# open http://localhost:8080
Deploy via Coolify
- Resource → New → Public/Private Repository. Verbind met
code.securityasaservice.org/Sek/SekWebsite.git, branchmain. - Build pack: Dockerfile. Coolify detecteert de
Dockerfilein de root. - Domain:
sekondant.je-ma.com. TLS-toggle aan. - Ports Exposed:
80(default 3000 werkt niet voor nginx). - Webhook: in Forgejo bij Settings → Webhooks → Add (Gitea) plak de
Coolify deploy-webhook URL. Trigger op
Push events, branchmain. - Deploy.
Eenmalige setup in Forgejo (voor Decap CMS)
A. OAuth-applicatie
- User Settings → Applications → Create New OAuth2 Application
- Vul in:
- Application Name:
Sekondant CMS - Redirect URIs:
https://sekondant.je-ma.com/admin/ - Vink Confidential client uit (PKCE)
- Application Name:
- Plak de Client ID in
admin/config.ymlbijapp_id:.
B. CORS via een Caddy-sidecar
Forgejo's eigen [cors]-config werkt niet voor het OAuth-token-endpoint. Daarom
loopt /login/oauth/access_token en /api/v1/* via een mini Caddy-proxy die
preflights afhandelt en de juiste headers injecteert.
In de Compose-stack van Forgejo staat een service forgejo-cors (Caddy:2-alpine)
op het zelfde netwerk. In Traefik gaat alleen die ene host+path-combinatie via
Caddy; de rest van Forgejo loopt rechtstreeks. Zie de docker-compose voor de
exacte labels.
Hoe de auto-deploy werkt
Redacteur bewerkt in Decap
│
▼
Decap commit content/* naar main (Forgejo API via Caddy-CORS)
│
▼
Forgejo webhook -> Coolify
│
▼
Coolify docker build:
stage 1: python -> build.py -> /site
stage 2: nginx serveert /site op poort 80
│
▼
sekondant.je-ma.com toont de nieuwe pagina
Wat staat waar?
| Wil je aanpassen… | Bewerk dan… |
|---|---|
| Hoofdmenu / footer-links | _data/site.yml (of CMS → Site-instellingen) |
| Logo, copyright, slogan, badges | _data/site.yml |
| Hero-tekst / -afbeeldingen | content/index.yml → hero: |
| 4 kaarten op homepage | content/index.yml → cards: |
| Partner-info (Movisie/NJi/Vilans) | content/voor-wie-werken-wij.yml |
| Vergaderzaaltabel | content/zaalhuur.yml → rooms_table: |
| Openstaande vacatures | content/vacatures.yml |
| Openingstijden, telefoon, mail | content/contact.yml |
| Cookie-/privacy-/CVD-tekst | content/juridisch/*.md (Markdown) |
| Nieuwe vrije pagina | content/pagina/<slug>.md (CMS → Extra pagina's → New) |
| Nieuws-bericht | content/nieuws/<datum>-<slug>.md (CMS → Nieuws → New) |
| Visuele styling / kleuren | assets/css/style.css |
| Nginx / serve-config | Dockerfile (laatste stage) |
| Nieuwe blok-type aan templates | _templates/_blocks.html.j2 (Jinja) + admin/preview.js (preview) + admin/config.yml (CMS-velden) |
Cookie-banner
Tekst, knopteksten en de "Voorkeuren wijzigen"-link in de footer zijn bewerkbaar
via Site-instellingen → Cookie-banner. Toestemming wordt opgeslagen in
localStorage; CustomEvent('cookie-consent') wordt afgevuurd zodat analytics-
scripts kunnen reageren:
window.addEventListener('cookie-consent', function (e) {
if (e.detail.value === 'accept') {
// laad bv. Plausible script
}
});
Image pipeline (WebP + lazy-loading)
build.py genereert automatisch een .webp variant naast elke jpg/png in
assets/. Tijdens render worden alle <img> gewrapt in <picture> met de WebP
als bron, en loading="lazy" decoding="async" toegevoegd waar nog niet aanwezig.
Inline background-image:url('...jpg') wordt herschreven naar .webp als
beschikbaar. Het nav-logo krijgt loading="eager" fetchpriority="high" voor LCP.
Bestandsgroottes zakken doorgaans 40–75% — zichtbare Lighthouse-winst zonder
template-wijzigingen.
Aandachtspunten
- Build output
_site/is niet in git — verwijder gerust als je hem niet nodig hebt. - Image-paths: gebruik
assets/img/...(zonder leading slash). Decap upload doet dit automatisch. - Sub-paginas (zoals
/nieuws/foo.html) gebruiken automatisch een base-path filter zodat assets, nav-links en footer-links blijven werken. - Body van juridische pagina's is Markdown — vetgedrukt, lijsten en links werken zoals je verwacht.
- Geen Forgejo Actions runner nodig — Coolify regelt de build in de container.
- Nieuws-overzicht (
/nieuws.html) wordt automatisch gegenereerd; vergeet niet "Nieuws" handmatig aan het hoofdmenu toe te voegen.