aleemshahad.github.io/portfolio
Personal site for Aleem Shahzad — technical SEO, Python + CDP automation, and full-stack development. Static HTML/CSS/ESM, built with esbuild, published to GitHub Pages by GitHub Actions. No framework, no runtime CDN, no build server.
Cyber-terminal × sleek-minimal. Dark ground, one accent, zero decoration that isn't doing a job.
| Rule | Value |
|---|---|
| Ground | #04060a |
| Accent | #2fe08a — used once per viewport, never as a fill |
| Terminal amber | #e6b348 — inside terminal strings only |
| Radius | 0px everywhere. One radius, and it is none |
| Shadows | none. Depth comes from hairlines and the surface ladder |
| Type | Space Grotesk (display) + JetBrains Mono (UI), self-hosted subsets |
| Icons | inline SVG sprite. No icon font, no CDN |
| Nav | text only. No pill button, no CTA in the header |
| Footer | two columns, four links |
Motion is the site's thesis, not a decoration on top of it. The concept is
BUILD LOG: a persistent left rail stages the page as boot → proof → build → ship → deploy, GSAP + ScrollTrigger drive the choreography, and a
rAF canvas draws the node field in the hero. Every animated element is
authored so its finished state is plain CSS — motion only ever hides it,
and only when [data-motion="on"] is set. Reduced motion, a missing GSAP
bundle, or a failed boot all strip the flag and the page is simply done.
index.html the whole site: hero, metrics, capabilities, work, terminal, contact
blog.html the Writing index — drafted notes, honestly labelled as drafts
404.html inert error page (no scripts, no canvas, no fetch)
assets/css/ reset, tokens, base, layout, sections, motion — one @layer chain
assets/js/ ESM, one entry: core, nav, nodes, hero, counters, machines,
terminal, projects, motion
assets/fonts/ two subset woff2 files + @font-face
assets/vendor/ gsap + ScrollTrigger, vendored
assets/data/repos.json GitHub project snapshot (build splice + offline fallback)
assets/images/og.png Open Graph card, generated by scripts/make_assets.py
scripts/ build, serve, shot, verify, fetch_repos, render_projects, vendor
.github/workflows/ deploy.yml — build, verify, publish to Pages
Output filenames are identical to source filenames, so the HTML never needs
rewriting between source and dist/.
npm ci # esbuild + gsap
npm run serve # source at http://127.0.0.1:4173
npm run build # splice repos.json + bundle into dist/
npm run serve:dist # the real artifact
npm run verify # hard gate on dist/ — run before every push
npm run sync # refresh assets/data/repos.json from the GitHub APInpm run verify is not advisory. It fails the build on a third-party resource
load, a glyph the subset font cannot draw, Urdu/Arabic script inside a shipped
file, a broken local reference, a non-zero radius, an elevation shadow, a
missing canonical or favicon, or a leftover TODO.
Screenshots need a real browser and this repo is usually built inside proot,
where Chromium dies with SIGTRAP. scripts/shot.mjs therefore drives Firefox
ESR directly:
node scripts/shot.mjs /index.html /tmp/shot.png 1440 900 full --distModes: full (two passes, sized to the document height), reduce
(ui.prefersReducedMotion=1). The page reports JS errors and its scroll
height to POST /_diag, which serve.mjs prints.
Push to main. deploy.yml installs, refreshes the project snapshot from the
GitHub API, builds, runs verify, and publishes dist/ to GitHub Pages.
There is no commit-back step — the projects list is rebuilt on every deploy.
Requires Settings → Pages → Source: GitHub Actions.
Full detail in DEPLOYMENT.md.
- Headline metrics (
7+/100+/10M+) are supplied, not derived. - Project cards come from the live GitHub API; a card with no description says so specifically rather than inventing one.
- Draft articles are labelled
draft. Nothing is presented as published until it is. - Invented or placeholder copy is marked
[...]andverifyrefuses to ship it.
MIT. © Aleem Shahzad — Nexus Automation.