Remove the "For agencies" design-partner door (and its hero affordance) from the landing — single self-serve door

0051-remove-agency-design-partner-door-from-landing

decision read as Explain confidence verified status active 2026-06-18 owner forward-deployed-engineer
Reversibility
two-way door

DEC-0051 — Remove the "For agencies" design-partner door from the landing

Reversibility: two-way door — a content-model + markup + CSS removal on the DEC-0037 tailorable LandingContent template, revertible by restoring the GetStartedContent.partner field, the getStarted.partner entries, the .door--partner card + CSS, and the hero affordance. The kept design-partner backend (endpoint branch, test, emails) makes a revert cheap — the funnel still accepts design-partner; only the landing surface stopped offering it.

Context

A founder-direction request this session (2026-06-18): "Remove the 'For Agencies' section/form at the bottom of the Dossier landing page."

The landing's get-started beat shipped as two equal doors (DEC-0049): a self-serve / direct-adopter door (selfServe, re-homed from the cut "Run it yourself" feature) and an agency design-partner door (partner — the DEC-0023 channel). A quiet dual-audience hero affordance ("Running this for clients? For agencies →") routed agencies to that door early without gating. The founder asked for the "For Agencies" section/form gone entirely.

Decision

Remove the agency design-partner door and everything that existed solely to serve it; keep the shared funnel/transactional infrastructure (flag it as now-dead-but-retained rather than tearing out live email plumbing in a landing change).

Removed (exclusively the landing "For Agencies" surface):

  • LandingPage.svelte — the .door--partner article (Door 2: kicker "For agencies", CaptureForm type="design-partner") and the hero__audience affordance line. The get-started beat now renders the single self-serve door inside a new getstarted__doors--single wrapper.
  • schema.ts — dropped GetStartedContent.partner; the shape is now { head: SectionHead; selfServe: DoorContent }. DoorContent kept (its optional note field stays general; CaptureForm still supports a second input). Invariant comments updated.
  • content/landing/dossier.ts + examples/rba.ts — removed the getStarted.partner entries; changed the head lead from "Two ways in…" to a single-door framing ("Stand up your own loop."). Header comments updated.
  • styles/landing.css — removed .door--partner (base + hover/focus-within in both motion media queries), .hero__audience / .hero__audience-link, and the .js .hero__audience entrance rule; the partner-note stacking rule was generalized off .door--partner onto .capture-form__field + .capture-form__field (CaptureForm still supports note); added .getstarted__doors--single (single column, capped at 34rem, centered) so the lone door reads as deliberate; the .getstarted head comments updated.
  • .claude/skills/generate-landing/SKILL.md — the tailorable-slots table dropped getStarted.partner.* (would now generate a type error against the new schema); states plainly there is no getStarted.partner.

Kept, deliberately — shared infrastructure, NOT the landing section/form:

  • routes/api/subscribe/+server.ts — the CaptureType union, the design-partner branch, and its success message (DEC-0022 funnel). Nothing on the landing POSTs design-partner anymore, so the branch is dead-but-retained; it is the funnel/transactional layer, not the landing form.
  • test/subscribe.test.ts — the design-partner tag+note case (guards the still-live endpoint behavior).
  • emails/welcome-design-partner.md + emails/README.md — the live Buttondown transactional copy/wiring that was pushed via API. Ripping out live email infra is a separate, larger decision than removing a landing section.
  • CaptureForm.svelte — the shared, parametrized capture component (the self-serve door still mounts it); its type union member design-partner and optional note prop stay general.

This is a landing-surface decision, not a reversal of DEC-0023. Agencies remain the highest-leverage channel strategically; the public landing's dedicated agency door is gone, and the self-serve adopter is now the single way in. (DEC-0023's Review note already flagged the design-partner door for revisit as demand data arrives — this is that revisit, in the direction of fewer doors.)

Why

  • The founder asked for it. Direct founder direction on a GTM-facing surface; the FDE implements, does not relitigate the strategy.
  • The orphaned pieces were exclusively the agency door. The hero affordance existed only to route to the partner door; with the door gone it pointed nowhere. The schema field, content entries, and .door--partner CSS served nothing else.
  • One door reads cleaner than a half-empty 2-up grid. A single direct-adopter door under a centered head, capped + centered (--single), is a deliberate front door — not an orphaned column.
  • The backend stays honest by being kept, not half-removed. The design-partner endpoint/test/email plumbing is live (Buttondown push, DEC-0022) and shared funnel infrastructure; removing the landing door does not justify tearing out live transactional wiring in the same change. It is flagged here as dead-but-retained so a future cleanup (or a revert) is a known, cheap move.

Verification (build-proven, reproduced this session)

  • pnpm --filter @dossier/app check (svelte-kit sync + svelte-check) → 470 files, 0 errors, 0 warnings.
  • pnpm vitest run packages/app/test3 files / 27 tests pass (subscribe funnel incl. the retained design-partner case, RBA tailored-landing invariants, Dossier OKF-artifact round-trip).
  • vite build → both client + server environments built and the landing prerendered (.svelte-kit/output/prerendered/pages/index.html). Grepped the emitted HTML: zero occurrences of "For agencies" / "design-partner" / "door--partner" / "hero__audience" / "Become a design partner"; the self-serve door ("Run it yourself" / "Stand up your own loop"), the new getstarted__doors--single layout, and the surviving type="early-access" form are present; the hero ends at its two CTAs and flows straight into the OKF beat. (The build's final @sveltejs/adapter-vercel step fails with EPERM: operation not permitted, symlink — a Windows symlink-privilege limitation in the serverless-function packaging, AFTER the app has compiled + prerendered cleanly — unrelated to this change.)
  • No live code references the removed getStarted.partner / .hero__audience / .door--partner (grep clean; only removal-documenting comments remain).

Files (all under packages/app/, plus the skill)

  • src/lib/components/LandingPage.svelte — partner door + hero affordance removed; single-door --single layout.
  • src/lib/content/landing/schema.tsGetStartedContent.partner dropped; doc/invariant notes updated.
  • src/lib/content/landing/dossier.tsgetStarted.partner removed; single-door head lead.
  • src/lib/content/landing/examples/rba.tsgetStarted.partner removed; single-door head lead.
  • src/styles/landing.css.door--partner + .hero__audience rules removed; .getstarted__doors--single added; note-stacking generalized.
  • .claude/skills/generate-landing/SKILL.mdgetStarted.partner slot dropped.