Visão arquitetural

Princípio orientador

A arquitetura baseia-se no princípio de separação de preocupações:

  • Conteúdo : ficheiros AsciiDoc estruturados com metadados ricos

  • Apresentação : templates Thymeleaf reutilizáveis

  • Dados : modelo extraído automaticamente pelo JBake a partir dos atributos AsciiDoc

  • Style : Bootstrap 5 para consistência visual

Escolha estratégica : AsciiDoc para o portfólio

Table 1. Por que AsciiDoc ?
Critério vantagem

Coerência

Mesmo formato que os artigos de blog

Metadados

Atributos estruturados e extensíveis (project-*)

Manutenabilidade

Edição simples em texto, versionável Git

Flexibilidade

Pode conter conteúdo rico (tabelas, código, imagens)

Modelagem

JBake extrai automaticamente os atributos para o Thymeleaf

modelo de dados

Cada projeto de portfólio é um documento AsciiDoc com:

  • Metadados de cabeçalho : informações estruturadas (cliente, duração, tecnologias, etc.)

  • Corpo do documento: descrição narrativa, desafios, soluções, resultados

  • Atributos personalizados : prefixados`project-*`para extração automática

@startuml
skinparam backgroundColor #FEFEFE
skinparam handwritten false

class ProjetAsciiDoc {
  +titre: String
  +jbake-type: "projeto"
  +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 : analisar
JBakeEngine --> ThymeleafTemplate : fornece dados
ThymeleafTemplate --> PortfolioPage : gera
@enduml

Casos de Uso Detalhados

UC1 : Adicionar um elemento ao portfólio

Fluxo nominal

@startuml
skinparam backgroundColor #FEFEFE
actor Développeur as dev
participant "Editor\nTexto" as editor
participant "File\nAsciiDoc" as file
participant "JBake\nMotor" as jbake
participant "Site\nestático" as site

dev -> editor : Criar novo arquivo
activate editor
editor -> file : portfolio/nouveau-projet.adoc
activate file

dev -> editor : Escrever cabeçalho com metadados\n(title, type=project, status=published,\natributos project-*)
dev -> editor : Escrever conteúdo narrativo\n(contexto, desafios, soluções)
dev -> editor : Adicionar imagens em assets/img/portfolio/

editor -> file : Salvar
deactivate editor

dev -> jbake : Iniciar build (jbake -b)
activate jbake
jbake -> file : Ler e analisar
jbake -> jbake : Extrair metadados
jbake -> jbake : Converter AsciiDoc → HTML
jbake -> jbake : Aplicar o template project.html
jbake -> jbake : Adicionar à lista portfolio.html
jbake -> site : Gerar páginas estáticas
deactivate jbake

dev -> site : Verificar resultado
activate site
site --> dev : Exibir projeto
deactivate site
@enduml

modelo do arquivo a ser criado

O desenvolvedor cria`content/portfolio/nom-projet.adoc`com uma estrutura padronizada:

  • Cabeçalho com todos os atributos necessários

  • Seções normalizadas (Contexto, Desafios, Soluções, Resultados)

  • Nomenclatura coerente das imagens

Pontos de validação

  • Os atributos obrigatórios estão presentes (jbake-type, jbake-status, project-thumbnail)

  • As imagens referenciadas existem em`assets/img/portfolio/`

  • O build JBake é bem-sucedido sem erro

  • O projeto aparece na página do portfólio

  • A página individual do projeto aparece corretamente

UC2: Remover um item do portfólio

fluxo nominal

@startuml
skinparam backgroundColor #FEFEFE
actor Développeur as dev
participant "Sistema\nArquivos" as fs
participant "JBake\nEngine" as jbake
participant "Site\nEstático" as site
database "Cache\nJBake" as cache

dev -> fs : Excluir portfolio/projet-ancien.adoc
activate fs
fs --> dev : Arquivo excluído
deactivate fs

dev -> fs : (Opcional) Remover imagens associadas\nassets/img/portfolio/projet-ancien-*
activate fs
fs --> dev : Imagens excluídas
deactivate fs

dev -> cache : Limpar cache JBake
activate cache
cache --> dev : Cache vazio
deactivate cache

dev -> jbake : Reconstruir completo (jbake -b)
activate jbake
jbake -> jbake : Digitalizar content/portfolio/
jbake -> jbake : Projeto ausente → não gerado
jbake -> jbake : Regenerar portfolio.html\n(sem o projeto excluído)
jbake -> site : Implantar nova compilação
deactivate jbake

dev -> site : Verificar
activate site
site --> dev : Projeto ausente da lista
deactivate site
@enduml

Estratégia alternativa : arquivamento

Em vez de excluir definitivamente, possibilidade de criar uma pasta`content/portfolio/archive/` :

  • Mover o arquivo em vez de excluí-lo

  • Permite restaurar facilmente

  • Mantenha o histórico do Git mais claro

Limpeza de recursos

  • Verificar imagens órfãs em`assets/img/portfolio/`

  • Remover as imagens não referenciadas por outros projetos

