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.
- Personal Website (Angular host + SSR)
- Native Federation manifest
- Angular Dashboard remote
- Next.js Blog (external link)
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 metricsNo 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.
Code notes
Short excerpts that illustrate integration points discussed above.
{
path: 'projects',
children: [
{ path: '', loadComponent: () => import('./projects-list/...') },
{ path: 'dashboard', loadChildren: () => loadDashboardRoutes() },
{ path: ':slug', loadComponent: () => import('./project-detail/...') },
],
}