Dev Log
About: real headshots for Shane/Kelli/Ryan + corrected LinkedIn URLs
What was done
- Three new portraits added to
src/assets/team/:shane.png,kelli.png,ryan.png(originals from.tmp/plans/about/). Astro’s image pipeline auto-generates optimized.webpvariants at the requested sizes. /about/team grid (src/pages/about/index.astro): added aportraitImagesslug→ImageMetadata map keyed by team slug. The.team-portraitcircle now renders an<Image>(160px requested, lazy loaded) when the slug has an entry; falls back to initials otherwise. Addedoverflow: hiddenandobject-fit: coverso the image fills the circle without a halo./about/{slug}/bio pages (src/pages/about/[slug].astro): sameportraitImagesmap. Bio hero portrait renders an<Image>(400px requested, eager loaded since it’s above-the-fold) when present; falls back to initials.aria-hiddentoggles tofalsewhen an image renders (so the alt text is exposed) andtruewhen initials render (purely decorative).- Placeholder aside copy updated from “Headshots are placeholders in this prototype. Real photography to follow before public launch.” to “Headshots for the rest of the team are placeholders…” — accurate now that 3 of 14 are real.
- LinkedIn URL corrections in
src/data/team.ts:- Kelli:
linkedin.com/in/kelli-black-6b0379141→linkedin.com/in/kelli-j-black - Ryan:
linkedin.com/in/varde→linkedin.com/in/ryan-t-benson
- Kelli:
Why
Real photography arriving incrementally; first 3 leadership headshots ready. LinkedIn URLs were outdated/wrong (Ryan’s was pointing to an unrelated profile slug varde).
Pattern for future headshots
When the next person’s headshot arrives:
- Drop the file into
src/assets/team/{slug}.png(or .jpg / .webp) - Add an import + entry in BOTH page files (
src/pages/about/index.astroandsrc/pages/about/[slug].astro):import nextPersonImg from "../../assets/team/{slug}.png"; const portraitImages: Record<string, ImageMetadata> = { // ...existing... "{slug}": nextPersonImg, }; - When all 14 are real, simplify by removing the conditional and the initials fallback in both files; also delete the placeholder aside on /about/.
The two duplicate maps are intentional — they let each page tree-shake imports independently rather than forcing both pages to bundle every portrait.
Files affected
Created
src/assets/team/shane.pngsrc/assets/team/kelli.pngsrc/assets/team/ryan.pngsrc/content/devlog/2026-04-23-about-headshots-and-linkedin-fixes.md(this entry)
Modified
src/data/team.ts— Kelli + Ryan LinkedIn URLs correctedsrc/pages/about/index.astro— Image import block, portraitImages map, conditional render in team grid, .team-portrait img CSS, aside copysrc/pages/about/[slug].astro— Image import block, portraitImages map, conditional render in bio hero, .portrait img CSS
Verification
- Build verify: 20/20 PASS
- Team grid per-person check (node parse of
dist/about/index.html): Shane Leavitt, Kelli Black, Ryan Benson render as IMAGE; other 11 team members render as initials - LinkedIn URLs in compiled HTML:
dist/about/kelli-black/index.html→linkedin.com/in/kelli-j-black/;dist/about/ryan-benson/index.html→linkedin.com/in/ryan-t-benson/ - Optimized webp assets generated under
dist/_astro/:shane.*.webp,kelli.*.webp,ryan.*.webp(multiple variants for retina + intrinsic sizes)