  • Limpar o cache JBake para evitar referências fantasma

UC3 : Definir como não publicado (rascunho)

Fluxo nominal

@startuml
skinparam backgroundColor #FEFEFE
actor Développeur as dev
participant "Arquivo\nAsciiDoc" as file
participant "JBake\nMotor" as jbake
participant "Site\nEstático" as site

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

dev -> file : Modificar atributo\n:jbake-status: published\n↓\n:jbake-status: draft

file --> dev : Salvo
deactivate file

dev -> jbake : Rebuild (jbake -b)
activate jbake
jbake -> file : Analisar o arquivo
jbake -> jbake : Detectar status=draft
jbake -> jbake : Excluir de published_projects
jbake -> jbake : Não criar página pública
note right
O projeto ainda existe
mas não está publicado
end note
jbake -> site : Gerar site (sem este projeto)
deactivate jbake

dev -> site : Verificar portfólio
activate site
site --> dev : Projeto ausente da lista pública
deactivate site
@enduml

Estados possíveis

@startuml
skinparam backgroundColor #FEFEFE

[*] --> Draft : Création initiale
Draft --> Published : Validação e publicação
Published --> Draft : Remoção temporária
Draft --> Archived : Projeto abandonado
Published --> Archived : Projeto obsoleto
Archived --> [*] : Exclusão definitiva
Published --> Published : Atualizações

note right of Draft
:jbake-status: rascunho
Não visível publicamente
Útil para projetos em curso
end note

note right of Published
:jbake-status: publicado
Visível no portfólio
Indexado por JBake
end note

note right of Archived
Movido para archive/
ou jbake-status: arquivado
Não publicado mas preservado
end note
@enduml

Casos de uso típicos

  • Projeto em fase de redação : criar como rascunho, publicar quando pronto

  • Projeto confidencial temporariamente : passar para draft durante o acordo do cliente

  • Atualização principal : mudar para rascunho, editar, republicar

  • A/B testing : duplicar em rascunho, testar, publicar a melhor versão

Arquitetura de Templating

Estratégia de templates reutilizáveis

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

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

  package "Parciais" {
    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 "Dados JBake" {
  database "published_projects" as data
  database "conteúdo (projeto)" as content
}

index --> header
index --> footer

portfolio --> header
portfolio --> footer
portfolio --> card
data --> portfolio : iteração

project --> header
project --> footer
project --> badge
project --> gallery
content --> project : projeto individual

note right of card
Fragmento reutilizável
para exibir um cartão
de projeto com :
- thumbnail
- título
- tags
- destaques
end note
@enduml

Padrão de extração de dados

JBake transforma automaticamente os atributos AsciiDoc em propriedades acessíveis no Thymeleaf :

@startuml
skinparam backgroundColor #FEFEFE

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

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

rectangle "Template Thymeleaf" {
  (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

Convenções de nomenclatura

  • Atributos do projeto : prefixo`project-*` (ex: project-client, project-tech-stack)

  • Ficheiros: kebab-case (ex:`ecommerce-platform.adoc`)

  • Imagens : prefixo nome-projeto (ex:`ecommerce-platform-thumb.jpg`)

  • modelos : nome funcional (ex:`project-card.html`, tech-badge.html)

Fluxo de Publicação

Pipeline de desenvolvimento

@startuml
skinparam backgroundColor #FEFEFE
skinparam handwritten false

class ProjetAsciiDoc {
  +titre: String
  +jbake-type: "projeto"
  +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 : analisar
JBakeEngine --> ThymeleafTemplate : fornece dados
ThymeleafTemplate --> PortfolioPage : gera
@enduml

Ambientes

Ambiente uso Status aceito

Local

Desenvolvimento e pré-visualização

rascunho, publicado

Encenação

Validação pré-produção

publicado apenas

produção

Site público

publicado apenas

extensibilidade

Adição de novos atributos

Para enriquecer o modelo de dados, simplesmente adicionar novos atributos prefixados`project-*`:

  • project-awards: Prêmios e reconhecimentos

  • project-testimonial: Citação do cliente

  • project-team-size: Tamanho da equipe

  • `project-budget-range`faixa orçamentária

Estes atributos ficam automaticamente disponíveis nos templates sem modificação no motor JBake.

Categorização avançada

@startuml
skinparam backgroundColor #FEFEFE

object Projet {
  project-category = "web"
  project-subcategory = "comércio eletrônico"
  project-industry = "varejo"
  project-complexity = "alto"
}

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

Projet --> Taxonomie : classificado segundo

note right of Taxonomie
Permite filtragem multi-critério no template portfolio.html via JavaScript ou no lado do servidor
end note
@enduml

Boas Práticas

Organização dos arquivos

  • Um arquivo = um projeto : evitar misturar vários projetos

  • Imagens na pasta dedicada :`assets/img/portfolio/nom-projet/`

  • Nomenclatura consistente : facilita pesquisa e manutenção

  • Versioning Git : rastreamento completo das modificações

Gestão de conteúdo

  • Status de rascunho padrão : publicar somente quando pronto

  • Revisão pré-publicação : validação de qualidade e confidencialidade

  • Metadados completos : preencher todos os campos pertinentes

  • Conteúdo narrativo rico : não se limitar aos metadados

Desempenho

  • Otimizar imagens : compressão antes do commit

  • Pagination se necessário : se >20 projetos

  • Lazy loading : imagens das galerias carregadas sob demanda

  • Cache do navegador : cabeçalhos apropriados para assets

Conclusão

Esta arquitetura permite :

  • Simplicidade de uso : adicionar um projeto = criar um arquivo de texto

  • Flexibilidade : extensível via novos atributos

  • Manutenabilidade : separação conteúdo/apresentação

  • Rastreabilidade : versionamento Git completo

  • Automação : build e implantação contínua possível

A escolha do AsciiDoc garante a coerência com o resto do site, oferecendo ao mesmo tempo a riqueza dos metadados necessários a um portfólio profissional.

Artigos relacionados