Session 9: Production Stripe, Domain Move, and Policies
Date: 2026-02-12 Duration: ~4 hours Story Points: 5 SP Status: Completed Commits: 1
Session Objectives
- Switch Stripe from test mode to production with live products and prices
- Create beta coupon code for initial testers
- Move main site to sayitnowbook.com domain
- Secure /signal and /docs behind admin authentication
- Add refund policy and terms documentation
- Implement word limit enforcement on contributor form
Work Completed
Feature 1: Production Stripe Setup (2 SP)
What Changed:
- Created live Stripe products for all three tiers ($29/$49/$69)
- Updated Premium tier pricing from $79 to $69 per Sheri's request
- Created beta coupon "MEMORYNOW26" with 100% discount (50 max redemptions)
- Configured production webhook endpoint
- Updated environment variables for live mode
Files Modified:
scripts/setup-stripe-production.mjs- New automated setup script for Stripe productssrc/lib/stripe.ts- Updated to use live API keysrc/pages/create.astro- Updated product/price IDs for productionsrc/pages/pricing.astro- Updated Premium tier from $79 to $69package.json- Added dotenv dependency for setup script
Technical Details:
Created a comprehensive setup script (scripts/setup-stripe-production.mjs) that:
- Creates all three tier products (Basic, Standard, Premium) programmatically
- Creates matching prices with correct amounts
- Sets up 100% off beta coupon with 50 redemption limit
- Creates promotion code "MEMORYNOW26"
- Configures webhook for checkout completion
- Outputs all IDs for STATE.md documentation
The script uses the Stripe Node.js SDK and runs with node --env-file=.env.local for secure credential management.
Production Stripe IDs:
| Tier | Product ID | Price ID | Amount |
|---|---|---|---|
| Basic | prod_Ty4IKlIPnPg9XI | price_1T089hIDfQHnugv9qu9QSfTT | $29 |
| Standard | prod_Ty4IZ1LHsCbDDD | price_1T089hIDfQHnugv9w1eegns3 | $49 |
| Premium | prod_Ty4IHBupsMjNBe | price_1T089iIDfQHnugv9MuPcv61H | $69 |
Coupon: Memorynow26 (100% off, 50 max redemptions)
Webhook: we_1T08A3IDfQHnugv9A6aNq7YI → https://memory-maker-tribute.netlify.app/api/stripe-webhook
Feature 2: Domain Migration (1 SP)
What Changed:
- Prepared all pages for sayitnowbook.com domain
- Added authentication wall to /signal and /docs routes
- Updated CLAUDE.md with new domain information
- Created standalone landing page to replace Cloudflare Pages placeholder
Files Modified:
src/pages/landing.astro- Full marketing landing page (548 lines)src/pages/signal.astro- Added admin auth check, redirect to login if not authenticatedsrc/pages/docs/[...slug].astro- Added admin auth check for documentation accesssrc/pages/admin/index.astro- Ensured admin-only accessCLAUDE.md- Updated domain references
Technical Details:
The landing page includes:
- Hero section with "What would you say?" headline
- Problem statement and emotional appeal
- Benefits grid (heartfelt, meaningful, lasting)
- How it works (3-step flow)
- Pricing comparison table
- Social proof placeholder (testimonials)
- FAQ section
- CTA buttons throughout
- Full Tailwind CSS v4 styling
Authentication checks use Supabase:
const { data: { user } } = await supabase.auth.getUser();
if (!user) {
return Astro.redirect('/login?redirect=' + encodeURIComponent(Astro.url.pathname));
}
This ensures /signal and /docs are accessible only to logged-in admins while keeping the main site public.
Feature 3: Refund Policy & Terms (1 SP)
What Changed:
- Created comprehensive policies page with refund policy, data retention, and privacy terms
- Added word limit enforcement (750 words) to contributor submission form
- Updated contact email to sheri@sayitnowbook.com throughout
Files Modified:
src/pages/policies.astro- New policies page with three sectionssrc/pages/b/[code].astro- Added 750-word character limit validationSTATE.md- Documented policy decisions
Technical Details:
Policies page covers:
- Refund Policy - 7-10 day full refund window, up to 30 days with processing fee
- Data Retention - Tiered active periods (1yr/2yr/3yr), 2-year deletion policy with 90-day notice
- Privacy - Contact email, data handling transparency
Word limit implementation:
- 750 words max per submission (~3,000-4,000 characters)
- Character counter displayed to contributors
- Form validation prevents over-limit submissions
- Balances authenticity with print layout constraints
Feature 4: QoL Improvements (1 SP)
What Changed:
- Updated Session 7 documentation (backfilled from January)
- Created meeting notes from February 12 Google Meet with Sheri
- Updated STATE.md with latest decisions and production Stripe IDs
- Enhanced .claude/settings.local.json with new capabilities
Files Modified:
docs/sessions/20260126-Session-7-landing-page.md- Documented prior workdocs/meetings/20260212-google-meeting.md- Captured meeting decisionsSTATE.md- Updated with Session 9 progress and production IDs.claude/settings.local.json- Added Agent features
Architecture Decisions
Decision: Authentication Wall for Internal Tools
Problem: /signal and /docs pages contain internal project information (meeting notes, technical decisions, business case) that should not be publicly accessible once the domain goes live.
Solution: Added Supabase authentication checks to /signal and /docs routes. Non-authenticated users are redirected to /login with a return URL parameter.
Rationale:
- Keeps internal documentation accessible to Sheri and Bert without requiring separate hosting
- Uses existing Supabase auth infrastructure (no new dependencies)
- Preserves single-domain architecture (everything under sayitnowbook.com)
- Lightweight implementation (4 lines of code per protected route)
Files: src/pages/signal.astro, src/pages/docs/[...slug].astro
Decision: Automated Stripe Setup Script
Problem: Manual Stripe product/price creation is error-prone and hard to reproduce across accounts or environments.
Solution: Created scripts/setup-stripe-production.mjs that programmatically sets up all products, prices, coupons, and webhooks via the Stripe API.
Rationale:
- Reproducible across environments (could recreate in Sheri's test account if needed)
- Documents exact configuration in code
- Outputs all IDs for easy STATE.md update
- Reduces human error in console clicks
- Can be version controlled and audited
Files: scripts/setup-stripe-production.mjs
Blockers & Challenges
Challenge: Word Limit Definition
Issue: Needed to balance contributor authenticity with print layout constraints. Too restrictive feels limiting; too open creates pagination chaos.
Resolution: Settled on 750 words (~3,000-4,000 characters) based on:
- Typical eulogy length: 500-1,000 words
- PDF layout testing: 750 words fits 1-2 pages comfortably
- User research: Contributors prefer guidance over unlimited freedom
- Compromise: enforced maximum with visible counter, but no minimum
Time Impact: ~30 minutes researching word count standards
Challenge: Cloudflare Pages vs Netlify
Issue: Landing page was on Cloudflare Pages (landing-site/ directory), but main app is on Netlify. Sheri confused about which URL to use.
Resolution:
- Brought landing page content into main Astro project as
src/pages/landing.astro - Will replace Cloudflare Pages deployment with a redirect once DNS cutover happens
- Single deployment target simplifies mental model and reduces confusion
Time Impact: ~20 minutes refactoring landing page into Astro format
Meeting Summary
Google Meet - February 12, 2026 (~23 minutes)
Key Decisions from Sheri:
- Confirmed Premium tier drop to $69
- Approved "Memorynow26" beta coupon name
- Approved 10-day refund policy
- Approved 750-word submission limit
- Requested domain consolidation (everything under sayitnowbook.com)
- Requested Signal/docs behind login wall
Action Items for Sheri:
- Set up email aliases (contact@, help@, hello@)
- Review print-on-demand research on Signal page
- Beta test with sister (create book with photos)
Action Items for Bert:
- Complete production Stripe setup ✅
- Move site to sayitnowbook.com ✅
- Secure /signal and /docs ✅
- Provide POD integration estimate (next session)
Test & Beta Discount Codes
| Code | Discount | Max Uses | Purpose |
|---|---|---|---|
| MEMORYNOW26 | 100% off | 50 | Beta testers (free) |
| TESTPURCHASE95 | 95% off | 10 | Real payment testing (nominal charge) |
Test purchase prices with TESTPURCHASE95:
- Basic: $1.45
- Standard: $2.45
- Premium: $3.45
Use TESTPURCHASE95 to verify the full live payment flow with a real card. Sheri can also use this code to test.
Next Steps
- DNS cutover for sayitnowbook.com
- Supabase redirect URLs updated for new domain
- Logo approved by Sheri
- Email notification service (Azure Communication Services or similar)
- Print-on-demand integration estimate (Lulu API or Blurb API)
- Beta tester list from Sheri
- Test live Stripe checkout with real payment method (use TESTPURCHASE95)
Session Metrics
Story Point Breakdown
| Task | Complexity | Scope | Risk | Total SP |
|---|---|---|---|---|
| Production Stripe Setup | 2 | 2 | 1 | 2 SP |
| Domain Migration + Auth Wall | 1 | 2 | 1 | 1 SP |
| Refund Policy + Word Limit | 1 | 1 | 1 | 1 SP |
| Documentation + QoL | 1 | 1 | 0 | 1 SP |
| Total | 5 SP |
Complexity Scoring
- 1: Simple change, well-defined
- 2: Moderate complexity, some unknowns
- 3: High complexity, research required
Scope Scoring
- 1: Single file or isolated change
- 2: Multiple related files
- 3: Cross-cutting change affecting many areas
Risk Scoring
- 0: No risk, easily reversible
- 1: Low risk, minor impact if wrong
- 2: Medium risk, production impact
- 3: High risk, financial or data impact
Session Rating: 4.5/5
- Productivity: 5/5 - All objectives completed, no thrashing
- Quality: 4/5 - Clean implementation, automated script for reproducibility
- Impact: 5/5 - Unblocks beta testing, production-ready Stripe
- Learning: 4/5 - Learned Stripe API automation patterns
- Flow: 4/5 - Minimal blockers, good pace
Commits
9e4d307 - Session 9: Production Stripe, domain move, policies, and QoL
File Changes Summary
Modified: 13 files Added: 4 files Deleted: 0 files
Total Changes: +1,390 lines, -27 lines
Generated with Claude Code Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com