Scope
Implements the “Clickable Levels of Detail” section (lines 54–68):
Level 1: Logo-only grid with crisp assets and alt text
Level 2: Expandable card (
LogoCardExpanded--Detail-1.astro) with progressive disclosure and a simple gate for sensitive fieldsLevel 3: Optional detail page route (
src/pages/portfolio/[slug].astro) with SEO fields
Files to Add/Update
Add:
src/components/basics/grids/grid-cards/LogoCardExpanded--Detail-1.astroProps:
{ brand, lightMode, darkMode, urlToPortfolioSite, blurbShortTxt?, team?: TeamMember[], sensitive?: SensitiveFields? }Behavior: expands/collapses in place; supports col-span-2/row-span-2 when expanded
Accessibility: focus management, Escape to close, aria-controls/expanded
Gate: small passcode input; if matches
import.meta.env.PUBLIC_PORTFOLIO_PASSCODE, reveals sensitive fields (placeholder now)
Update:
src/components/basics/grids/grid-cards/LogoOnlyContainer.astroAdd an “Expand” affordance (button) that toggles rendering of
LogoCardExpanded--Detail-1.astrobelow the logoMaintain external link on the card while keeping the expand control separate and accessible
Update:
src/components/basics/grids/LogoGrid--LogoOnly.astroAccept optional flags:
{ expandable?: boolean, expandSpan?: { cols?: number; rows?: number } }When expandable, mount expanded card with Tailwind classes
col-span-2/row-span-2per props
Add:
src/pages/portfolio/[slug].astro(optional, scaffold)Generates
slugfromconventionalName/officialNameSections: Summary, Metrics (gated placeholder), Team, Links
SEO: title/description/OG image passed from layout
Add:
src/utils/slug.tsSimple slugifier to normalize names to URL-safe slugs
Data & Mapping
Existing JSON records remain source of truth (lpcommits/directs)
Mapping adds optional
teamandblurbShortTxtwhen presentSensitive fields are not embedded in static HTML; for Phase 1 we show placeholders after gate. Phase 2 will fetch private data on demand.
UI Details
Level 1: logo grid
Use existing
ThemeImage.astrofor light/dark assetsAlt text from
conventionalName || officialName
Level 2: expanded card
Shows blurb, team list (name, role, image, LinkedIn)
Expand control: keyboard focusable,
aria-expandedbound to state;EscclosesExpanded card increases grid footprint (
col-span-2orrow-span-2) for readabilityPasscode gate: input + button; toggles a
unlockedstate; no secret is exposed server-side in Phase 1
Level 3: detail page
Route uses slug; loads matching record and renders sections
SEO: set unique title/description/OG
Accessibility & Performance
Keyboard: Enter/Space expand; Escape collapse; focus returned to trigger
Screen readers: labels and state announced via
aria-expandedPerformance: SVG preferred; lazy-load raster assets
Acceptance Criteria
Grid renders crisp logos with correct alt text
Clicking “Expand” opens in-place details with blurb/team; “Close” and
EsccollapseExpanded card spans multiple grid units when configured
Passcode input reveals gated placeholders; no sensitive data in prerendered HTML
Detail page route compiles; basic content loads by slug
Next Steps (after approval)
Implement
LogoCardExpanded--Detail-1.astroWire expand/collapse in
LogoOnlyContainer.astroandLogoGrid--LogoOnly.astroAdd
slug.tsand scaffold[slug].astroValidate with
pnpm build; check/portfoliointeractionsIterate on gate and private-data fetch in Phase 2