Skip to content

feat(pricing): add Office Hours mentoring tier ($99, 90-min 1:1) - #743

Merged
TortoiseWolfe merged 1 commit into
mainfrom
feat/office-hours-pricing-tier
Aug 15, 2026
Merged

feat(pricing): add Office Hours mentoring tier ($99, 90-min 1:1)#743
TortoiseWolfe merged 1 commit into
mainfrom
feat/office-hours-pricing-tier

Conversation

@TortoiseWolfe

Copy link
Copy Markdown
Owner

Adds the paid Office Hours tier the launch blog already promises (public/blog/ride-the-open-source-city.md: "live Office Hours ... the recording is yours to keep"). Signed off: $99, one-time, 90-minute live 1:1, paid checkout, in the Developers lane next to Field Study.

Changes (3 files)

  • migration (20251006_complete_monolithic_setup.sql) — new prd-office-hours product row: amount 9900, one_time, active, metadata {} (charged in full). One-time SKUs charge from an inline amount, so no Stripe price object is required.
  • src/app/pricing/page.tsx — a card in the DEVELOPERS array with empty href, so the button routes to /checkout?sku=prd-office-hours like the other one-time SKUs.
  • src/config/__tests__/payment-ceiling.test.ts — catalog count 10 → 11 (guard message + toHaveLength). The new row is active and $99, so priciest ($3,500 svc-site), cheapest-≥-min, ceiling, and inactive-count (3) all still hold.

Verified

  • payment-ceiling unit test: 5/5 pass
  • tsc --noEmit: clean
  • prettier + eslint (pre-commit): clean

Deploy note

The card is static and ships on merge. Checkout resolves the SKU against the live Supabase products table: a fresh DB (CI, local reset) gets prd-office-hours from the migration, but the live prod DB needs the row inserted or the button shows "That package is not available". The e2e pricing-links spec covers it once the DB is seeded from the migration.

Adds the paid "Office Hours" tier the launch blog already promises
(public/blog/ride-the-open-source-city.md: "live Office Hours ... the
recording is yours to keep"). One-time $99 checkout SKU in the Developers
lane, next to Field Study.

- seed row prd-office-hours in the monolithic products migration
  (amount 9900, one_time, active, metadata {} = charged in full)
- card in the DEVELOPERS array on /pricing (empty href -> /checkout?sku=)
- bump payment-ceiling.test.ts catalog count 10 -> 11 (guard + assertion)

One-time SKUs charge from an inline amount, so no Stripe price object is
needed. Verified: payment-ceiling unit test (5/5), tsc --noEmit, prettier.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@TortoiseWolfe
TortoiseWolfe merged commit 0fbaa88 into main Aug 15, 2026
36 of 39 checks passed
@TortoiseWolfe
TortoiseWolfe deleted the feat/office-hours-pricing-tier branch August 15, 2026 01:35
TortoiseWolfe added a commit that referenced this pull request Aug 15, 2026
… no way forward (#748)

Recovered from a worktree that was about to be deleted. Four items were genuinely unshipped;
the rest of what was sitting there was superseded and has been dropped rather than carried
along.

WHAT LANDS

  - `public/chatt-diorama-og.jpg` (new) and `src/app/chatt/page.tsx` pointing at it. The
    card advertised `chatt-atlas-og.jpg` — still a valid image, but the diorama shot is what
    the route became once walk mode shipped (#651, #702-#706, #718, #723).
  - `public/blog/playable-city-chattanooga.md` gains an update note linking forward to
    "ride the open source city". That post is live; the brainstorm that preceded it had no
    pointer to where the idea actually went.
  - `docs/social/ride-the-open-source-city-facebook.md`, the social copy for that post.

`src/lib/blog/blog-data.json` is TRACKED and derived, so it is regenerated here with
`pnpm run generate:blog` rather than carried over from the worktree — the stale copy there
predated three merges. Diff is 2 lines: the cross-link.

WHAT WAS DROPPED, and why, so nobody goes looking for it

  - The pricing page and the monolithic migration both carried `prd-office-hours` at
    **$49 / 60-minute**. #743 shipped that product at **$99**, page and seed together. The
    worktree copy was an earlier draft; taking it would have silently halved a live price.
  - `public/blog/ride-the-open-source-city.md` and its two images are already in main.
  - Nothing else in that worktree differed from main.

The branch it sat on was 0 commits ahead of main, so none of this was recoverable by looking
at commits — it existed only as uncommitted working-tree state, which is why it survived
this long unnoticed.

ONE JUDGEMENT CALL WORTH A SECOND OPINION: `/chatt` renders the Cesium atlas by default and
the diorama is the `?diorama` opt-in (#297), so an OG card showing the diorama advertises the
opt-in rather than the default. It was staged deliberately, and the walk arc is the reason
anyone visits, so it ships — but say the word and it reverts to one line.

Co-authored-by: TurtleWolfe <TurtleWolfe@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant