ARCHITECTURE REVIEW

pedroreis.dev

Deepening opportunities found around the recently changed homepage, Projects archive, shared project-card module, and browser-side behavior.

2026-08-21
5 candidates
solid box = module dashed line = seam red = leakage dark box = deep module

No CONTEXT.md or docs/adr/ exists, so there are no domain terms or recorded decisions to preserve or revisit.

01 / BUILD-TIME DATA

Deepen the archive curation projection

Strong

Files

projects.html:5-20,45-73
_data/project_categories.yml
_data/repos.json

Problem

The archive module repeats category lookup while mixing normalization, counting, grouping, and rendering. Missing entries silently fall into the personal group.

Solution

Concentrate the build-time projection in one deep module that combines repository records with curation records before the page renders.

Benefits

  • locality: grouping rules live once
  • leverage: one projection feeds both groups
  • tests hit the interface
  • missing categories become visible failures

Before / repeated knowledge

repos.json
lookup
lookup
lookup
production loop
personal loop
category rules leak into rendering

After / concentrated depth

Archive projection module
join recordsclassifycount

one build-time result
for both groups

02 / SHARED RENDERING

Deepen the project-card module

Strong

Files

_includes/repo.html:1-33
index.html:42-49
projects.html:51-73

Problem

The shared module accepts unrelated optional variants and emits both visual markup and the DOM data contract consumed by browser behavior.

Solution

Normalize project presentation before rendering, then keep one coherent project-card module behind a smaller caller interface.

Benefits

  • locality: card rules change in one place
  • leverage: homepage and archive share behavior
  • tests cover raw and curated records
  • fewer optional inputs at the seam

Before / caller-specific surface

homepage caller
featured_*
archive caller
category_*
↓   ↓
repo.html
markup + data contract
caller variants leak through the seam

After / one coherent role

Project-card module

presentation data in
card markup out

internal DOM details

03 / BROWSER BEHAVIOR

Deepen the archive filtering module

Strong

Files

assets/js/script.js:13-62
projects.html:31-77
assets/css/style.css:498-600

Problem

The archive filter is coupled to global DOM selectors, data attributes, nested tag markup, group visibility, and empty-state behavior inside one closure.

Solution

Separate terminal reveal from archive filtering and concentrate matching, state transitions, and DOM updates in the archive filtering module.

Benefits

  • locality: archive behavior stops sharing a file
  • leverage: one matcher drives every state
  • tests cover search and topic outcomes
  • the interface is the test surface

Before / global coupling

flowchart TB
              DOM[Generated DOM] --> JS[script.js]
              JS --> T[terminal reveal]
              JS --> M[match cards]
              JS --> G[hide groups]
              JS --> E[empty state]
              M -. leak .-> D[data-* attributes]
              classDef leak stroke:#dc2626,stroke-width:2px;
              class D leak

After / local behavior

Archive filtering module
matchstaterender

terminal reveal stays separate

04 / EXTERNAL DATA

Separate repository metadata from portfolio curation

Worth exploring

Files

_data/repos.json
_data/project_categories.yml
projects.html:5-12
.github/workflows/update-repos.yml

Problem

The external repository metadata adapter passes upstream descriptions and topics directly into portfolio rendering, including stale blog wording after the blog was removed.

Solution

Keep fetched metadata immutable and let a portfolio curation module decide what is visible and which text belongs in the archive.

Benefits

  • locality: corrections survive metadata refreshes
  • leverage: curation rules serve every page
  • tests use stable fixture metadata
  • the adapter stops leaking upstream meaning

Before / upstream leakage

GitHub metadata adapter
portfolio archive
upstream meaning crosses the seam

After / owned meaning

metadata adapter
Portfolio curation module

owned visibility and meaning

05 / BRAND DECORATION

Delete or deepen the terminal reveal module

Speculative

Files

_includes/hero-terminal.html
assets/js/script.js:1-11
assets/css/style.css:231-287,672-680

Problem

The terminal module hardcodes its content and adds only timer-driven class changes, while reduced motion is split between CSS and JavaScript.

Solution

Keep the terminal only if it is a deliberate brand asset; otherwise apply the deletion test and remove the include, animation branch, and styles.

Benefits

  • deletion test: no complexity spreads
  • locality: fewer motion rules to verify
  • tests cover meaningful hero content
  • deepening earns leverage only if reused

Before / thin animation seam

hardcoded terminal markup
CSS opacity
JS timers
animation complexity for little behavior

After / deletion or earned depth

Hero module

meaningful status content
without scattered timing rules

TOP RECOMMENDATION

Deepen the archive curation projection first.

It is the clearest current source of shallow implementation: repeated category knowledge, silent fallbacks, and build-time work spread through the page. One deep module would improve locality, provide leverage to the card and filter modules, and create a stable interface for tests.

Jump to candidate 01