Architectonisch visioen

leidend principe

De architectuur is gebaseerd op het principe van scheiding van zorgen :

  • Inhoud : gestructureerde AsciiDoc-bestanden met rijke metadata

  • Presentatie : herbruikbare Thymeleaf-sjablonen

  • Gegevens : sjabloon automatisch geëxtraheerd door JBake vanaf de AsciiDoc-attributen

  • Stijl : Bootstrap 5 voor visuele consistentie

Strategische keuze: AsciiDoc voor het portfolio

Waarom AsciiDoc?

Criterium voordeel

Coherentie

Zelfde formaat als de blogartikelen

metadata

Gestructureerde en uitbreidbare attributen (project-*)

onderhoudbaarheid

Simpele tekstbewerking, versiebaar met Git

Flexibiliteit

Kan rijke inhoud bevatten (tabellen, code, afbeeldingen)

Sjabloon

JBake extraheert automatisch de attributen voor Thymeleaf

gegevensmodel

Elk portfolio-project is een AsciiDoc-document met:

  • Koptekstmetadata : gestructureerde informatie (klant, duur, technologieën, enz.)

  • Lichaam van het document : narratieve beschrijving, uitdagingen, oplossingen, resultaten

  • Aangepaste attributen: voorgefixeerd`project-*`voor de automatische extractie

@startuml
skinparam backgroundColor #FEFEFE
skinparam handwritten false

class ProjetAsciiDoc {
  +titre: String
  +jbake-type: "project"
  +jbake-status: published|draft
  +jbake-date: Date
  +jbake-tags: List<String>
  --
  +project-category: String
  +project-client: String
  +project-duration: String
  +project-role: String
  +project-thumbnail: String
  +project-gallery: List<String>
  +project-tech-stack: String
  +project-highlights: List<String>
  +project-demo-url: String
  +project-github-url: String
  --
  +body: HTML (converti)
}

class JBakeEngine {
  +parse(asciidoc)
  +extractMetadata()
  +convertToHTML()
}

class ThymeleafTemplate {
  +portfolio.html
  +project.html
  +partials/project-card.html
}

class PortfolioPage {
  +published_projects: List
  +filtres: categories
}

ProjetAsciiDoc --> JBakeEngine : parse
JBakeEngine --> ThymeleafTemplate : levert gegevens
ThymeleafTemplate --> PortfolioPage : genereert
@enduml

Gedetailleerde use cases

UC1 : Voeg een element toe aan de portfolio

nominaal flux

@startuml
skinparam backgroundColor #FEFEFE
actor Développeur as dev
participant "Editor\nTekst" as editor
participant "Bestand\nAsciiDoc" as file
participant "JBake\nEngine" as jbake
participant "Site\nStatisch" as site

dev -> editor : Nieuw bestand aanmaken
activate editor
editor -> file : portefeuille/nouveau-projet.adoc
activate file

dev -> editor : Kop met metadata\n(title, type=project, status=gepubliceerd,\nattributen project-*)
dev -> editor : Schrijf narratieve inhoud\n(context, uitdagingen, oplossingen)
dev -> editor : Voeg afbeeldingen toe aan assets/img/portfolio/

editor -> file : Opslaan
deactivate editor

dev -> jbake : Start de build (jbake -b)
activate jbake
jbake -> file : Lezen en parseren
jbake -> jbake : Metadata extraheren
jbake -> jbake : Converteer AsciiDoc → HTML
jbake -> jbake : Toepassen sjabloon project.html
jbake -> jbake : Toevoegen aan de lijst portfolio.html
jbake -> site : Genereer statische pagina's
deactivate jbake

dev -> site : Resultaat controleren
activate site
site --> dev : Toon project
deactivate site
@enduml

Sjabloon van het bestand dat moet worden gemaakt

De ontwikkelaar maakt`content/portfolio/nom-projet.adoc`met een gestandaardiseerde structuur :

  • Kop met alle vereiste attributen

  • Genormaliseerde secties (Context, Uitdagingen, Oplossingen, Resultaten)

  • Coherente nomenclatuur van afbeeldingen

Validatiepunten

  • De vereiste attributen zijn aanwezig (jbake-type, jbake-status, project-thumbnail)

  • De verwezen afbeeldingen bestaan in`assets/img/portfolio/`

  • De JBake-build slaagt zonder fout

  • Het project verschijnt op de portfolio-pagina

  • De individuele projectpagina wordt correct weergegeven

UC2 : Verwijder een item uit het portefeuille

nominale flux

@startuml
skinparam backgroundColor #FEFEFE
actor Développeur as dev
participant "Systeem\nBestanden" as fs
participant "JBake\nMotor" as jbake
participant "Site\nStatisch" as site
database "Cache\nJBake" as cache

dev -> fs : Verwijderen portfolio/projet-ancien.adoc
activate fs
fs --> dev : Bestand verwijderd
deactivate fs

