# stripe-convex: I shipped a Theo-compliant Stripe+Convex library — and never published the package

Source: https://www.michaelchurley.com/blog/stripe-convex-email-payments-theo-unpublished  
Published: 2026-03-20  
Author: Michael C. Hurley  
Tags: stripe-convex, stripe, convex, payments, subscriptions, cart, coupons, typescript, webhooks, theo, t3, saas, billing, michaelmonetized

![stripe-convex API surface: Pay, Cart, Checkout, Has, Convex exports](/blog/stripe-convex-email-payments-theo-unpublished/screenshots/api-surface.png)

## Who

I wanted one payment module I could drop into getat.me, hustlelaunch, and every other Convex SaaS instead of rewriting Stripe checkout + webhooks per repo.

Who it is for now: operators who bill by **email** before they finish auth binding; builders who want Convex `sc_*` tables and idempotent webhook logs without starting from Theo KV snippets; anyone who will check the registry before they trust a README badge.

## What

I built **stripe-convex**, public under **michaelmonetized/stripe-convex**, package **0.1.0**, MIT on paper. Peer deps: Convex ≥1, Stripe ≥14, React ≥18. Built with tsup + Bun. Exports: root types/components, `stripe-convex/convex`, `stripe-convex/components`.

React surface: `StripeConvexProvider`, `Pay`, compound `AddToCart` (with `CartItemPlan`), `Cart`, `Checkout`, `Has`. Hooks: `useStripeConvex`, `useCart`, `useCoupon`, `useCheckout`, `useHasAccess`.

![sc_* Convex schema tables](/blog/stripe-convex-email-payments-theo-unpublished/screenshots/schema-sc-tables.png)

Convex schema spreads six tables: `sc_customers`, `sc_payments`, `sc_subscriptions`, `sc_orders`, `sc_coupon_usage`, `sc_webhook_events`. Customers are indexed by **email**. `TRACKED_EVENTS` lists **19** Stripe types, checkout.session.completed through charge.refunded.

Theo lane (t3dotgg/stripe-recommendations): `getOrCreateStripeCustomer`, `syncCustomerData`, `createPortalSession`, brand/last4 on subscription payment method fields. Commit `77812a0` on 2026-02-06 is `feat: implement Theo's Stripe recommendations`. The compliance report file still opens with a summary table that marks several of those items Missing: stale header, live code.

![Theo helpers vs stale report header](/blog/stripe-convex-email-payments-theo-unpublished/screenshots/theo-compliance.png)

HEAD `22e099e` is PR **#13**: `AddToCart` gains `isSubscription` + `planId`; subscriptions default to direct checkout unless `addToCart` forces the cart path.

![AddToCart subscription compound API](/blog/stripe-convex-email-payments-theo-unpublished/screenshots/addtocart-subscription.png)

sitrep.md says **SHIPPED**. ROADMAP still has package publication unchecked. `.github/workflows/publish.yml` waits for a GitHub Release. Releases: **zero**. Public registry package stripe-convex: **404**. README still shows the version badge. LICENSE and README footer: **© Michael Shilman**. package.json author: Michael Hurley.

PENDING_ISSUES.md parks twelve real notes: Pay clearCart/addToCart race, unused onSuccess, Has returns null while loading, email checks only for `@`, duplicated formatPrice, cart not persisted, `as any` in syncCustomerData, and more.

## Where

Code: [github.com/michaelmonetized/stripe-convex](https://github.com/michaelmonetized/stripe-convex), **public**. No homepage / demo URL. Intended consumers named in ROADMAP: getat.me, hustlelaunch, other SaaS products. Revenue note in ROADMAP: **INDIRECT**.

![Badge vs registry 404](/blog/stripe-convex-email-payments-theo-unpublished/screenshots/registry-gap.png)

Local clone used for the pack: `/home/michael/Projects/_site-map/stripe-convex` on m1pro16. GitHub API shows **11** commits; that clone git log is squash-shaped to the single HEAD commit while the tree matches the library.

## When

**2026-02-04.** `1a3d250` Initial commit: stripe-convex payment package. Same day `0f5b81c` comprehensive docs.

**2026-02-06.** `c38c209` full type system + Convex functions. `f608a74` roadmap + license year. `77812a0` Theo recommendations.

**2026-02-11.** `635c61c` repo URLs + document all 19 webhook events.

**2026-02-21.** PR **#8** `cd172db`: dep conflicts, processRefund index, replace `v.any()`.

**2026-02-28.** PR **#11** CI/CD testing + publishing. Eight minutes later `c1e4a39`: remove GitHub Actions workflows; Vercel is our CI. `publish.yml` is still in the tree at HEAD.

**2026-03-01.** PR **#12** prep for registry publish.

**2026-03-20.** PR **#13** AddToCart subscription support. HEAD `22e099e`.

**2026-06-22.** GitHub `pushed_at` 22:20:53Z with no newer main commit beyond HEAD.

![Commit arc Feb to Mar 2026](/blog/stripe-convex-email-payments-theo-unpublished/screenshots/commit-arc.png)

## Why

Every monetized Convex app was going to need the same Stripe spine, and copying webhook handlers is how you get drift. Email-first customers match the products that take payment before they finish auth. Theo recommendations are a checklist I wanted encoded as exports, not a blog tab I reopen under pressure. The honest scar is the unpublished registry: badge, workflow, prep PR, sitrep SHIPPED, and a 404.

**Engagement Q:** When sitrep says SHIPPED and the registry returns 404, which status do you put in the blog title?
