sahin.io

All skills and agents

page-vc-portfolios

The five "portfolio in a firm-inspired style" pages (a16z, Sequoia, Accel, Founders Fund, YC) on sahin.io/angel-investments, which show the whole public portfolio as a design homage. Use when building, rebuilding or changing any of them, their shared company list, filters, featured carousel or homage line.

Source file
.claude/skills/page-vc-portfolios/SKILL.md
Routes covered
/a16z/sequoia/accel/founders-fund/yc

VC-style portfolio pages

Routes

URL React kind
https://sahin.io/angel-investments/a16z a16z
https://sahin.io/angel-investments/sequoia sequoia
https://sahin.io/angel-investments/accel accel
https://sahin.io/angel-investments/founders-fund foundersFund
https://sahin.io/angel-investments/yc yc
  • Manifest kind reactPage, 5 routes, all index. They are SINGLE_PAGES entries in server/reactPageRoutes.ts; createSeoRouteManifest() adds them from reactRouteSpecsFor().
  • Render path: React. renderReactShellPage() in server/seoRouteManifest.ts writes the static shell (head, breadcrumb, minimal header); scripts/generate-static.ts calls reactPageForRoute() (server/publicReactPages.ts) and the React page replaces the body.
  • They are not menu pages; breadcrumb names come from content/pages/page-crumbs.yaml.

Files

  • Shared props: server/publicPages/styledPortfolio.ts: buildStyledPortfolioProps(ctx) (every company: name, href, logo, market, market group, status, stage, stage group, year founded, one-liner, rank by company value), featuredIndices(), alphabeticalMarkets(), homageLine(), countsLine(), FIRM_META_SHAPE, stageGroupOf().
  • Per-firm builders (only copy plus featured picks): server/publicPages/a16z.ts, sequoia.ts, accel.ts, foundersFund.ts, yc.ts, each exporting <firm>PageMeta and build<Firm>Props.
  • Components: client/src/publicPages/A16zPage.tsx, SequoiaPage.tsx, AccelPage.tsx, FoundersFundPage.tsx, YcPage.tsx; shared parts in styledPortfolioParts.tsx (Dropdown, Logo, SORTS, STATUS_FILTERS, applyFilters, sortCompanies, useCarousel, sharedCopy) and styledPortfolioTypes.ts (StyledCompany, StyledPortfolioProps).
  • Types: a16zTypes.ts, sequoiaTypes.ts, accelTypes.ts, foundersFundTypes.ts, ycTypes.ts; registered in client/src/publicPages/types.ts, components.client.ts, components.server.ts.
  • CSS: client/src/publicPages/styles/{a16z,sequoia,accel,foundersFund,yc}.css, imported from client/src/index.css.
  • Copy: content/pages/{a16z,sequoia,accel,founders-fund,yc}.yaml (meta title and description, firm, firmFullName, heading, labels, filters) and the shared content/pages/styled-portfolio.yaml (section names, stage names, homage, counts, years). Browser copy via client/src/generated/copy/pages/... (node scripts/sync-site-copy-module.mjs).
  • Data: ctx.companies (public portfolio, sorted by company value) and the enriched research file read by loadEnrichedRecords() (stage, year founded).

Sections on the page

  1. Firm-styled top bar and heading (heading from the firm YAML), with the visible homage line (homageLine(firmFullName): a design homage, not affiliated).
  2. Intro counts line (countsLine: companies, markets, companies with a sourced company value of $1B or more via sourcedValueCount).
  3. Featured strip or carousel. a16z: exits (public or acquired) then the 12 largest live companies; Sequoia: top 20 by company value plus a note; the others pick in their own builder.
  4. Filters (sort, market/focus, stage, status, year), search, grid/list toggle.
  5. Company grid or list linking to each https://sahin.io/angel-investments/{company} page.

SEO

  • Title and description: meta in the firm YAML (exported as <firm>PageMeta), titles at most 60 characters (fitPageTitle).
  • Canonical https://sahin.io/angel-investments/<path>; JSON-LD from buildPageGraph() with kind reactPage (CollectionPage plus BreadcrumbList). In the sitemap and llms files (indexable).
  • Query targeting is checked by server/keyword-[redacted].test.ts; do not let these pages target queries other pages own.

Rules

  • Never use a firm's logo or wordmark. Copy layout, type and imagery; put Sahin's own mark in that slot (owner rule "No VC firm logos in themes"; see server/vc-theme-management.test.ts).
  • Every page must carry the homage line; never imply affiliation with the firm.
  • Counts come from the portfolio (portfolio-counts-single-source skill); no hard-coded numbers.
  • Company values only from the sourced dataset (sourcedValueCount, sourced()); never summed.
  • No private deal data (private-data-boundary skill). Research text that trips the public content policy is dropped in styledPortfolio.ts.
  • All words in YAML (page-content-yaml skill).

Tests

  • server/public-link-graph.test.ts (the five paths are in the link graph).
  • server/public-company-value.test.ts (sourced company values only).
  • server/public-content-policy.test.ts, server/content-in-yaml.test.ts.
  • server/vc-theme-management.test.ts (no firm names or logos as wordmarks in the theme views).
  • server/seo-route-manifest.test.ts, server/route-indexing.test.ts.

Rebuild from scratch

  1. Write content/pages/styled-portfolio.yaml (shared words) and one content/pages/<firm>.yaml with meta, firm, firmFullName, heading and the firm's labels. Add the breadcrumb name to content/pages/page-crumbs.yaml. Run node scripts/sync-site-copy-module.mjs.
  2. Implement buildStyledPortfolioProps(ctx) in server/publicPages/styledPortfolio.ts.
  3. Per firm, add server/publicPages/<firm>.ts: load copy with loadPageContent(<file>, SHAPE), spread the shared props, set firm, heading, disclaimer: homageLine(...), intro: countsLine(props), featured: featuredIndices(...).
  4. Add <firm>Types.ts, the PublicReactPage union member in types.ts, the component, and the lazy and server entries in components.client.ts / components.server.ts (see new-react-page).
  5. Add styles/<firm>.css and import it from client/src/index.css (see theme-system).
  6. Register { path, meta, page } in SINGLE_PAGES in server/reactPageRoutes.ts.
  7. deploy-gate, then ui-before-after (desktop and mobile), then ship-to-production.