Case study
Calm Sheets
Calm Sheets was running Google Ads with no idea what visitors did after the click. We built them the ability to watch every visit — every click, every scroll, every hesitation. They went from seeing their ad spend to seeing their customers.
Brand naming and domain acquisition
Landing page design with multiple iteration rounds
Customer research strategy with Python automation
SEO research and 90-day rebuild playbook
They could see their ad spend but nothing about the people the ads brought in. No way to know which ads actually worked, which pages lost visitors, or which words on the site were pulling their weight. The biggest line item in their business, and they were flying blind.
We built custom tracking at every step of the visitor's journey — from the ad they saw, to the page they landed on, to the moment they hit checkout. Every click, scroll, and hesitation gets captured. We also turned on screen recordings so the team can literally watch people shop: where they pause, where they leave, what catches their eye. Every visit is now visible.
Now they can watch every visitor. For the first time, they can see which ads actually earn customers, which pages lose people, and where shoppers hesitate before buying. They have the evidence they were missing — now the work of testing fixes and proving what works can begin with real data instead of guesses.
Session timeline
The complete record.
Rate limit /api/track (60/min) and dashboard login (10/15min brute-force protection)\n- Email format + 254-char length validation on magic link and refund flows\n- Input truncation (500 chars) on all tracking string fields\n- CORS scoped to calmsheets.com on /api/track (was wildcard)\n- Replaced SELECT * with named columns in 8 queries across 5 files\n- Added Strict-Transport-Security header\n- All 178 unit tests passing, deployed to production
Live audio notifications via Web Audio API: warm triangle-wave two-note chime for new visitors (660-880Hz, distinct from Spark's brighter sine-wave), A-C#-E-A arpeggio for purchases · Alert banner UX: tap-to-enable, pulsing indicator, localStorage persistence, preview sound on activation
Dashboard UX port from Spark Academy: center-aligned filter buttons, moved page selector to own section with title/description, friendly date format, renamed tabs Overview→Visitors / Funnel→Page Activity, removed redundant text from Funnel Overview and Page Comparison · Added Visitor Actions section with engagement stats: Button Taps, Started Checkout, Opened an FAQ, Tried Breathing Tool, Started Meditation (all hidden if 0)
Ported all 12 funnel tab UX improvements from Spark Academy: friendly section names, Visited Page/Reached X labels, stacked bar layout, delta inside/count outside, simpler column headers, < 1s display, friendlier descriptions, scroll depth labels, full section depth with PAGE_SECTIONS, All Pages vs Single Page view, tab persistence via URL hash · Added friendly page names to dropdown and comparison table (Night-Before Panicker not /flight/tomorrow/)
Fixed dashboard tab persistence: auto-refresh now preserves active tab via URL hash instead of resetting to Overview\n- Fixed funnel API 500 error: var hoisting bug where _funnelDays was undefined during hash restore, plus hardened days param parsing\n- Sorted funnel page dropdown dynamically by session count from D1\n- Removed pricing from 18 early CTAs across all 6 landing pages (hero + social proof + after What's Inside) to reduce early bounce — visitors now see content before price\n- Added owner exclusion: ?notrack URL sets permanent cookie, tracker skips, API drops beacons server-side\n- Added Chesterfield MO to GA4 city exclusion for both report and realtime queries\n- Improved funnel API error reporting with stack traces and client-side response body\n- Updated funnel-tracker-blueprint.md v1.0 → v1.1 with all lessons learned
Built 3 Google Ads API scripts: keyword report (metrics, search terms, impression share, QS), optimizer (batch pause/negative keywords), scheduler (ad schedules + day-of-week bid mods)\n- Applied live Google Ads changes: 43 negative keywords, paused QS 1 keyword, shifted 4 campaigns to 5pm-midnight, added day-of-week bid modifiers (Thu/Sat +20%, Tue -20%)\n- Built funnel tracking system: client-side JS tracker (Intersection Observer, sendBeacon), /api/track POST endpoint, D1 funnel_sessions schema\n- Built dashboard Funnel tab: funnel chart, section engagement table, drop-off report, page comparison, scroll depth distribution, date range + page filters\n- Edited 5 landing pages: added data-section attributes (10 per page), Microsoft Clarity snippet, tracker script, rebranded Reddit r/fearofflying to Anxious Flyers Community\n- Deep research on US flight traffic by day of week to inform bid strategy\n- Wrote reusable funnel tracker blueprint for other projects\n- Fixed dashboard Funnel tab JS bug (escaped apostrophe in template literal)
Researched anchor/strikethrough pricing UX best practices for digital products (conversion impact, visual patterns, ethical considerations)\n- Implemented ~~$49~~ $34 strikethrough pricing with 'Save 31%' badge across all 6 landing pages (/flight/, /tomorrow/, /prepare/, /understand/, /fear-of-flying/, /anxiety/)\n- Added reusable CSS classes (.price-anchor, .price-save-badge) with dark mode support\n- Updated pricing cards, section headers, all CTA buttons, and FAQ copy\n- Verified rendering at 375px, 768px, 1440px in light + dark mode via Playwright\n- Fixed dark mode contrast for anchor price and badge elements\n- JSON-LD schema and Stripe checkout unchanged — display-only change\n- Committed and deployed to production (calmsheets.com)
API security hardening: rate limiting on 5 public endpoints (checkout, verify-magic-link, confirm-refund, refresh-auth, download-pdf) via shared rate-limit.js helper\n- Fixed SQL injection risk in x-scheduled.js ORDER BY clause (status allowlist)\n- Added input validation allowlists to x-replies.js and x-scheduled.js\n- Hardened ADMIN_TOKEN auth on 3 admin endpoints (fail closed with 503 if not configured)\n- Created global API security rule (~/.claude/rules/common/api-security.md)\n- 41 new unit tests across 4 new + 5 existing test files (178 total, all passing)\n- Full production deployment: Cloudflare Pages + health worker + X reply bot
Diagnosed failing synthetic test: upgrade-rejects-missing-token probe was removed from local code during single-tier consolidation (commit 307c9f6) but health worker was never redeployed\n- Redeployed health worker to remove stale probe\n- Full production health audit: all 5 ad landing pages, checkout validation, auth gating, homepage, health worker — all healthy and stable for ad spend
Consolidated two-tier pricing (Standard $29 / Pro $34) to single-tier product at $34 — 48 files changed, 2,279 lines removed · Updated all 6 landing pages: single pricing card, 16-item feature list with guides/interactive tools separator
Full rewrite of /flight/ landing page for organic/direct/X-bot traffic conversion\n- Strategic debate on page positioning: analyzed traffic sources (X bot 6x/day, organic, returning visitors, direct), mapped all 3 personas, adapted PAS framework (lighter agitation, heavier solution)\n- New H1: 'Flight anxiety doesn't have to win' — broad catch-all vs scenario-specific\n- Added 8 new sections: problem validation, persona self-sort (in-page anchors), light agitation with success stories, solution positioning, methodology proof (4 credibility cards), objection handling (4 objections), price anchoring (therapy/courses comparison), FAQ with FAQPage structured data (8 questions)\n- 6 CTAs throughout page, all pointing to #pricing with 14-day refund signals\n- Preserved all functional code: checkout forms, breathing demo JS, meditation player JS, gclid capture, analytics, dark mode, form-guard\n- Kept free articles section as upsell funnel per Stephen's direction\n- Centered all quote cards for visual alignment\n- Committed and pushed to production
Audited all 6 free SEO articles against paid product — found severe overlap giving away the store (breathing techniques in 4/6 articles, complete packing lists, crew scripts, sound guides, timelines) · Rewrote all 6 articles as What/Why teasers: removed all How content (techniques, scripts, lists, action plans), kept education and validation, added soft CTAs bridging to paid guide
Added 'Reddit' prefix to all bare subreddit references (r/fearofflying, r/flyinganxiety) across 6 hand-authored landing pages and 3 content markdown source files\n- Rebuilt guide HTML from updated markdown via build-content.js\n- Verified no duplicate 'Reddit Reddit' or doubled subreddit names\n- Deployed to production (calmsheets.com)
Full PAS conversion rewrite of /flight/understand/ landing page (Logic Seeker persona)\n- Read & analyzed 11 strategy/context files (copywriting guide, Reddit research, Google Ads campaigns, keywords, ad copy, personas, brand docs)\n- Keyword & audience analysis: 26 keywords across 3 ad groups (Turbulence, Airplane Sounds, Claustrophobia & Control)\n- New sections: Agitate, Solution, Try It Now, Objection Handling, FAQ with FAQPage schema, price anchoring\n- Removed exit ramps: Free Articles (6 cards) and Related Articles (3 cards) sections\n- Extracted interactive demos into dedicated Try It Now section with conversion framing\n- Added Product and FAQPage structured data for SEO\n- 5 CTAs placed at emotional peaks (up from 2)\n- Fixed Reddit attribution (r/ → Reddit r/), centered quote cards, removed redundant login link\n- Deployed to production via Cloudflare Pages
Full /flight/prepare/ landing page rewrite for conversion optimization (Avoidant Traveler campaign)\n- PAS framework: added Problem, Agitate, Solution, Methodology Proof, Objection Handling, FAQ sections\n- Keyword & audience analysis across 28 keywords in 3 ad groups (Preparation, Returning Flyer, Scared but Must Travel)\n- Read 11 strategy/context files to inform copy decisions\n- Added FAQPage + Product structured data, 6 CTAs, price anchoring (-300 therapy vs )\n- Removed 2 article exit ramp sections, updated nav links\n- Copy fix: added Reddit prefix to all subreddit references\n- Style fix: center-aligned quote card content\n- Deployed to production on main branch
Full conversion rewrite of /flight/tomorrow/ landing page for Night-Before Panicker persona\n- Read & synthesized 11 strategy/context docs (copywriting guide, Reddit research, Google Ads, keywords, ad copy, personas, brand, site arch, reference rewrite)\n- Keyword & audience analysis: 33 keywords across 3 ad groups, persona mapping, emotional state assessment\n- PAS framework: Hero, Problem, Solution, Agitate, What's Inside, Try It Now, Methodology Proof, Objection Handling, Pricing, FAQ, Final CTA\n- Added 6 CTAs (was ~2), price anchoring (-300 therapy vs ), 3 inline objection handlers\n- Added mobile hamburger menu, FAQ section with FAQPage schema, Product structured data, Twitter meta tags\n- Removed exit ramps (Related Articles section, standalone permission section)\n- Preserved all functional JS (breathing demo, meditation player, checkout forms, gclid, time-aware label, dark mode)\n- Post-write tweaks: centered quotes, Reddit prefix on attributions, removed duplicate login link\n- Committed and deployed to production via Cloudflare Pages
Full conversion rewrite of /flight/anxiety/ landing page using PAS framework\n- Read 11 context files (strategy, copywriting guide, Reddit research, Google Ads config, personas, reference rewrite)\n- Keyword/audience analysis for Flight Anxiety campaign (22 keywords, 4 ad groups)\n- Added: agitation section, objection handling, price anchoring, FAQ with FAQPage schema, 5 CTAs\n- Removed: exit ramps (articles section, community voices, stat ticker, nav links to non-conversion sections)\n- Preserved all functional code (checkout forms, breathing demo JS, meditation JS, analytics, dark mode)\n- Deployed to production on calmsheets.com
UI polish on /fear-of-flying/ rewrite: fixed interactive tools grid alignment (lg→xl breakpoint), removed duplicate login link from pricing section, stacked price anchoring lines vertically, fixed spacing · Verified price anchoring accuracy: researched real fear-of-flying course prices, updated from $500+ to $295+ (SOAR program reference)
Audited codebase for auth cookie (30d), magic link uses (5x), and magic link expiration (24h) settings across all code paths · Audited all user-facing copy explaining auth system (emails, success page, FAQ, login, privacy, terms)
Conducted full conversion research: analyzed Reddit deep analysis (100+ posts), audited all 6 free articles + article hub, reviewed /fear-of-flying/ landing page, and researched online copywriting best practices (PAS framework, CXL, CopyHackers, Unbounce, MECLABS) · Analyzed Google Ads keyword data for Fear of Flying campaign (3 ad groups, 27 keywords) to map searcher intent to landing page copy
Full Google Ads account audit: analyzed 138 keywords + 195 search terms, identified waste, cannibalization, wrong-intent keywords · Built and deployed /flight/anxiety/ landing page targeting anxiety keyword cluster (validation-first hook, Reddit quotes, full pricing/checkout)
Full-screen mobile nav overlay (Spark Academy style) with hamburger-to-X animation, body scroll lock, ESC/click-outside dismiss, dark mode support across all 4 landing pages\n- Standardized nav links: Free Articles + Already Purchased on all landing pages (desktop + mobile)\n- Added 6-card Free Articles sections to /prepare/ and /understand/ landing pages\n- Fixed dark mode article cards blending into background (lighter bg + subtle border in dark-mode.css)\n- Audited and pushed uncommitted changes: bot relocation to bots/, health worker hardening, Google Ads campaign expansion\n- Redeployed health worker to production (external cron trigger, fewer false alarms, Google Ads API v20)
Analyzed Google Ads keyword 'flight anxiety' across campaigns; recommended /fear-of-flying/ as best landing page for broad head terms · Updated project CLAUDE.md with /fear-of-flying/ in site architecture and What's Built sections
Analyzed Google Ads keyword data (Avoidant Traveler campaign), identified budget drains and recommended pausing broad informational ad groups · Built /flight/fear-of-flying/ landing page: keyword-optimized for 'fear of flying' head terms, Reddit-sourced community quotes, persona routing section, Pro tool demos (breathing timer + meditation player), strategic article links, full pricing section
Fixed synthetic test false failures: removed 5 page-load probes that hit Cloudflare's ~10s Worker-to-Pages subrequest timeout limit · Kept all 12 API probes that test actual server-side logic (auth, checkout, webhooks, refunds, etc.)
Diagnosed health worker cron failure (Cloudflare cron silently stopped after D1 timeout errors) · Migrated health worker scheduling from Cloudflare cron trigger to cron-job.org (external cron, every 5 min)
Auto-hide System Health & Synthetic Tests dashboard cards when all healthy\n- Fix xFollowers undefined crash (null vs undefined check)\n- X follower count tracking: bot records hourly snapshots to D1, dashboard displays count + change\n- Fix OAuth 1.0a signing to include query params in signature base string\n- Deep research: 40+ X accounts to follow across 8 categories (saved to strategy/x-accounts-to-follow.md)\n- Hashtag monitoring bot: searches 10 flight anxiety hashtags, Gemini filters for real people, auto-replies with helpful tips (max 3/hour)\n- D1 migration for x_hashtag_tweets table\n- Social media expansion analysis: evaluated 10 platforms, ranked by fit/effort/ROI (Pinterest #1, TikTok #2)\n- Updated CLAUDE.md with hashtag monitoring docs + social media expansion plan
Analyzed 14 Ahrefs keyword research screenshots and extracted 61 new keywords for Google Ads campaigns\n- Organized new keywords into existing ad groups (B, C, F, H) and 4 new ad groups (J-M)\n- Wrote full RSA ad copy (12 headlines + 4 descriptions each) for Ad Groups J (Fear of Flying Head Terms), K (Flight Anxiety General), L (Coping & Calming Tips), M (First Time & Travel Anxiety)\n- Updated google-ads-keyword-list.md: 56→104 keywords, 9→13 ad groups, with comma-delimited export\n- Updated google-ads-copy.md with all 4 new ad group copy blocks\n- Advised on landing page URL change for Ad Group C (/flight/tomorrow → /flight/)
Created Google Ads keyword list document (56 keywords across 9 ad groups, comma-delimited) · Diagnosed and fixed Google Ads API v19→v20 sunset issue in dashboard and health worker (silently broken for weeks)
Fixed Google Search Console 'HTTPS not evaluated' issue for www.calmsheets.com\n- Added CNAME DNS record (www → calmsheets.com) via Cloudflare API\n- Created Page Rule for 301 redirect (www → apex domain)\n- Verified redirect working with HTTP/2 301 response
Diagnosed X API 403: app was standalone, moved to Pay Per Use package in X Developer Portal\n- Reset 2 failed scheduled posts, triggered manually, first tweets posted to @CalmSheets\n- Reorganized x-reply-bot/ into bots/x-reply-bot/ directory structure (mirrors site/ pattern)\n- Updated all relative paths in load-calendar.js and wrangler.toml\n- Created bots/CLAUDE.md with full bot documentation\n- Updated root CLAUDE.md with X Reply Bot section (worker URL, secrets, deploy commands, D1 tables)
Auto-hide System Health dashboard card when all systems healthy (only shows on warnings/failures)\n- Auto-hide Synthetic Tests card when all probes passing or no results yet\n- Fix xFollowers undefined crash: !== null didn't catch undefined, changed to != null\n- Updated local dev dashboard password in .dev.vars\n- Committed and pushed to production
Removed '— The full experience' from Pro buy button on /flight/prepare · Full audit of 'Standard' usage across 50+ files (215+ occurrences catalogued)
Built 4 new Google Ads campaigns: Avoidant Traveler East/West and Logic Seeker East/West\n- 9 ad groups across Campaign 2 (Returning Flyer, Preparation, Terrified but Must Travel) and Campaign 3 (Know Its Safe But Still Scared, Sounds and Turbulence, Body Panic Somatic)\n- Created account-level negative keyword list with 125+ terms applied to all campaigns\n- Set up account-level assets: 6 callouts, sitelinks, structured snippet\n- Configured timezone-split scheduling: Avoidant Traveler evening hours, Logic Seeker all-day\n- Audited all 6 campaigns for presence-only targeting, budgets, and settings consistency\n- Removed duplicate campaign-level sitelinks, cleaned up assets
Added 15 strategy file entries + data pipeline diagram + research tool commands to root CLAUDE.md · Updated CLAUDE.md: status to LIVE, real tech stack, 15 'What's Built' items, removed stale ad strategy section
Replaced male + female demo audio MP3s on all 4 landing pages, purged CDN cache\n- Fixed scroll/refresh: removed sessionStorage hack, clear URL hash after anchor clicks so refresh goes to top\n- Right-aligned mobile nav dropdown under hamburger on all 4 landing pages\n- Removed hamburger menu from /tomorrow/ page\n- Fixed success page copy: 24h magic link expiry (was 90 days), 30-day cookie, landing page re-entry\n- Go-live: set all 5 Stripe live secrets (keys, webhook, 3 price IDs), created live webhook endpoint, redeployed Pages + health worker\n- Dashboard launch date floor (GA4 from 2026-04-01, Stripe from 07:10 UTC) to zero out test data\n- Added Open Your Guide CTA swap to /prepare/, /tomorrow/, /understand/ via HTMLRewriter Pages Functions\n- Fixed dashboard Purchases hint text to match actual code behavior\n- Updated health worker with launch timestamp to prevent re-syncing test transactions\n- Multiple Cloudflare cache purges for audio files and dashboard
Fix mobile 'Processing...' button stuck after Stripe checkout (form-guard.js pageshow reset)\n- Fix bfcache scroll jump on refresh after checkout across all 4 landing pages\n- Fix duplicate 'Pro interactive tools' divider text on desktop/tablet (/tomorrow/)\n- Remove bookmark/save-page toast popup from /guide/\n- Hide dark/light toggle on mobile for /success page\n- Upgrade modal scrolls to Interactive Pro Tools section instead of reloading\n- Rename 'Interactive Tools' to 'Interactive Pro Tools Unlocked'
Diagnosed & fixed phantom D1 database divergence: wrangler dev --d1 flag created separate databases from CLI, causing 609 ghost purchases on dashboard. Removed flags, consolidated to single DB from wrangler.toml · Audited all project docs, memory files, and schema for stale/outdated info
Replaced small top-of-screen upgrade success toast with full-screen centered celebration modal\n- Modal features checkmark badge, 'You're Pro now!' headline, and 'Continue to Your Guide' button\n- Button reloads page fresh to top so user sees Pro badge immediately
Added X follower count card to admin dashboard with change pill (green for gains, red for losses, gray for no change)\n- Created D1 migration (011-x-follower-snapshots.sql) for tracking follower counts over time\n- Built API endpoint (POST/GET /api/x-followers) with dashboard cookie + admin token auth\n- Follower change compares today's latest vs yesterday's latest snapshot\n- Deployed migration to production D1 database
Fix webhook-rejects-no-signature synthetic probe (401→400 status alignment) · Fix post-upgrade scroll position — land at top of guide after Standard→Pro upgrade
Audited all 33 claimed bug fixes from post-testing session against actual codebase (23 bugs + 4 test updates + infra actions)\n- Found 3 issues: /prepare breathing bullets missed, dashboard refresh 5min vs 60s spec, email tier test gap\n- Fixed /prepare breathing section from div to ul/li matching other 3 landing pages\n- Changed dashboard auto-refresh from 5 minutes to 60 seconds per original spec\n- Added 2 unit tests verifying Pro/Standard tier labels in magic link email subject and body\n- Deployed audit fixes to production (154 tests passing)
Fixed 23 bugs from post-testing audit across all 4 tiers (launch blockers through polish)\n- Magic link security: rate limit 3/15min, 5-use + 24h expiry, anti-enumeration\n- Styled Pro gate page with $5 upgrade CTA (replaced plain-text 403)\n- Meditation play button fix for mobile browsers (iOS Safari audio loading)\n- Feature list consistency: all 4 landing pages now match /flight/ (11 items)\n- Degraded mode: visible countdown timer with auto-restart loop\n- Health worker: degraded mode enter/exit event logging to D1\n- Email updates: tier labels in subject/body, 90-day→24-hour expiry copy\n- Refund email: removed Scripts & Phrases from Pro upsell (Standard feature)\n- Dashboard auto-refresh every 5 minutes for non-realtime sections\n- Scroll position reset on navigation, custom 404 page, refund button color fix\n- Landing page copy: breathing techniques bulleted, timer count 4→2, Kit→Guide\n- Synthetic test status codes fixed (302→303), PDF header spacing + rebuild\n- D1 migration (use_count), 2x health worker deploy, Cloudflare Pages deploy\n- Test suite: 4 tests updated, 1 new test added, 152 passing
Production testing Phases 5-12: magic link auth flows, refund flows, upgrade flows ( paid + free via refund), repurchase with refunded email, Google Ads conversion verification, edge cases (double-click, back button, degraded mode with auto-heal), Cloudflare infrastructure (D1 integrity, webhook audit, health worker, PWA), content spot-checks · Discovered and documented 10 new bugs (#14-#23): rate limiting, email enumeration, refund email content issues, gray button styling, countdown timer for degraded mode, synthetic tests not writing to D1, article terminology
Led production testing Phases 3-4: Standard ($29) and Pro ($34) purchase flows end-to-end · Phase 3: Verified Stripe checkout, success page, Google Ads conversion (Standard label + $29 value), magic link email delivery, auth flow, all 11 Standard content pieces, PDF downloads (phone + print), Pro content gating, dashboard metrics
Production testing script execution: Phases 1-2 complete (Pre-Test Setup + Landing Pages & Public Routes, 12 test steps)\n- 7 bugs discovered and documented: back-button Processing stuck on /flight, Standard feature list order wrong on persona pages, inconsistent feature lists across 4 pages, no 404 page, scroll position not resetting, breathing section needs bullets\n- Fixed form-guard.js: added pageshow event listener to reset Processing buttons on bfcache restore\n- Baseline dashboard metrics recorded (all zeros)\n- Stripe Sandbox webhook verified active\n- All findings saved to memory for session continuity
Built synthetic endpoint monitoring: 17 HTTP probes derived from 112 unit tests, running every 5 min via health worker cron · Probes test page loads, auth gating, checkout validation, PDF security, refund/upgrade flows, webhook security
Enriched all 4 landing page bento grids with missing content cards (Scripts & Phrases, Flight Day Timeline, Packing Checklist detail, Resources & Disclaimer, What's That Sound) · Audited grid column alignment across all pages — fixed orphaned rows, ensured every row sums to 6 columns
Installed and configured Vitest for unit testing across the Calm Sheets site · Built shared mock infrastructure (D1, KV, ASSETS, fetch, auth cookies, Stripe webhook signatures)
Development workflow guide: source vs generated files, local dev, staging via preview deploys, testing checklist, common mistakes (markdown + Word doc) · CLAUDE.md updated with source-vs-generated rules and staging deployment workflow
Production readiness audit: identified and ranked 20 issues before $100/day ad spend · Auth added to /api/download-pdf (was publicly accessible)
Repositioned dark/light theme toggle inside hero section on all 4 landing pages (flight, tomorrow, prepare, understand)\n- Added dark mode CSS/JS + toggle to all 7 article pages and updated build-articles.js template\n- Fixed toggle visibility with solid background and backdrop blur in both modes\n- Fixed CSS transition streaking on nav/breadcrumb during theme switch\n- Removed checkout rate limiter that was blocking real customers\n- Added visible error messages for checkout failures instead of silent redirects\n- Added scroll position restore when returning from Stripe checkout\n- Hardened critical path error handling: guide middleware falls back to signed cookie on D1 outage, send-magic-link/verify-magic-link/refresh-auth all have top-level try/catch\n- Reformatted time display from '3 a.m.' to '3:00am' across all landing pages\n- Rotated Stripe secrets in .dev.vars and set up local D1 database with all migrations
Diagnosed broken Stripe checkout: stale price IDs causing silent redirect back to /flight\n- Updated 3 Stripe price secrets (Standard, Pro, Pro Upgrade) in Cloudflare Pages production\n- Moved dark mode toggle from cramped header bar to fixed position below nav on all 4 landing pages (flight, tomorrow, prepare, understand)\n- Fixed degraded mode UX: removed action=# rewrite that scrolled users to top of page\n- Configured Cloudflare 'Claude Code Full Access' API token with full permissions + CLOUDFLARE_ACCOUNT_ID env var to fix wrangler /memberships auth error\n- Saved landing-page-sync rule: all persona pages must be updated together
Diagnosed ERR_CONNECTION_REFUSED on /flight/api/status health polling (dead dev server + stale browser cache)\n- Fixed dev script to include --kv SITE_STATUS binding for local health system support
Debug & fix degraded mode auto-polling (setInterval→setTimeout recursion, DOMContentLoaded wrapper, separate banner/poll injection)\n- Add scroll-aware maintenance banner using IntersectionObserver on #pricing section\n- Add Cache-Control: no-store on HTML responses and fetch calls to prevent stale page caching\n- Remove unauthenticated admin status-set endpoint\n- Deploy to production
Dashboard health monitoring panel: 7 checks (D1, Stripe, GA4, purchase sync, orphaned purchases, webhook freshness, upgrade sync) + re-sync button + heartbeat display · Health worker (Cloudflare cron every 5 min): auto-detects orphaned purchases and failed upgrades, auto-repairs with magic link delivery, manages degraded mode via KV, pauses/resumes Google Ads
Built graceful Pro upgrade path: /api/refresh-auth endpoint, Pro teaser card on /guide/, upgrade toasts, footer nudge, content page nudges in journey flow, Resources page callout · Checkout flow: upgrade=true in success URL, auto-redirect to refresh-auth with 5/10/15s retry backoff
Fluid responsive typography system (clamp()) across 23 reading pages for iPhone through desktop\n- Pill-shaped dark/light mode toggle site-wide with icon + DARK/LIGHT label, auto-injected via JS\n- Session-based auto dark mode: 7pm-6am local time, manual toggle resets on next visit\n- Hamburger nav menu on 4 landing pages for tablet/medium viewports\n- Bookmark toast redesign on guide dashboard: floating, dark/light aware, dismissible\n- Download help modal hidden on desktop, mobile/tablet only\n- Ticker banner slowed 50%\n- Build template sync: build-content.js updated with dark mode toggle, journey flow nav, no download bar\n- Build template sync: build-articles.js updated with typography.css and fluid classes\n- Initial deploy: favicon, OG images, rate limit cleanup, X reply bot, content calendars
Fixed Error 1101: created missing rate_limits table in production D1 database\n- Fixed rate_limits CHECK constraint: recreated table to allow 'checkout' and 'refund' types (was only 'ip'/'email')\n- Ran full production diagnostic: D1 schema audit, env var cross-reference, static asset check, live endpoint testing\n- Added opportunistic rate_limits cleanup via waitUntil in checkout/login/refund flows\n- Removed dev-login.html from public site\n- Updated schema.sql to match production D1 state\n- Deployed x-reply-bot worker with 15-min cron trigger (540 scheduled posts, first due April 1)\n- Deployed site with all fixes to Cloudflare Pages
SEO audit & added og:image, twitter:image, twitter:card (summary_large_image) across all 35 HTML pages\n- Generated branded OG image (1200x630) with Puppeteer build script\n- Generated favicon set (SVG, 32px PNG, Apple Touch Icon) with build script\n- Fixed missing noindex/nofollow on 2 authenticated guide pages (breathing-timer, flight-day-timeline)\n- Updated layout.js template and package.json with new build scripts\n- Deployed to Cloudflare Pages and verified all assets live
Built analytics dashboard at /dashboard with password auth, 13 sections, real-time refresh · Stripe financial metrics: revenue, fees, net, tax owed, disputes, payouts, per-tier revenue
Rebuilt Stripe product images with larger fonts and less text for mobile checkout readability · Added md:grid-cols-2 tablet breakpoint to bento grid across all 4 landing pages (/flight, /tomorrow, /prepare, /understand)
Built X auto-reply bot: Cloudflare Worker with 15-min cron, fetches @calmsheets mentions, generates replies via Gemini 2.0 Flash-Lite, posts automatically via OAuth 1.0a · Extracted 2,500-word knowledge base from all 11 guide resources + 6 published articles for bot context
Deep research: X/Twitter marketing strategy for @calmsheets (content pillars, posting schedule, growth tactics, hashtag strategy, sell ramp) · 540-post content calendar: 90 days x 6 posts/day across 3 CSV files (April, May, June) ready for Buffer import
Created ai-code-production-audit skill (15-point checklist, 369 lines) · Ran full production audit on Calm Sheets, identified 12 fixes
Wallpaper download modal with iPhone/Android instructions (matches PDF modal style)\n- API error handling overhaul: Stripe refund failure no longer silent, Resend emails wrapped in try/catch, single retry with 2s delay for magic link and refund offer emails\n- Dark mode fixes: error text colors, wallpaper modal theming, primary-fixed/30 override\n- Auth cookie cleared on refund cancellation so landing pages reset\n- User-friendly error states added to login and refund pages\n- Ticker animation slowed 20%, wallpaper helper text updated\n- GitHub-to-Cloudflare Pages auto-deploy pipeline configured (no more manual wrangler deploy)\n- Cache purge hook updated with calmsheets.com zone and 90s delay\n- Cloudflare security/speed/caching configured: TLS 1.2 min, HSTS subdomains, browser cache 4h, crawler hints, cert transparency
Remove disorienting scroll-jump on timeline 'I'm here now' click · Dark mode readability fixes across timeline, breathing timer, meditation, and download modal
Fix iOS Safari auto-zoom on refund page (input font-size to 16px)\n- Redesign guide page header: add slim nav bar, move Pro badge + theme toggle, rename title to 'Your Pre-Flight Guide' (drop 'Anxiety' post-purchase)\n- Fix dark mode Pro interactive tool cards showing light cream backgrounds\n- Fix wallpaper PNG centering (absolute positioning) + rename files to drop cs- prefix\n- Push stale landing page breakpoint changes (md → lg)
Fixed noindex tags and robots.txt blocking Google from indexing privacy, terms, and refund pages\n- Added all 3 legal page URLs to sitemap.xml\n- Dark mode contrast overhaul: topic cards, login email input, breathing timer text, quote bubbles (cream bg + dark text), Pro-only labels (vibrant green), Standard pricing button (cream bg), nav links (white)\n- Renamed 'Send Magic Link' to 'Email Me a Link' on login page\n- Shrunk meditation play button (w-14 to w-10) + added mt-4 spacing from voice toggles on all 4 landing pages\n- Right-aligned 'Get the Guide' nav button on compressed windows with ml-auto\n- Centered nav links with absolute positioning, collapse at lg (1024px) breakpoint to prevent overlap\n- Added margin-left spacing between Get the Guide button and theme toggle\n- Renamed 'Pro-only' section label to 'Communication' on /prepare/ (Scripts now included in Standard)\n- Bumped content grid breakpoint from md to lg on all 4 landing pages to prevent squished Flight Day Timeline\n- Increased quote bubble padding from p-4 to p-6 on /flight/ and /prepare/\n- Fixed Pro demo cards spacing: switched from justify-between to gap-5 for consistent layout in both stacked and side-by-side views
Fix ticker banner: seamless infinite scroll loop + speed tuning (30s→8s) · Fix PDF downloads: blob-fetch approach for individual + single-file picker downloads (prevents browser tab opening)
Stripe webhook setup with HMAC signature verification and replay protection\n- Two-layer rate limiting system (6/hr per IP, 15/day per email) with D1 migration\n- Email-not-found error handling on login page with user-friendly messages\n- Success page UX fixes (removed confusing button, added bookmark tip)\n- PDF download overhaul: Worker with Content-Disposition headers, human-readable filenames, print margin fixes, build template updated\n- Post-download modal with device-specific instructions (iPhone/Android detection)\n- Save-this-page dismissible banner on guide dashboard\n- Login/access links added to landing page nav and footer\n- Smart CTA button swap via Cloudflare HTMLRewriter (cookie + tier aware)\n- Full Pro upgrade path: $5 checkout, webhook tier update, form injection for Standard buyers\n- Stripe product images (3 branded PNGs for checkout)\n- Stripe tax configuration (txcd_10302000 Digital Books, tax-inclusive pricing)\n- Refund policy removed from product content\n- Content cleanup: removed parenthetical filenames from all guide copy
Breathing timer reset fix: re-show start button after demo ends\n- Audio meditation path fix: moved preview MP3s to /flight/preview/ outside auth gate\n- Nav header flicker fix: removed backdrop-blur on all 4 landing pages\n- Phone wallpaper build script + 3 PNG variants (sage/navy/cream) generated via Puppeteer\n- Wallpaper preview card added to What's Inside section on all 4 landing pages\n- Pro Interactive Tools section (breathing timer + meditation player) added to /tomorrow/, /prepare/, /understand/\n- X profile assets generated: profile pic (400x400), header banner (1500x500), horizontal wordmark (800x200)\n- Stripe branding setup: logo, colors, statement descriptor, refund policy guidance\n- Google Ads conversion tags verified working for Standard and Pro tiers\n- Cloudflare env secrets configured for Stripe, Resend, magic link\n- Sitemap fixed: correct path, added terms/privacy/refund pages (16 total)\n- Google Search Console sitemap submitted
Built Google Ads Campaign 1A (Night-Before Panicker — East) with 3 ad groups (Can't Sleep, Panic Attack, Scared Tomorrow), full keyword sets, responsive search ad copy, sitelinks, geo targeting (Eastern + Central states), and 10pm-5am CT ad schedule · Built Campaign 1B (Night-Before Panicker — West) cloned from East with Mountain + Pacific states, 11pm-7am CT schedule, and $40/day budget
Built comprehensive Playwright E2E test suite: 245 tests across 11 spec files (public pages, purchase, magic link auth, content gating, PDFs, interactive tools, refund, upgrade, SEO, mobile, security)\n- Test infrastructure: playwright config, TypeScript fixtures, HMAC cookie helper, D1 database seeder, 6 page objects\n- Found and fixed XSS vulnerability in refund page (innerHTML injection from query params)\n- Deployed to Cloudflare Pages production with Stripe test keys\n- Created remote D1 database and ran schema migrations\n- Configured DNS: calmsheets.com + www.calmsheets.com CNAME to Pages, www->apex 301 redirect\n- Cloudflare performance/security: SSL Full strict, HSTS, Always HTTPS, browser cache TTL, tiered cache, Early Hints, Bot Fight Mode, no-sniff header
Google Ads keyword research: 68 keywords across 3 personas (Night-Before Panicker, Avoidant Traveler, Logic Seeker) with CPC/volume estimates and tiered priority · Google Ads ad copy: 9 ad groups of responsive search ad headlines, descriptions, sitelinks, callouts, and price extensions