Arquitetura Portfólio JBake – Visão e Casos de Uso
Publicado em 15 January 2026
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
| Critério | vantagem |
|---|---|
Coerência |
Mesmo formato que os artigos de blog |
Metadados |
Atributos estruturados e extensíveis ( |
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.