dev -> fs : (Optioneel) Verwijder gekoppelde afbeeldingen\nassets/img/portfolio/projet-ancien-*
activate fs
fs --> dev : Verwijderde afbeeldingen
deactivate fs

dev -> cache : Wis de cache JBake
activate cache
cache --> dev : Videocache
deactivate cache

dev -> jbake : Volledig herbouwen (jbake -b)
activate jbake
jbake -> jbake : Scanner inhoud/portfolio/
jbake -> jbake : Project ontbreekt → niet gegenereerd
jbake -> jbake : Regenereer portfolio.html\n(zonder het verwijderde project)
jbake -> site : Nieuwe build implementeren
deactivate jbake

dev -> site : Controleren
activate site
site --> dev : Project ontbreekt in de lijst
deactivate site
@enduml

Alternatieve strategie : archivering

In plaats van definitief te verwijderen, mogelijkheid om een map aan te maken`content/portfolio/archive/` :

  • Verplaats het bestand in plaats van het te verwijderen

  • Maakt het mogelijk om gemakkelijk te herstellen

  • Houd de Git-geschiedenis duidelijker

bronopschoning

  • Controleer de weesafbeeldingen in`assets/img/portfolio/`

  • Verwijder de afbeeldingen die niet door andere projecten worden gerefererd

  • Maak de JBake-cache schoon om spookverwijzingen te voorkomen

UC3: Zet als niet gepubliceerd (concept)

nominale flux

@startuml
skinparam backgroundColor #FEFEFE
actor Développeur as dev
participant "Bestand\nAsciiDoc" as file
participant "JBake\nMotor" as jbake
participant "Site\nStatisch" as site

dev -> file : Openen portfolio/projet.adoc
activate file

dev -> file : Wijzig attribuut\n:jbake-status: published\n↓\n:jbake-status: draft

file --> dev : opgeslagen
deactivate file

dev -> jbake : Opnieuw bouwen (jbake -b)
activate jbake
jbake -> file : Parseer het bestand
jbake -> jbake : Detecteer status=draft
jbake -> jbake : Uitsluiten van published_projects
jbake -> jbake : Maak geen openbare pagina.
note right
Het project bestaat nog steeds
maar is niet gepubliceerd
end note
jbake -> site : Genereer site (zonder dit project)
deactivate jbake

dev -> site : Controleer portefeuille
activate site
site --> dev : Project ontbreekt in de publieke lijst
deactivate site
@enduml

Mogelijke staten

@startuml
skinparam backgroundColor #FEFEFE

[*] --> Draft : Création initiale
Draft --> Published : Validatie en publicatie
Published --> Draft : Tijdelijk intrekken
Draft --> Archived : Verlaten project
Published --> Archived : Verouderd project
Archived --> [*] : Definitieve verwijdering
Published --> Published : Updates

note right of Draft
:jbake-status: draft
niet publiekelijk zichtbaar
nuttig voor lopende projecten
end note

note right of Published
:jbake-status: gepubliceerd
Zichtbaar op het portfolio
Geïndexeerd door JBake
end note

note right of Archived
Verplaatst naar archive/
of jbake-status: gearchiveerd
Niet gepubliceerd maar behouden
end note
@enduml

Typische gebruiksscenario’s

  • Project in concept : maak een concept, publiceer wanneer klaar

  • Tijdelijk vertrouwelijk project : overschakelen naar concept totdat de klant akkoord gaat

  • Belangrijke update: overgaan naar draft, wijzigen, opnieuw publiceren

  • A/B testing : dupliceren in concept, testen, publiceer de beste versie

Sjabloonarchitectuur

Strategie van herbruikbare sjablonen

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

package "Sjablonen Thymeleaf" {
  component [index.html] as index
  component [portfolio.html] as portfolio
  component [project.html] as project

  package "partialen" {
    component [header.html] as header
    component [footer.html] as footer
    component [project-card.html] as card
    component [tech-badge.html] as badge
    component [gallery.html] as gallery
  }
}

package "Gegevens JBake" {
  database "published_projects" as data
  database "inhoud (project)" as content
}

index --> header
index --> footer

portfolio --> header
portfolio --> footer
portfolio --> card
data --> portfolio : iteratie

project --> header
project --> footer
project --> badge
project --> gallery
content --> project : individueel project

note right of card
Herbruikbaar fragment

voor het weergeven van een projectkaart met :

- thumbnail
- titel
- tags
- highlights
end note
@enduml

Patroon van gegevensextractie

JBake converteert automatisch de AsciiDoc-attributen naar toegankelijke eigenschappen in Thymeleaf :

@startuml
skinparam backgroundColor #FEFEFE

rectangle "AsciiDoc-document" {
  (":project-client: Acme Corp") as attr1
  (":project-duration: 6 maanden") as attr2
  (":project-tags: java, react") as attr3
}

rectangle "JBake-model" {
  (content['project-client']) as prop1
  (content['project-duration']) as prop2
  (content.tags) as prop3
}

