This repository powers my public portfolio: a focused story around data engineering, AI-enabled workflow systems, and production platform work.
I am a Data Engineer who builds reliable data platforms first, then layers applied AI systems on top: RAG pipelines, multi-provider LLM routing, document intelligence, workflow automation, and backend services that can be tested, deployed, monitored, and reused.
The central story: I can own the full path from data foundation to AI-enabled product - ETL, SQL, CI/CD, APIs, retrieval, testing, observability, and measurable business impact.
Data Engineer building AI-enabled data platforms and workflow systems. I modernize ETL, CDC, SQL, CI/CD, and analytics foundations, then build applied AI layers on top: RAG pipelines, multi-provider LLM routing, document intelligence, FastAPI services, and production dashboards. My strongest value is owning the path from data foundation to AI-enabled product with measurable impact, testing, observability, and cost discipline.
This repository is the public source for my portfolio and career positioning, aligned to the roles I am targeting:
- Senior Data Engineer
- ML Engineer
- AI/ML Platform Engineer
The site highlights the kind of work I want to keep doing: production data and AI systems with strong engineering discipline, not one-off demos.
Deployment cycles compressed from 3 months to 14 days, CDC ETL reengineered from full reloads to incremental merge-upserts (30min to 8min runtime, -67% compute cost), and payroll-critical AAG database automation on Azure.
AI workflow automation platform: Chrome MV3 + FastAPI connecting job discovery, document tailoring, form-state management, LLM routing, and application tracking. 355 backend tests, 40+ endpoints, 11 ATS adapters, 9-page dashboard. Private deployment on Fly.io; public launch gated by tracked security fixes.
Document intelligence engine extracted from AutoApply AI. 190 tests, 4 distribution surfaces (PyPI, MCP server, Streamlit, CLI), and a strict no-fabrication constraint.
Direct-source job discovery across 130+ company career pages and 6 ATS platforms - data quality over aggregator noise.
- HTML
- CSS
- JavaScript
- GitHub Pages
The site is intentionally simple and fast: no framework, no build step, and no runtime dependencies.
index.html: site structure, portfolio sections, copy, and project cardsconfig.js: live status badge, terminal widget, metrics, recommendations, and social linkscontent/posts/: long-form writing and supporting portfolio content
Open index.html in a browser for a quick preview, or serve the repo with any lightweight static file server if you want local routing behavior to match GitHub Pages more closely.
The site uses a deliberate split: monogram "N" white-on-orange for the browser tab (16/32/48 px) and the actual headshot for the iOS home screen (apple-touch-icon.png), Android adaptive icon (favicon-512-maskable.png), and OpenGraph share card (og-image.jpg). All assets are deterministic, regenerated from a single source photo by scripts/snap-favicon.py.
# 1. Install pipeline deps (one-time)
pip install -r scripts/requirements.txt
# 2. Drop a fresh head-and-shoulders photo at scripts/_in/headshot-portrait.jpg
# (and optionally a full-body shot at scripts/_in/headshot-fullbody.jpg)
# 3. Regenerate everything
python scripts/snap-favicon.py
# 4. Bump the cache-bust query strings in index.html (search for "?v=2026-04-28")
# so existing browsers fetch the new files instead of stale cached copies.
# 5. Commit and pushThe script auto-detects the face via OpenCV's Haar cascade, applies a tight 1.18× face-bbox crop, renders the monogram from Inter Black (or Arial Bold fallback), and writes all six tab/iOS/Android/OG outputs deterministically. Source masters are downscaled to 1200 px long-edge and saved to static/originals/ so the repo stays light.
Status: v0.1.0-experimental. The well-known path
/.well-known/resume.jsonis not yet IANA-registered (RFC 8615 §3.1); for hardened use, vendor-prefix it.
Every developer with a portfolio hits the same pain: recruiter clicks a 6-month-old resume URL → 404 (file renamed); LinkedIn / cold-outreach links rot every update; CDNs cache aggressively so content changes don't propagate. This repo ships a small protocol that fixes all three.
The contract:
| Path | Purpose |
|---|---|
/static/resume.pdf |
Canonical PDF. Filename never changes; inbound links never break. PDF metadata (/Producer, /CreationDate, /ID) is sanitized at publish time to avoid toolchain fingerprinting. |
/.well-known/resume.json |
Discovery sidecar (RFC 8615). Tools probe <host>/.well-known/resume.json and read version + page count + last-updated date without parsing PDF bytes. |
/static/resume.schema.json |
JSON Schema (draft 2020-12) so adopters can validate their sidecars. |
<a href="/static/resume.pdf?v=<hash>"> |
Cache-bust uses content-derived version_hash. Stable URL, immediate invalidation on content change. |
Regenerate:
# 1. Drop your latest resume at scripts/_in/resume.pdf (gitignored)
# 2. Run — script auto-strips PDF metadata, writes sidecar+schema, and
# rewrites every /static/resume.pdf?v=<hash> in index.html in place.
python scripts/snap-resume.py
# 3. Commit and push.Self-test (11 assertions, stdlib only):
python scripts/snap-resume.py --self-testA GitHub Action (.github/workflows/resume-self-test.yml) runs the self-test, validates the sidecar against the schema, and warns if the cache-bust hash in index.html drifts from the sidecar.
CDN cache-bust compatibility:
| Host | Query-string ?v= cache-bust works out of the box? |
|---|---|
| GitHub Pages, Vercel | Yes |
| Cloudflare Pages, Netlify | No — query strings stripped from cache key by default; configure cache-level standard or hash the path instead |
| S3 + CloudFront | No — distribution must forward query strings |
For CDNs that strip query strings, hash-suffix the filename (/static/resume.<hash>.pdf) and 302 from the canonical URL.
Privacy notes:
- The sidecar's
last_updatedfield is intentionally date-only (not full ISO 8601 timestamp). Full timestamps broadcast job-search activity to anyone (including a current employer) probing/.well-known/resume.json. - Source PDFs in
scripts/_in/are gitignored by default; only the sanitized canonical copy ships.
Every flagship project card on this site uses an "impact strip" — 3-5 quantified-impact metrics displayed beneath the card title. Senior-engineer-credible (verifiable provenance via aria-describedby, AAA contrast, no font-swap CLS) and copy-pasteable into any portfolio (Hugo, Jekyll, Next.js, Astro, vanilla HTML).
See docs/impact-strip-pattern.md for the full spec, HTML/CSS, conventions ("numbers > tech labels", "3-5 stats per card", "every stat has defensible provenance"), and a11y/mobile checklist.
The reference implementation ships in index.html + styles.css. Tests in scripts/test-portfolio.py enforce the contract:
python scripts/test-portfolio.py --self-test17 assertions cover: pattern presence on every card, 3-5 stat range, semantic primitive (<dl>), aria-describedby linkage, no scrapped-project claims, no inline styles, JetBrains Mono loaded, mobile breakpoint at 600px, dark-mode + print blocks. Wired into CI (.github/workflows/portfolio-self-test.yml).
This site is deployed through GitHub Pages from the main branch.
- Email:
edara.narendranath@gmail.com - LinkedIn:
https://www.linkedin.com/in/narendranathe/ - GitHub:
https://github.com/narendranathe