All projects

Case study

Personal Website

Angular portfolio host that owns branding, resume content, contact, SSR, and Native Federation composition for project demos.

Overview

Role
Sole engineer — product shell, SSR, federation host, content system
Timeline
2026
Status
In progress
Case study path
/projects/personal-website

Problem

A personal site needs to present credible engineering work while remaining deployable as a resume product. Embedding every experiment in the host slows shipping; splitting everything into remotes too early creates unnecessary runtime risk. The host has to be the stable brand and routing spine.

Goals

  • Ship a polished resume experience (about, skills, qualification, contact)
  • Support light/dark and bilingual shell state
  • Host federated project demos without blocking the main site
  • Keep content typed and centralized so updates stay mechanical
  • Remain SSR-capable for the marketing/resume routes

Key features

  • Resume sections driven by typed constants
  • Contact form with configuration-aware failure messaging
  • Theme and language shell state
  • Projects navigation into demos and case studies
  • Client-only federation boundary for remote routes
  • Vercel-oriented SSR prepare step in the build pipeline

Architecture

Runtime composition flow — top is the entry surface, bottom is the leaf dependency.

Open Architecture Explorer

Host = brand + resume + contact + composition. Remotes/siblings = focused engineering surfaces.

Technology

Each choice below includes the engineering reason it was selected for this project.

  • Angular

    Why selected: Standalone components, typed routing, and SSR fit a content-heavy portfolio with interactive shell state.

  • Angular SSR

    Why selected: Resume and contact routes should render without waiting on browser-only remotes.

  • Native Federation

    Why selected: Lets the host compose demos while keeping the primary deployable independent.

  • Tailwind CSS + design tokens

    Why selected: Fast, consistent UI iteration on host pages with a shared primary brand color.

  • EmailJS

    Why selected: Contact form delivery without standing up a custom mail backend for the portfolio.

  • GSAP

    Why selected: Small, intentional hero motion without adopting a heavy animation framework.

Engineering challenges

Concrete problems and the solutions that shipped.

Challenge 1

How to keep SSR for the host while federation remotes are browser-oriented?

Solution

SSR the resume/contact routes; load remotes only in the browser; mark federated paths as client render mode; allow Node federation init to soft-fail.

Challenge 2

How to grow project storytelling without forking a new page template each time?

Solution

Introduce a data-driven case-study model and a reusable detail page composed from section components.

Architecture decisions

Decision · reason · alternative · trade-off for each major fork in the road.

Decision

Host/remote split for demos

Reason
Protect the resume product’s release train from experimental UI churn.
Alternative
All demos as feature modules inside one Angular app
Trade-off
Operational complexity around manifests, remote URLs, and local multi-port development.

Decision

Typed content constants for resume data

Reason
Updates stay in one place; templates stay declarative.
Alternative
CMS or Markdown for every resume field
Trade-off
Non-developers cannot edit content without a PR; acceptable for a personal site.

Decision

Case-study pages in the host (not only live demos)

Reason
Hiring readers need engineering decisions, trade-offs, and lessons—not only a running widget.
Alternative
Demo-only projects dropdown with no write-up
Trade-off
More content to maintain; mitigated by a single reusable page shell.

Performance

Demo / estimated metrics

No production performance budget artifacts are stored in-repo yet. The metrics below describe the architecture’s intended characteristics.

Resume routes

SSR-capable

Server render mode

Federated demo routes

Client-only

Isolated from SSR critical path

Contact delivery

EmailJS client SDK

No custom mail API

Lessons learned

What held up in practice, what did not, and what the next iteration should change.

What worked

  • Treating the host as a composition root clarifies what belongs in remotes vs shell
  • Soft-fail federation init keeps the resume site usable when remotes are down
  • OnPush standalone components keep feature folders easy to navigate

What didn't

  • Expecting one navigation label (“Projects”) to substitute for written case studies

What would be improved

  • Shared token package across host, remotes, and blog
  • Measured Lighthouse baselines committed per release
  • Expanded architecture explorer coverage for more remotes

What I learned

  • Portfolio credibility comes from explaining decisions and failure modes, not from stacking logos
  • SSR and micro-frontends can coexist if route boundaries are explicit

Future improvements

Next engineering increments if this surface continues to evolve.

  • Real API-backed demos behind federation
  • Authentication for gated project previews
  • Better remote caching and offline-friendly fallbacks
  • Expanded case-study corpus as new apps join the workspace

Technical stack

Compact summary for scanning.

Angular 20 Angular SSR Native Federation Tailwind CSS PrimeNG theme tokens EmailJS GSAP TypeScript

Code notes

Short excerpts that illustrate integration points discussed above.

Case-study route shape typescript
{
  path: 'projects',
  children: [
    { path: '', loadComponent: () => import('./projects-list/...') },
    { path: 'dashboard', loadChildren: () => loadDashboardRoutes() },
    { path: ':slug', loadComponent: () => import('./project-detail/...') },
  ],
}