paulserban.eu

Portfolio Edition

Paul Serban

AI & full-stack engineer · agentic platforms · distributed systems

← Back to portfolio

Personal Portfolio (V1)

Full working service - not yet load-tested

Vanilla Webpack/Handlebars static portfolio with ADRs

Role: Architect & lead implementer

  • #adr
  • #architecture
  • #css
  • #github pages
  • #handlebars

Problem

I needed a credible online presence and a freeCodeCamp-compliant portfolio without adopting a framework I could not yet justify - and I wanted the architecture decisions written down, not buried in tribal knowledge.

Approach

Constrained the stack to vanilla HTML/CSS/JS; treated Webpack + Handlebars as a lightweight SSG over JSON content; split the product into a portfolio surface and a design-system surface; recorded nine ADRs and ASRs as the delivery contract.

Outcome

Shipped a maintainable static site on GitHub Pages and proved the content-at-build idea that v2 later expanded into typed MDX collections, SEO, and dual hosting.

pages
2
adrs
9
hosting
GitHub Pages
View code Live demo

Problem

A personal engineering presence has to do two jobs at once: show the work and show how you think about systems. For v1 that meant a freeCodeCamp-compliant portfolio (fixed navbar, welcome hero, project tiles, profile link) that still read as deliberate architecture - not a theme dump or a framework demo I could not defend.

I did not yet need a blog, typed collections, or a multi-environment CDN. I did need:

The risk of skipping that discipline was clear: a pretty single page that could not grow, could not explain itself, and would force a full rewrite the moment content or SEO became real requirements.

Solution

I built prj--personal-portfolio--v1 as a static site with an explicit architecture contract: vanilla frontend, Webpack 5 + Handlebars as a lightweight SSG, JSON content merged at build time, and GitHub Pages as the sole hosting path.

The product is two HTML outputs from one pipeline: the portfolio (index) - hero, about, technical arsenal, projects, experience, contact - and a design system page that documents colors, typography, components, and UI patterns (terminal, skill cloud, timeline, competency matrix). Multi-entry *.entry.js bundles keep each UI area's CSS/JS co-located with its Handlebars partial. Nine ADRs lock the framework, build, content, hosting, navigation, structure, Sass, and Babel choices.

Architecture

src/data/*.json          <- profile, projects, pages, skills, …
src/markup/*.hbs         <- index + design_system + partials/
src/styles/**/*.scss     <- tokens, reset, themes, components
src/scripts/**/*.entry.js
        │
        ▼
 Webpack 5
   HandlebarsPlugin  ->  dist/*.html   (all JSON merged into context)
   multi-entry JS/CSS ->  named bundles
   Sass -> MiniCssExtract -> minified CSS
   Babel + Terser -> production JS
        │
        ▼
 GitHub Actions (push main)
   npm ci -> npm run build -> peaceiris/gh-pages -> dist/
        │
        ▼
 GitHub Pages
   paulalexserban.github.io/prj--personal-portfolio--v1/
LayerResponsibility
src/data/JSON content: page shells, profile, projects, skills, competency matrix, experience (and stubs for coursework / arsenal)
src/markup/Handlebars pages + partials; _template_base layout; section composition
src/scripts/Multi-entry feature bundles (navbar, hero, terminal, about, contact, …)
src/styles/Sass tokens / themes; CSS variables for light/dark
build/Modular Webpack config: paths, loaders, plugins, entry glob
ADRs / ASRsDecision log and quality attributes under docs/arch docs/
CI.github/workflows/deploy.yml -> build -> GitHub Pages

Approach

As architect and lead implementer, I treated a "simple" portfolio as a system with boundaries - content, composition, assets, and delivery - and wrote the decisions down before the stack could calcify by accident.

Platform boundaries first

Product surfaces

Architecture knowledge management

Stack

LayerChoices
AuthoringJSON in src/data/, Handlebars markup + partials
BuildWebpack 5, Handlebars plugin, Sass, Babel, Terser, CSS minimizer
RuntimeVanilla ES6+ modules, CSS variables theme, no framework
DeliveryGitHub Actions -> GitHub Pages (dist/)
GovernanceADRs, ASRs, Dependabot, CODEOWNERS

Design decisions that mattered

What shipped

Outcome

V1 established an online presence and, more importantly, a habit of platform thinking on a small surface: content separated from markup, build as a contract, design system as a first-class page, decisions written as ADRs. Its limits - co-located content, incomplete data binding, single hosting path, no typed collections or SEO release seam - are exactly what v2 was designed to fix. The line from this Webpack/Handlebars site to a multi-surface content platform is continuous, not a rewrite from zero.

Predecessor to the platform

This is the first generation of the personal engineering site. Related successors: