Case study
Career Portal
The site you are reading: a zero-dependency vanilla-JS PWA with 90+ automated tests, Lighthouse 95+, and $0/month hosting on Cloudflare Pages.
- Vanilla JS (ES6)
- CSS custom properties
- PWA + Service Worker
- node --test
- Cloudflare Pages
- Azure Functions
Context
Portfolio sites tend to be either a static template (forgettable) or a framework app with 200 KB+ of JavaScript and a build pipeline. I wanted the site itself to be the demonstration: fast, accessible, offline-capable, and readable source — with no framework tax.
Architecture
There is no build step. HTML pages import ES modules straight from /js/, styling is plain CSS with design tokens as custom properties, and everything ships as-is to Cloudflare Pages. The contact form posts to an Azure Function; the rest is static.
The first version's hook was a working terminal emulator with 28 commands. This redesign retired it for a content-first layout with a Ctrl+K command palette — the terminal was fun, but it hid the actual work behind a help command. One convention survived every version: every dynamic string passes through escapeHtml() before any innerHTML assignment.
Key decisions & tradeoffs
- Zero build step. Files ship exactly as written — no bundler, no transpiler. The cost: no tree-shaking, so every module is hand-curated for size.
- Native test runner. The suite runs on
node --test— no Jest, no Mocha. GitHub Actions runs it on every push and blocks the Cloudflare Pages deploy on any failure. - Accessibility as a gate, not a feature. Skip links, landmark structure, full keyboard navigation, and
prefers-reduced-motionhonored by every animation (WCAG 2.1). - Manually versioned service worker. The PWA cache uses a fetch-first strategy with an offline fallback page; the cache name must be bumped by hand on asset changes. I have forgotten twice — the stale-cache bug is subtle both times.
- Terminal → palette. The 28-command terminal buried the content, so v2 keeps the personality in a Ctrl+K palette and puts the case studies first. Try it.
Measured outcomes
- Shipped dependencies
- 0
- npm packages in the bundle
- Automated tests
- 90+
- native Node runner
- Lighthouse
- 95+
- performance & accessibility
- Hosting cost
- $0/mo
- Cloudflare Pages free tier