← All changelog entries
April 28, 2026 · Feature

Stacks v0.5 — interactive stack builder, GitHub App write path, full registry browse

Ship the Stacks feature end-to-end: a public catalog of who's using what, OAuth-gated edit at /people/{handle}/stack/edit, a Svelte StackBuilder that buffers drafts in localStorage and publishes via direct commit through a GitHub App bot, and a registry-wide browse at /stacks/see-all-tools so members can read the catalog without having to add tools to their own stack first. Plus the home page reflows: the Dojo cards explainer moves to a new /about placeholder, leaving the home column uniform with the hero.

Authors
Michael Staton
Augmented with
Claude Code on Opus 4.7
Tags
#Stacks-Feature#Stack-Builder#Svelte-Islands#Tool-Registry#GitHub-App-Bot#OAuth#Markdown-as-Database#Public-Profiles#Design-System

Changelog — 2026-04-28 (02)

Stacks v0.5

This entry consolidates the full Stacks feature, which landed across several commits over the last 36 hours without its own changelog: b2789eb (initial read path), b42ef4f (write path + Svelte + GitHub App bot), af9d30e (tool registry seed + roster), a9da596 (header popdown + AlertDisplay), and the polish landing in this commit.

Why Care?

The Agentic VC Dojo’s launch webinar is in <2 days. The whole point of the dojo is to make it easy for venture professionals to share what they’re actually using — and to learn from each other’s setups. Until this feature, the site was read-only marketing copy. Now it’s a working community surface: members log in with GitHub, build their stack interactively, and a bot publishes a commit to lossless-group/fullstack-vc:main on submit. Vercel rebuilds in ~30 seconds and the public /people/{handle} profile updates. No database, no Auth0, no Notion sync — markdown files in a git repo all the way down, in line with the firm thesis that AI tools work best on markdown and JSON.

What Got Built

Read path (public, static)

  • /people/[handle] — per-participant profile rendering current / aspirational / abandoned stacks via ParticipantStackView. Headshot priority: explicit headshot: field → github_avatar.
  • /people — directory of members with public profiles.
  • /stacks — community-aggregate front door. Shows the most-adopted tools in current use (top 8) and members with public stacks.
  • /stacks/see-all-tools (new this commit) — flat alphabetical listing of every entry in the registry, with adoption-count annotations on tools that show up in someone’s current_stack. Front-door surfaces only the most-adopted handful; this page makes the whole registry browseable without having to add tools to your own stack first.
  • ToolCard, ParticipantCard, ParticipantStackView — display components, mode-aware semantic tokens, no JS. All cataloged in /design-system.

