Fri 10 Jul · Stripe + Supabase edge functions + webhook loop. Copy · paste · your app takes a real (test) payment by 5 PM.
ROLE You are a senior payments engineer working inside my Cowork Project. You have full context on my MVP (from Foundation Doc, PRD, and Day 4 S1 build). GOAL Prime this chat with everything needed to add Stripe payments today. Do NOT write code yet · just report state. CONTEXT · READ THESE 1. Foundation Doc + PRD in this Project's Knowledge 2. Project-Plan.md (features shipped so far) 3. Supabase MCP → list_tables · report which tables exist (esp. `subscriptions` if any) 4. Stripe MCP → get_stripe_account_info · fetch_stripe_resources (products, prices) 5. Existing edge functions → mcp list_edge_functions OUTPUT · 6 sections 1. What I'm selling (product name · one-time or subscription · price · currency) — derived from PRD 2. Stripe state (account exists yes/no · test mode active · products in test mode) 3. Supabase state (subscriptions table yes/no · RLS enabled) 4. Edge fn state (create-checkout-session · stripe-webhook · deployed yes/no) 5. Frontend state (Pricing page exists in Lovable · Success page · Cancel page) 6. Gaps to close today · ranked · with recommended next prompt (P01–P08) SELF-CHECK - Did I actually query the MCPs (Supabase + Stripe) or just guess? If guess → re-do with MCP. - Did I read Project-Plan.md? If not → read it. - Did I recommend the RIGHT next prompt? (If Stripe account doesn't exist → P01. If it exists but no products → P02. If both exist → P03.)
ROLE You are my Stripe onboarding coach. Talk me through account creation like I'm building an MVP · not a public company. GOAL Get me to a state where I have (a) a Stripe account (b) 2FA enabled (c) test mode confirmed active (d) API keys copied and stored safely. OUTPUT · a numbered 8-step walkthrough For each step: exact URL to visit · what to click · what to type · what I should see next. Steps to cover: 1. Sign up at stripe.com · what info to give (real vs "figure out later") 2. Business type · pick "Individual/Sole Prop" if unsure 3. Country + currency — stress that CANNOT be changed later 4. Enable 2FA · Settings → Team + Security (required for live mode later) 5. Confirm Test Mode toggle in top-right is ON 6. Developers → API keys · reveal + copy `pk_test_…` and `sk_test_…` 7. Where to store secret key safely (Supabase Edge Function env · never Lovable public var) 8. Bookmark 3 pages: Products · Webhooks · API keys SELF-CHECK - Did I tell them WHERE to put `sk_test_` (Supabase secrets · not Lovable)? - Did I flag the "country can't be changed" gotcha? - Did I skip anything they don't need for TEST mode? (Bank account · tax ID · full business address — all optional for test.)
price_ids you'll paste into P03. Handles one-time · monthly · yearly · trial · in one shot.ROLE You are a Stripe API operator. Use the Stripe MCP to create products + prices for my MVP. CONTEXT - My MVP: {{from Project-Plan.md · e.g. "AI journal app"}} - Pricing model I want: {{one-time / monthly sub / yearly sub / freemium}} - Price: {{$X}} in {{USD}} - If subscription: trial days? {{0 or 7 or 14}} GOAL Create in test mode via Stripe MCP: 1. One Product with name + description 2. All required Prices (monthly · yearly · one-time · whatever I picked) 3. Return the `price_id`s in a copy-able table STEPS 1. Confirm my pricing model by echoing it back 2. Call Stripe MCP `stripe_api_write` → create Product 3. Call Stripe MCP `stripe_api_write` → create each Price (with `recurring` param if sub) 4. If trial: include `trial_period_days` on the price 5. Return a Markdown table with: Price name · Amount · Interval · price_id 6. Update Project-Plan.md → Features → "Stripe products created" ✓ SELF-CHECK - Am I in test mode? (price_id should start with `price_1…test…` context) - Did I use the correct currency? (matches account default) - If sub → is `recurring.interval` set to "month" or "year"? - Did I return the price_ids in a copy-able format?
ROLE You are my senior payments engineer + designer. I want to ship Stripe Checkout end-to-end today. You will run a 5-stage gated loop and STOP at each gate until I approve. CONTEXT - Product: {{name}} · Price IDs from P02: {{price_monthly}} · {{price_yearly}} - Mode: subscription (or one-time · adjust accordingly) - Design tokens: light theme · indigo/violet gradient · Outfit + Instrument Serif + JetBrains Mono (or my brand tokens from Foundation Doc) - App stack: Lovable frontend · Supabase auth + DB + edge functions - Trial: {{0 or 7 or 14 days}} GOAL Ship: Pricing page → Checkout Session → Stripe → Success page → Webhook writes to `subscriptions` table → user has "active" status. ═══ STAGE 1 · HTML MOCKUP PREVIEW · IN CHAT · NOT LOVABLE ═══ Generate ONE self-contained .html file rendered inline in this chat with: - Pricing page (monthly · yearly toggle · CTA button) - Success page (with confetti or celebratory glass card) - Cancel page (empathetic · "no worries · try again") - Inline <style> using my design tokens - Hardcoded mock user + mock plan - All 3 pages as toggleable sections at top GATE 1: STOP. Ask: "Approve the mockup or want changes? Which page needs work?" ═══ STAGE 2 · SUPABASE + EDGE FUNCTIONS ═══ 2A · Supabase schema (via Supabase MCP `apply_migration`): - Create `subscriptions` table with columns: id · user_id · stripe_customer_id · stripe_subscription_id · stripe_price_id · status (trialing/active/past_due/cancelled) · current_period_end · cancel_at_period_end · created_at · updated_at - Enable RLS · policy: user reads own only · service role writes - Indexes on user_id + stripe_subscription_id 2B · Edge functions · TWO of them Ask me: "Ready to create both edge functions? (create-checkout-session + stripe-webhook)" If yes → walk me STEP-BY-STEP with EXACT: - File paths: `supabase/functions/create-checkout-session/index.ts` and `stripe-webhook/index.ts` - Full Deno TypeScript code for BOTH (CORS · auth check on Session · signature verify on webhook) - Exact URL to get webhook signing secret: https://dashboard.stripe.com/test/webhooks - Exact Supabase Dashboard path for secrets: Project → Edge Functions → Secrets - Secret names: STRIPE_SECRET_KEY · STRIPE_WEBHOOK_SECRET · SUPABASE_SERVICE_ROLE_KEY · SITE_URL - Deploy commands: `supabase functions deploy create-checkout-session` and `supabase functions deploy stripe-webhook --no-verify-jwt` (webhook MUST be no-verify-jwt) - Local test with Stripe CLI: `stripe listen --forward-to [url]` + `stripe trigger checkout.session.completed` - Common failure: "signature failed" → cause = req.json() instead of req.text() → fix 2C · Wire mockup to Lovable Full Lovable prompt with approved mockup HTML pasted at top · wires "Buy" button to invoke create-checkout-session · redirects to session.url · Success + Cancel pages read session_id from URL. GATE 2: STOP. Ask: "Migration applied? Both fns deployed? Signing secret added? Lovable wired?" ═══ STAGE 3A · LOVABLE QA REVIEW ═══ Give me a paste-ready Lovable prompt: "Review the Pricing / Success / Cancel pages for 10-star UX. Check: loading states on buy button · error voice if session fails · a11y (contrast, keyboard, screen reader) · mobile layout · empty state · first-10-seconds friction. Suggest 3 concrete improvements." GATE 3A: STOP. Ask: "What did Lovable suggest?" ═══ STAGE 3B · 3 PATHS TEST + HUMAN REVIEW ═══ Test scripts (already anticipated in 2B build · now execute): - HAPPY · card 4242 4242 4242 4242 · any future date · any CVC · confirm subscriptions row appears with status=active - EDGE · card 4000 0025 0000 3155 (3D Secure) · confirm 3DS challenge shows · confirm still lands correctly - BROKEN · card 4000 0000 0000 9995 (insufficient funds) · confirm error message is human · confirm no partial row Then HUMAN review checklist: - Does the flow FEEL like MY product · not Stripe's default? - Would I be embarrassed to show this to a stranger right now? - If my 60-year-old parent tried to buy · would they succeed? - Does the error copy sound like my brand voice · not "Error 500"? - Does the success page make me smile? GATE 3B: STOP. Ask: "3 paths result? Human concerns?" ═══ STAGE 4 · ITERATE ═══ Based on 3A + 3B feedback · give me ONE polish per page (Pricing · Success · Cancel · Error toast). Lovable prompts to implement each. GATE 4: STOP. Ask: "Ship or another iteration?" ═══ PLAN UPDATE ═══ Update Project-Plan.md: - Payments status: Mocked → Wired → Tested → SHIPPED - Note trial length · price IDs used · edge function names - Next: P05 (extensive test cards) OR P06 (customer portal) OR P07 (go-live check) NON-NEGOTIABLE - Stage 1 is ALWAYS HTML preview in chat first · NEVER Lovable first - Stage 2B ALWAYS gets my "yes" before writing edge fn code - Signing secret walkthrough ALWAYS includes exact URL + secret name - Stage 3B ALWAYS includes human-review (not just Lovable auto-review) - Every stage gates on my approval before proceeding
ROLE You are a payments debugger. Something's off between Stripe → my edge function → Supabase. Diagnose systematically. SYMPTOM {{describe: e.g. "payment succeeded in Stripe but no row in subscriptions table" · or "webhook returns 400" · or "signature failed"}} GOAL Find root cause · confirm fix · verify with a test event. DIAGNOSTIC · 6 checks 1. Stripe Dashboard → Developers → Events · did the event fire? What's the response code from my endpoint? 2. Supabase MCP get_logs for edge fn `stripe-webhook` last 20 min · what's the error? 3. Signature check: is the code using `req.text()` (correct) or `req.json()` (breaks signature)? 4. Env var check: STRIPE_WEBHOOK_SECRET matches the Stripe endpoint's signing secret? (These differ between endpoints — even test vs live · and between prod endpoint vs `stripe listen` local) 5. RLS check: is the fn using `SUPABASE_SERVICE_ROLE_KEY` (bypasses RLS · required) not `SUPABASE_ANON_KEY`? 6. Idempotency check: are you upserting on stripe_subscription_id · or blindly inserting (dupes)? OUTPUT - Root cause · 1 sentence - Exact code fix (diff format) - Test command: `stripe trigger checkout.session.completed` · then check subscriptions table appears SELF-CHECK - Did I actually query Stripe events + Supabase logs · or guess? - Did I confirm the fix WORKS (not just "should work")?
stripe listen · that CLI generated a DIFFERENT secret. Use the dashboard endpoint's secret for deployed code · CLI's secret for local dev.ROLE You are my QA lead for payments. Walk me through 6 test scenarios · check DB state after each · flag any gap. CONTEXT - My Pricing page URL: {{url}} - Subscriptions table in Supabase (via MCP) - Stripe test mode active TEST MATRIX · 6 scenarios For each: give me the card · what should happen · what DB state to check via Supabase MCP query. 1. HAPPY (subscription) ·4242 4242 4242 4242→ subscriptions row · status=active · stripe_subscription_id set 2. 3D SECURE ·4000 0025 0000 3155→ user sees 3DS challenge · after auth · row appears · status=active 3. 3DS AUTH FAILS ·4000 0000 0000 3220→ error page · no row in DB · no ghost customer in Stripe 4. DECLINE ·4000 0000 0000 9995(insufficient funds) → error toast with human copy · no row · Cancel page or retry 5. DISPUTE ·4000 0084 0000 1629→ charge succeeds initially · Stripe fires `charge.dispute.created` webhook later → verify: does my webhook handler catch this? (Bonus if yes · optional if no) 6. SUB CANCEL · use Stripe Dashboard → Customers → cancel a subscription → verify subscriptions row status flips to "cancelled" OUTPUT · results table | # | Scenario | Card | UI result | DB result | Pass/Fail | SELF-CHECK - Did I query Supabase MCP after each test · not just trust the UI? - Any scenario where UI + DB disagreed? (That's the interesting bug.) - Did I test on mobile too · not just desktop?
ROLE You are a churn-reduction engineer. Wire up Stripe Customer Portal + a polished cancellation flow. GOAL User can: 1. Click "Manage subscription" in-app → hit Stripe-hosted Customer Portal 2. Update payment method · view invoices · cancel · pause · switch plan 3. See a branded "we'd miss you" retention screen BEFORE the cancel button (Stripe supports this) 4. My webhook picks up any change and mirrors it in `subscriptions` table STEPS 1. Enable Customer Portal · Stripe Dashboard → Settings → Billing → Customer Portal · configure branding · enable "pause subscription" · enable "cancellation reasons" 2. Add a 3rd edge function: `create-portal-session` · takes stripe_customer_id · returns portal URL 3. Frontend: "Manage subscription" button in Settings · calls the edge fn · redirects to portal URL 4. Return URL: back to `/settings?portal=return` · show toast "changes saved · syncing…" 5. Webhook events to handle: - `customer.subscription.updated` (plan change · pause) - `customer.subscription.deleted` (canceled) - `invoice.paid` (extend period) - `invoice.payment_failed` (flag past_due · trigger email) 6. Retention polish: cancellation reason capture · offer 20% off next cycle · pause 1-3 months option 7. Update Project-Plan.md · Payments milestone → "Portal live" SELF-CHECK - Portal branding matches app (logo · colors · font · not raw Stripe)? - Cancellation reasons are captured in Stripe metadata (I can review later)? - Retention offer is TASTEFUL · not desperate?
ROLE You are my go-live checkpoint. I'm about to flip from test mode to live mode. Audit 12 things · block me if I'm not ready. CHECKLIST · 12 items 1. Stripe account fully activated (Settings → Account status) 2. Business info complete (address · tax ID if applicable) 3. Bank account added and verified (for payouts) 4. 2FA on Stripe login 5. Live webhook endpoint added in Dashboard → Webhooks · live signing secret in Supabase 6. Frontend env var swap: pk_test_ → pk_live_ 7. Edge fn env swap: STRIPE_SECRET_KEY test → live · STRIPE_WEBHOOK_SECRET updated 8. Stripe Tax enabled (or explicit decision to skip) 9. Email receipts enabled in Settings → Emails 10. Refund policy page linked from Pricing + Success page 11. Terms of Service + Privacy Policy pages exist 12. Dispute response strategy · who checks Stripe every 3 days? OUTPUT - Traffic light per item: 🟢 ready · 🟡 warning · 🔴 blocker - Blocker count · if > 0 · list exact fixes - If all green · give me the go-live playbook: 5 steps to flip · what to test first · what to watch for in first 24h SELF-CHECK - Did I query Stripe MCP for account status · not guess? - Did I confirm the LIVE webhook secret is different from test? - Did I flag the currency-can't-change gotcha (again)?
ROLE You are my product delivery lead. Update Project-Plan.md with everything shipped in S3. GOAL Reflect payments state accurately so Day 5–10 prompts don't re-ask questions or re-build features. UPDATE · these sections 1. Features Shipped · add: - Stripe products created (list price_ids) - subscriptions table + RLS - create-checkout-session edge fn - stripe-webhook edge fn - Pricing page · Success page · Cancel page (Lovable) - Customer Portal (if P06 shipped) 2. Status · Payments milestone: Mocked → Wired → Tested → SHIPPED (test mode) 3. Known gaps · anything from P05 that failed · anything deferred to Week 2 4. Next unlocks · - Day 5 can now polish real payment flow - Day 6 can deploy with confidence payments works - Day 8 Sellathlon can flip to live keys (run P07 first) 5. Metrics to track · first test payment timestamp · first live payment (target: Day 8) OUTPUT Show me the diff of Project-Plan.md before writing. Confirm with me before applying. SELF-CHECK - Did I actually read the current Project-Plan.md first? - Did I not overwrite non-payments sections? - Am I honest about what's SHIPPED vs what's DEFERRED?