This website - the living workshop
v0.5 focuses on privacy-first contact sharing (auth-gated QR with single-use tokens), a refined proposal PDF (clean typography, ToC, mission page, circular avatar), routing/CSP fixes, and UX polish across the CV header and downloads.
Why
I want one home for my research notes, projects, and writing—lightweight, fast, and easy to grow. This site is a “living workshop” where I ship in public and keep improving the craft.
Stack Overview
- Core: Next.js 15 (App Router), MDX from the filesystem, Tailwind, shadcn/ui.
- Content tooling:
remark-gfm
,rehype-slug
, autolinked headings. - PDF:
pdf-lib
(portable; no headless browser), with WinAnsi-safe text. - Contact sharing: server-rendered QR (SVG) with HMAC tokens, enforced by Edge middleware.
- State & limits: serverless key–value store over HTTP for single-use tokens and gentle rate limits.
- Hosting: Vercel.
What changed in v0.5
Private contact card (QR-first; NFC later)
I tightened the sharing flow so I control who sees my contact details and when.
- /card is private, and /card/qr is challenge-gated (simple PIN → versioned cookie).
- Every QR encodes a short-lived, signed token. The vCard endpoint requires the token (cookies are ignored).
- Tokens are single-use and gently rate-limited to discourage scraping. A second scan returns 410 Gone.
- The code auto-rotates (refreshes) before expiry.
- The QR now points directly to the vCard download, and the vCard includes my avatar inline.
- If I unlock from
/card/qr
, the flow sends me back to that page after the PIN using a safenext
parameter. - I also fixed form submissions under my Content Security Policy and optionally canonicalize the host to avoid apex/
www
mismatches.
Note on ops: In public posts I keep security at a high level. I don’t publish environment details; those live in my private runbook.
Proposal PDF (executive-ready)
The proposal export moved to a portable generator so it works the same everywhere and looks good.
- Dedicated Mission & Executive Summary page with my statement.
- Experience renders time / scope / metrics / highlights with dividers and breathing room.
- Skills follow experience in clean two columns.
- Table of Contents with dotted leaders and page numbers.
- Supports a circular avatar (prefers a transparent PNG; falls back to JPG).
- Consistent 1″ margins, subtle rules, and tidy type scale; text is sanitized so there are no encoding surprises.
CV & UI polish
- The Download actions show a clear “Preparing…” busy state.
- The QR page scales nicely on mobile and stays visually centered.
Routing & content fixes
- Middleware is Edge-safe (WebCrypto) and typed.
- MDX page rendering is stabilized (server serialization + component map).
- I removed brittle build flags and simplified the deployment config.
Highlights (implementation notes)
Endpoints & files
- Middleware: gated
/card
+/card/qr
; token-only check on the vCard endpoint; optional host canonicalization. - Tokens: compact HMAC SHA-256 payloads (base64url) with short TTL and a nonce for one-time use.
- KV store: small helpers to “burn” tokens on first use and throttle downloads per IP.
- Contact: PIN → versioned cookie, safe
next
redirect, avatar embedded in the vCard. - QR: server-generated SVG with an auto-refresh interval.
- Proposal PDF: mission, ToC, experience, and skills; page numbers and consistent spacing.
- CV header: busy state during downloads.
Security posture (high-level)
- Private contact area with a simple unlock, single-use links, and short TTL.
- Rate-limits on sensitive endpoints.
- Instant revoke by rotating a secret or bumping a version value in config.
Before / After (at a glance)
- Before: QR could be reached without a fresh challenge; PDF export was brittle; the cover layout felt cramped; experience read like a wall of text.
- After: QR is private, rotating, and single-use; the proposal PDF is clean and portable with a ToC; the cover and contact row have breathing room; experience is broken up with dividers and spacing.
Known issues / Next up
- Add NFC / Apple Wallet pass that opens the same tokenized flow.
- Optional Exec one-pager PDF theme (summary-first).
- Brand accents for PDFs (color, link styling), clickable email/URL.
- Consider moving the KV usage to a native provider in my host for simpler ops.
- Site search (
/search?q=
) andSearchAction
JSON-LD.
Changelog
- v0.5 (2025-09-10): Private contact flow (auth-gated QR, single-use tokens, rate-limits), proposal PDF with ToC/mission/clean typography, circular avatar support, safer redirects & CSP, CV download busy state, QR layout fixes.
- v0.4 (2025-09-05): CV overhaul (Exec Summary, scope/metrics, mobile collapse), robust PDF export with live canvas capture, scrim refinement, sidebar spacing, export/import fixes.
- v0.3 (2025-09-03): Centered reading layout with column-blur scrim; descriptive sidebar grids + mobile Filters sheet; Blog/Research/Projects overhauled; Next 15 fixes; stricter taxonomy.
- v0.2 (2025-08-28): Trust pages, mobile command palette, JSON-LD, lazy-loading, a11y touches.