Tool registry seed

  • ~14 entries seeded so far, copy-pasted from the Lossless Obsidian Tooling/* vault (Astro, Svelte, Claude Code, Cursor, Windsurf, Ghostty, n8n, CrewAI, Hermes, Pi-Dev, Bolt, Ideogram, Obsidian, Jina, ImageKit, Fallow Tools).
  • Schema is a strict superset of the Obsidian Tooling frontmatter (Jina + OpenGraph fetch pipeline) so files paste in unchanged.

Tool schema fix (this commit)

The schema declared OG-prefixed names (og_image, og_favicon, url_aliases) but Obsidian source files use the bare names (image, favicon, aliases). .passthrough() masked the issue (files validated), but typed renderers querying data.og_image silently missed data stored under image, so e.g. Ghostty’s favicon never rendered. Fixed by:

  • Adding bare-name fields to the Zod schema as first-class typed properties (image, favicon, aliases, hero_image_url), plus typed entries for the fields that were passing through unannotated (docs_url, github_profile_url, github_repo_url, product_of, publish).
  • Renderer fallback in ToolCard.astro: og_screenshot_url ?? og_image ?? image ?? hero_image_url; og_favicon ?? favicon.
  • Same fallback in /api/tools.json.ts so the StackBuilder picker typeahead inherits favicons.

The schema is now an actual strict superset of the Obsidian Tooling frontmatter, as the spec promised.

Auth (Phase 1: GitHub OAuth, hand-rolled)

  • /api/auth/github/{login,callback} + /api/auth/logout — three endpoints, ~100 LOC, no Auth0 / Clerk / Lucia. Session is a jose-signed JWT in an HttpOnly cookie.
  • Roster match is by GitHub handle first, with email fallback for registrants not yet roster’d by handle (most webinar attendees are roster’d by email only).
  • LinkedIn OIDC scaffolded but not yet wired into the public flow.

Write path (the no-DB challenge, solved)

  • StackBuilder.svelte — the only interactive island on the site. Edits current_stack (v1 scope); aspirational + abandoned tiers are hand-edited in the participant .md for now. Buffers every keystroke to localStorage["stack-draft:{handle}"] so refresh / navigate / close-tab doesn’t lose work. 5-min idle threshold + visibility-loss event both trigger best-effort auto-save.
  • POST /api/stack/save — Zod validation, frontmatter merge that preserves UI-untouched fields (so editing the current stack doesn’t blow away your aspirational stack), retry-on-409 for SHA conflicts.
  • GitHub App bot auth — App ID + Installation ID + Private Key (PKCS#1 or PKCS#8, both handled via Node crypto.createPrivateKey() + jose SignJWT). Lazy env reads so HMR picks up .env changes without restart.
  • Direct commit to main with prefix data(stack): for filterable git history (git log --invert-grep "^data" filters the noise so feature commits stay readable). PR + auto-merge was the spec’s original Phase 1; direct-commit was chosen for v0.5 to ship inside the 36hr launch window. PR-with-auto-merge becomes a v0.6 hardening pass.
  • scripts/smoke-test-github-app.ts — direct READ + WRITE auth check, no dev-server needed. Saved hours when debugging the App ↔ Installation handshake.

Header surfaces (prev commit a9da596)

  • JumboPopdown__More — third sibling popdown alongside Groups and Projects. Static items (Stacks, People) under a “More” trigger.
  • AlertDisplay — inline announcement bar with primary→secondary gradient and an × dismiss button. Per-id session-scoped dismissals via sessionStorage. The home page now opens with one clarifying that “FullStack VC is NOT a VC.”
  • Top utility strip with an About link (above the main nav row, hidden on mobile).
  • Mobile drawer — gained Stacks, People, About entries.

Home / About page split (this commit)

The new Section__HowItWorks plus the home hero conflicted on column width — the section’s three-card explainer wanted ~1100px, the hero wanted max-w-4xl. Resolution: extract the cards into Section__DojoComponents (kept at 72rem) and ship it on a new /about placeholder page. The home page now reads as a single uniform column hero → Dojo intro + hierarchy diagram → “Learn more about the Dojo →” → footer. Section__HowItWorks accepts an optional hideMore prop so the about page can suppress the self-referencing link.

Design System catalog

Per the design-system maintenance motion, every component introduced lands in /design-system in the same change. Added in this batch: JumboPopdown__More, AlertDisplay, both with their own demo subpages.

Behavior

  • All read paths are fully static at build time. The only server endpoints are /api/auth/* and /api/stack/save.
  • Submit → commit → Vercel rebuild → live ≈ 30 seconds.
  • StackBuilder draft survives a tab close until the user explicitly clears localStorage.
  • Roster mismatch (logged-in GitHub user not on the Kauffman list) lands on a friendly /login/not-on-roster page rather than the edit screen.
  • The bot writes only ever start with data(...) so feature-commit history stays scannable.

Decisions Encoded That Revise the Original Spec

  • URL structure: canonical per-person path is /people/[handle] (not /stack/people/[handle]); aggregate front door is /stacks (plural). /stack/me is preserved as a backward-compat redirector.
  • Direct-commit chosen over PR + auto-merge for v0.5 launch velocity. Audit-trail concerns become a v0.6 hardening pass.
  • /stacks/see-all-tools added because the front-door page caps at the top 8, which made registry browsing impossible without first adding a tool to your own stack.

Open Work for v0.6

  • Aspirational + abandoned tier editing in StackBuilder (current_stack only today).
  • Free-text “add a tool not in registry” → save creates tools/{slug}.md placeholder + participant file in the same submit.
  • Per-tool detail page (/stacks/tools/[slug]) that renders the tool’s body markdown.
  • Full /stacks aggregate: heatmap (categories × tools, intensity = adoption count), leaderboards, sparklines from added: dates.
  • PR-with-auto-merge write path for audit-trail value.
  • Cohort views (/stack/cohorts/kauffman-[year]).
  • AI-assisted tool metadata enrichment (Browserless + LLM agent for tool YAML autogen from a URL).

Verification

  • pnpm build — clean across all routes, including /stacks/see-all-tools, /about, /design-system/components/alert-display, /design-system/components/jumbo-popdown-more.
  • Tool schema fix verified by inspecting Ghostty’s card on /stacks/see-all-tools — favicon now renders (was previously blank because the file uses favicon: not og_favicon:).
  • StackBuilder smoke-tested end-to-end: log in via GitHub OAuth → /people/mpstaton/stack/edit → drag a tool → wait 5 minutes → idle auto-save fires → page refresh → draft restored from localStorage → submit → commit lands on main with data(stack): prefix → Vercel rebuilds → public /people/mpstaton reflects the change.
  • scripts/smoke-test-github-app.ts confirms App credentials independently of the dev server.
Files modified (11)
  • sites/fullstack-vc/src/components/sections/Section__HowItWorks.astro
  • sites/fullstack-vc/src/components/sections/Section__DojoComponents.astro
  • sites/fullstack-vc/src/components/stack/ToolCard.astro
  • sites/fullstack-vc/src/content.config.ts
  • sites/fullstack-vc/src/pages/about/index.astro
  • sites/fullstack-vc/src/pages/api/tools.json.ts
  • sites/fullstack-vc/src/pages/design-system/components/alert-display.astro
  • sites/fullstack-vc/src/pages/design-system/components/jumbo-popdown-more.astro
  • sites/fullstack-vc/src/pages/design-system/index.astro
  • sites/fullstack-vc/src/pages/stacks/index.astro
  • sites/fullstack-vc/src/pages/stacks/see-all-tools.astro