rectangle "Thymeleaf-template" {
  (th:text="${project['project-client']}") as tmpl1
  (th:text="${project['project-duration']}") as tmpl2
  (th:each="tag : ${project.tags}") as tmpl3
}

attr1 --> prop1 : parsing
attr2 --> prop2 : parsing
attr3 --> prop3 : parsing

prop1 --> tmpl1 : binding
prop2 --> tmpl2 : binding
prop3 --> tmpl3 : binding
@enduml

Naamgevingsconventies

  • Projectattributen : voorvoegsel`project-*` (ex: project-client, project-tech-stack)

  • Bestanden : kebab-case (bijv:`ecommerce-platform.adoc`)

  • Afbeeldingen : voorvoegsel projectnaam (bijv:`ecommerce-platform-thumb.jpg`)

  • Sjablonen : functionele naam (voorbeeld:`project-card.html`, tech-badge.html)

Publicatie workflow

Ontwikkelingspipeline

@startuml
skinparam backgroundColor #FEFEFE
skinparam handwritten false

class ProjetAsciiDoc {
  +titre: String
  +jbake-type: "project"
  +jbake-status: published|draft
  +jbake-date: Date
  +jbake-tags: List<String>
  __
  +project-category: String
  +project-client: String
  +project-duration: String
  +project-role: String
  +project-thumbnail: String
  +project-gallery: List<String>
  +project-tech-stack: String
  +project-highlights: List<String>
  +project-demo-url: String
  +project-github-url: String
  __
  +body: HTML (converti)
}

class JBakeEngine {
  +parse(asciidoc)
  +extractMetadata()
  +convertToHTML()
}

class ThymeleafTemplate {
  +portfolio.html
  +project.html
  +partials/project-card.html
}

class PortfolioPage {
  +published_projects: List
  +filtres: categories
}

ProjetAsciiDoc --> JBakeEngine : parse
JBakeEngine --> ThymeleafTemplate : levert gegevens
ThymeleafTemplate --> PortfolioPage : genereert
@enduml

omgevingen

omgeving Gebruik Geaccepteerde status

Lokaal

Ontwikkeling en preview

concept, gepubliceerd

Staging

pre-productievalidatie

alleen gepubliceerd

Productie

Openbare site

uitsluitend gepubliceerd

Extensibiliteit

Toevoeging van nieuwe attributen

Om het gegevensmodel te verrijken, voeg eenvoudig nieuwe voorvoegsel-attributen toe.project-*</think> (empty)

  • `project-awards`Prijzen en erkenningen

  • project-testimonial: klantcitatie

  • project-team-size: Teamgrootte

  • `project-budget-range`Begrotingsmarge

Deze attributen worden automatisch beschikbaar in de sjablonen zonder wijziging van de JBake-motor.

Geavanceerde categorisatie

@startuml
skinparam backgroundColor #FEFEFE

object Projet {
  project-category = "web"
  project-subcategory = "ecommerce"
  project-industry = "retail"
  project-complexity = "hoog"
}

object Taxonomie {
  categories : [web, mobile, data, devops]
  subcategories : Map<category, List>
  industries : [retail, finance, healthcare, ...]
  complexities : [low, medium, high]
}

Projet --> Taxonomie : geclassificeerd volgens

note right of Taxonomie
Biedt ondersteuning voor multicriteria-filteren binnen sjabloon portfolio.html via JavaScript of serverzijde.
end note
@enduml

Beste Praktijken

Organisatie van bestanden

  • Een bestand = een project: Vermeng meerdere projecten niet

  • Afbeeldingen in speciale map :`assets/img/portfolio/nom-projet/`

  • Consistente nomenclatuur : vergemakkelijkt zoeken en onderhoud

  • Versioning Git : volledige bijhouding van wijzigingen

Inhoudsbeheer

  • Standaardconceptstatus : publiceren alleen wanneer gereed

  • Review voor publicatie : validatie van kwaliteit en vertrouwelijkheid

  • Volledige metadata : vul alle relevante velden

  • Rijk narratieve inhoud : niet beperken tot metadata

prestatie

  • Afbeeldingen optimaliseren : compressie voor commit

  • Paginering indien nodig : als >20 projecten

  • Laden op aanvraag : afbeeldingen van galeries worden geladen op aanvraag

  • browsercache : geschikte headers voor assets

Conclusie

Deze architectuur maakt het mogelijk :

  • Gebruiksgemak : een project toevoegen = een tekstdocument maken

  • Flexibiliteit : extensible via nieuwe attributen

  • Onderhoudbaarheid : scheiding inhoud/presentatie

  • Traceerbaarheid : volledige Git-versiebeheer

  • Automatisering : build en continu implementatie mogelijk

De keuze voor AsciiDoc zorgt voor consistentie met de rest van de site en biedt tegelijkertijd de rijkdom aan benodigde metadata voor een professioneel portfolio.

Gerelateerde artikelen