Skip to content

asprouse/sprouse.dev

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

115 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

sprouse.dev

Source for sprouse.dev — Andrew Sprouse's interactive resume site.

It's also intended to be a forkable example of a small but production-grade modern stack: Astro 5 + React 19 + Tailwind v4 deployed to Cloudflare Workers, with an in-page chatbot powered by the Vercel AI SDK and a JD-driven tailored-CV flow. MIT-licensed — fork it freely.


What's here

Path What it is
andrew/ Everything that defines Andrew: cv.yml (structured CV), profile.md (narrative + framings), qa/ (chatbot corpus), leadership.md (CV's "How I run things" section), APPROACH.md (chatbot methodology). See andrew/README.md.
schemas/ JSON Schema (resume.schema.json) that validates andrew/cv.yml and codegens src/types/resume.ts
src/pages/ Routes. / is the landing card; /cv is the interactive CV; /cv/print is the printable version
src/components/ Astro components for layout + React islands (Chat.tsx, Positioning.tsx)
src/lib/ Resume helpers, BM25 retrieval, chat/tailor prompts
src/pages/api/ /api/chat (streaming Claude responses), /api/tailor (JD-driven CV re-rank)
public/ Static assets — favicon, OG image
wrangler.jsonc Cloudflare Workers config including the rate-limit bindings
astro.config.mjs Astro + Cloudflare adapter, sitemap, React aliasing for the Edge runtime

Architecture at a glance

┌─ andrew/
│   ├─ cv.yml ──────────── source of truth (validated against JSON Schema)
│   │  └─ src/types/resume.ts (auto-generated)
│   ├─ profile.md ──────── persona + voice rules + framings
│   ├─ qa/*.md ─────────── Q&A corpus (~150 entries across 6 categories)
│   ├─ leadership.md ──── distilled themes rendered as the "How I run things" section on /cv
│   └─ APPROACH.md ─────── methodology, rendered at /about-the-bot
│
├─ Astro routes
│   ├─ / ─ landing card
│   ├─ /cv ─ interactive CV (with ?lens=cto|principal|cofounder)
│   ├─ /cv/print ─ printable CV with tailor-from-JD dialog
│   └─ /about-the-bot ─ how the chatbot works
│
└─ React islands
    ├─ Chat.tsx ───────── floating chat with tools (scroll_to_role, expand_role, …)
    └─ Positioning.tsx ── unified lens picker + JD tailor dialog

Three positioning variants (src/lib/variants.ts) let the resume re-frame itself for different audiences. Each variant has its own headline, "open to" line, and SEO meta, but the experience/skills/education content is shared.

The tailor flow is a deliberate experiment: paste a JD, the model returns a structured patch (a positioning variant, a rewritten summary, per-role project ordering, hidden projects, and emphasized skills) which is applied via DOM mutation and encoded into the URL hash so it's shareable and survives reload. The model never rewrites project descriptions — it can only re-rank, hide, and re-emphasize what's already in andrew/cv.yml. That guarantees you can't accidentally generate experience you don't have.

Running locally

Requires Node 22+ and an Anthropic API key for the AI endpoints.

npm install
cp .dev.vars.example .dev.vars   # then put your real ANTHROPIC_API_KEY in it
npm run dev

Open http://localhost:4321.

What npm run does

Script What it does
dev Astro dev server
build Astro production build to dist/
preview Serve the built dist/ locally
format / format:check Prettier write / check
lint ESLint
typecheck astro check (types across .astro + .ts/.tsx)
validate:resume Validate andrew/cv.yml against schemas/resume.schema.json (Ajv)
gen:types Regenerate src/types/resume.ts from the JSON Schema
check All of the above (validate, format, lint, typecheck) — what CI runs

Deployment

Deployed to Cloudflare Workers via @astrojs/cloudflare (output: 'server'). Asset serving is configured through wrangler.jsonc + public/.assetsignore so the Worker bundle and the static asset upload don't fight.

To deploy your own fork:

  1. Create a Cloudflare Workers project (Pages will also work, but this repo is configured for Workers)
  2. Set ANTHROPIC_API_KEY as a Worker secret
  3. Update wrangler.jsonc:
    • Change name to your own
    • Change the three unsafe.bindings.namespace_id values — they're per-account globals, so collisions with mine would cross your traffic with mine
  4. wrangler deploy (or wire it to your CI of choice)

How the chatbot works

Methodology lives in andrew/APPROACH.md (also rendered at /about-the-bot on the live site). The short version:

  • Q&A corpus over RAG-over-blog. Andrew hand-wrote ~150 Q&A pairs across 6 categories. They're parsed at build time from andrew/qa/*.md.
  • BM25 retrieval, no vector DB. For 150 docs you don't need embeddings; src/lib/retrieval.ts is a from-scratch BM25 with the usual k1=1.5, b=0.75 parameters.
  • Persona-grounded. Top-5 retrieved Q&As + andrew/profile.md go into the system prompt. The model is told to answer as Andrew, drawing from these as ground truth.
  • Tools. The chat can scroll to a specific role, expand a collapsed retrospective entry, navigate between variant landing pages, or open /about-the-bot.

Forking this for your own résumé

Steps to make it yours (rough order):

  1. Replace andrew/cv.yml (the schema in schemas/resume.schema.json validates structure; npm run validate:resume will tell you what's missing)
  2. Run npm run gen:types to regenerate types from your schema if you extend it
  3. Replace andrew/profile.md with your persona + voice rules + framings
  4. Replace andrew/qa/*.md with your own Q&A entries — see andrew/APPROACH.md for the format. Empty answers are silently skipped, so you can stub headings as you go.
  5. Replace src/assets/portrait.jpg and src/assets/original-photo.jpeg with your own images (or remove src/components/Portrait.astro entirely)
  6. Regenerate the OG image: npm run gen:og (writes public/og.png)
  7. (Optional) Edit andrew/cv.yml variant taglines/openTo for your own positioning
  8. Edit astro.config.mjs site to your domain
  9. Update wrangler.jsonc name and rate-limit namespace_id values
  10. Run npm run check and fix what falls out

Stack

Documentation

License

MIT. The personal content (everything under andrew/, plus the portrait illustrations) describes me specifically — you obviously shouldn't ship that as-yours. The code is yours to fork.

About

No description, website, or topics provided.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors