Super System · Vision
Last updated 2026-06-13

🎯 What We're Building

One owned platform — the Super System — where all of Love at First Fight's data lives once and every screen, email, and app reads from it. Below is the system we're building, not the stack we're leaving.

One platform

1
source of truth, replacing ~8 glued tools

Owned modules

13
CRM, courses, commerce, automation…

Surfaces

4
public · member · admin · API (+Flutter)

Tool spend cut

~$7k/yr
+ accurate data & new revenue

The vision

A custom platform built in-house: one clean database, logic in code (not fragile webhooks), every capability we rely on owned and extensible. It delivers courses, runs the CRM, takes payments, sends email, and automates the business — in each customer's local time zone, in real time, and AI-native so Claude can query and help run it.

✨ What the new system does

The capabilities that make it more than a like-for-like replacement.

🎓 Course delivery + gamification

Modules, lessons & pricing in one place. Duolingo-style progress, badges, cohort visibility, and couple/partner progress → higher completion, retention, upsells.

👥 Real CRM (People)

Leads, students, partners — payments, notes, tags, progress, watch-%. Per-user "3D" column views; sensitive data permission-gated. Replaces AC-as-CRM + the 39k-row sheet.

🛒 Own cart & checkout

One product, many pricing options (no more 18+8 duplicates). Stripe/PayPal direct — Apple/Google Pay, Klarna. Refunds from inside the system.

🌍 Time-zone-aware

Courses open and emails send in the customer's local time — retiring the Phoenix-time workaround.

📈 Trusted tracking

End-to-end attribution under one domain — replacing distrusted ThriveCart reports and ClickMagick.

⚙️ Automation, owned

A per-minute scheduler ("what needs to happen now?") replaces AC "waiting" flows. Marketing editable, back-end logic locked.

🔌 Integrations

QuickBooks/Wave accounting sync; Missive & WebinarJam connected via API where we keep them.

⚡ Real-time + 🤖 AI-native

Live notifications & CRM updates via sockets. APIs expose data so Claude can analyse, report, and assist ops.

🛡️ Secure by design

Secrets in encrypted env files, token auth, monthly key rotation, error alerting (Bear), YubiKey for staff under consideration.

Shape of the system

🌐 www · Nuxt 👤 app · Vue 🛠️ admin · Vue 📱 Flutter · future
⚙️ Laravel API · api.loveatfirstfight.com
🗄️ PostgreSQL · 2 DBs (functional + audit) ⚡ Redis/Horizon 🎬 BunnyStream ✉️ SES

Full detail under Architecture. A future Flutter app reuses the exact same API — no rebuild.

Where the plan stands

DECIDED locked LEANING default unless changed OPEN needs a call
DECIDED Laravel API + Vue SPAs + Nuxt
DECIDED PostgreSQL · Redis/Horizon
DECIDED AWS · WAL-G backups
DECIDED Video on BunnyStream
DECIDED Email via Amazon SES
DECIDED One product, many prices
DECIDED Stripe + PayPal (drop ThriveCart)
OPEN Phasing (decide w/ Linka)
OPEN Real course-title source

🗂️ Current Systems reference / context

Background only — what we're migrating away from. Kept for context; the build itself is described under Vision, Modules and Architecture.

Site #1 — Marketing / Funnel laff_website

Users6 (staff only)
RoleQuizzes, opt-ins, scarcity, reviews, blog
Content3,190 posts · 718 reports · 517 reviews · 7 quizzes
Key pluginsThrive Quiz Builder, Leads, Ultimatum, Visual Editor, Yoast

Site #2 — Courses / Membership laff_data ← engine

Users41,113 customers
RoleLMS, member access, orders, automation
Growth2023: 2.4k · 2024: 18.9k · 2025: 14.9k · 2026: 4.9k
Key pluginsThrive Apprentice, Uncanny + Thrive Automator, ActiveCampaign, 2× custom dispute plugins

ThriveCart — external checkout (where the money moves)

💳 33,445 paid orders 💰 ~$7.92M USD gross 🎁 110,842 manual grants 💵 PayPal · ThrivePay

⚠️ Data reality (drives the whole design)

  • LOGS DWARF DATA wp_thrive_reporting_logs = 501 MB / 2.1M rows — 16× bigger than the orders table (31 MB)
  • SMALL CORE Entire functional dataset ≈ 536 MB → fits in RAM
  • GOTCHA Course titles are NOT in post_title (all say "Course overview post")
  • GOTCHA Money is integer cents stored as strings
  • GOTCHA Two automation engines run at once — audit both

🏗️ Architecture

Five front-end surfaces, one API — public (Nuxt), member, admin & ops (Vue SPAs), plus a future Flutter app — all speaking to the same Laravel API.

Front ends & clients

🌐 Public site
Nuxt (Vue SSR) · marketing & funnel · SEO
www.loveatfirstfight.com
👤 Member app
Vue SPA · dashboard, courses, account
app.loveatfirstfight.com
🛠️ Admin app
Vue SPA · CRM, orders, authoring
admin.loveatfirstfight.com
📋 Ops / procedures
Vue SPA · staff SOPs & procedures
ops.loveatfirstfight.com
📱 Flutter app
Future · reuses the same API, no rebuild
(mobile)
⚙️ Laravel — JSON API only
api.loveatfirstfight.com · one contract for every client
IdentityCRM CatalogCourses CommerceFunnels AutomationMessaging Reporting

Data & services

🗄️ PostgreSQL — one server
Two databases (split-aware):
laff · functional (sacred) laff_audit · access/activity/orders
WAL-G PITR → S3 · split audit to own server later, on a trigger
⚡ Redis · Horizon
Queues, cache & analytics Stream (async batch-drain)
🎬 BunnyStream
Course video hosting & streaming
✉️ Amazon SES
Transactional & marketing email (replaces AC)

Hosted on AWS · CloudFront in front of www / app / admin

Capability replacement

Today (rented)Super System (owned)
Thrive Apprentice→ Courses / LMS module
ThriveCart→ Commerce module + PSP
Thrive Quiz Builder→ Funnels module
Leads / Ultimatum→ Funnels module
Uncanny + Thrive Automator→ Automation engine
ActiveCampaign→ Messaging module
WordPress users/roles→ Identity & access

Data store strategy

WorkloadHome
Functional
users, orders, courses, payments
Postgres (main) sacred
Audit / business events
access, activity, order events
Postgres — separate database (same server; split later)
Behavioral analytics
navigation, A/B, funnels
In-house pipeline → PG → ClickHouse later
App / debug logsFiles + error tracker (NOT SQL)

🔒 Rule: analytics writes are never synchronous in a request — fire-and-forget to a Redis Stream, drained in batches.

🧭 Decisions Log

Every architectural decision made so far, with status. Full reasoning lives in the research markdown files.

DecisionChoiceStatus
Backend frameworkLaravel (PHP 8.3+)OPEN
Front-end shapeDecoupled JSON API + 2 Vue SPAs (for future Flutter)OPEN
Public siteNuxt (Vue SSR) for SEOOPEN
Deployment topology5 domains: www / app / admin / ops / api (ops = Vue SPA for staff procedures)OPEN
API authLaravel Sanctum tokensOPEN
Database enginePostgreSQLOPEN
DB topologyFunctional + audit = 2 databases on 1 server (split-aware)OPEN
Queues / workersHorizon + Redis, separate poolsOPEN
Analytics captureRedis Stream, async batch-drainOPEN
Analytics: build vs buyBuild in-house (rejected PostHog)OPEN
HostingAWS (CloudFront / Beanstalk / EC2 / S3)OPEN
DB backup / recoveryEC2 + WAL-G PITR → S3 + local RAID + internationalOPEN
Video hostingBunnyStream (closes blocker)OPEN
EmailAmazon SES + per-minute scheduler (replaces AC)OPEN
Catalog modelOne product → many pricing optionsOPEN
Logic splitEditable marketing vs hard-coded back-endOPEN
PaymentsStripe (primary) + PayPal · drop ThriveCartOPEN
PhasingTrust-Again pilot vs back-end-firstOPEN
Vue admin component libraryPrimeVue / Vuetify / shadcn-vue?OPEN
Repo shapeMonorepo vs 4 repos?OPEN
API tierBeanstalk vs ECS Fargate / App Runner?OPEN

⚡ Capacity & Bottleneck

Where the ceiling is, and how many users/day we can serve before it strains.

Today's real load

~3.3k
visits/day · 88 orders · 20 signups · ~5–6 q/s peak

Start tier capacity

~40k–60k
sessions/day on t3.medium (~$30/mo)

Headroom at start

~15×
current load uses ~1–2% of smallest box

The bottleneck

Postgres
connections (→ PgBouncer) then CPU (→ replica/tier). RAM never.

Bottleneck order (what breaks first)

CloudFront / SPAs
effectively infinite
✅ never the wall
Laravel API
hundreds req/s
autoscale adds nodes
Redis
tens of thousands ops/s
PostgreSQL
CPU + connections
◀ THE WALL

Postgres stays the bottleneck — it has the lowest ceiling in the stack either way. PgBouncer doesn't make it faster; it removes the connection limit, leaving CPU as the only Postgres wall (so the bar moves right, not away). CPU scales with instance size + read replicas; connections don't — that's what PgBouncer is for.

Key fact: the functional dataset (~536 MB) fits in RAM, so the DB is memory-served, not disk-bound — the wall is CPU/connections, never disk. Writes are trivial (~88 orders/day, peak 293).

📈 EC2 scaling tiers — "if we make Postgres bigger, what can we handle?"

Because the whole DB fits in RAM, scaling = adding vCPUs. Each step up roughly doubles capacity. Pick a starting tier; scale on measured signals.

TierPostgres instancevCPU / RAM~Member sessions / day~$/mo*
★ Todayt3.small2 / 2 GB~20k–30k~$15
Startt3.medium (rec.)2 / 4 GB~40k–60k~$30
Steadym7g.large (Graviton)2 / 8 GB~150k–200k~$60–75
Growthm7g.xlarge4 / 16 GB~350k–450k~$120–150
Heavym7g.2xlarge8 / 32 GB~700k–900k~$240–300
Bigr7g.4xlarge16 / 128 GB~1.5M–1.9M~$700–850

You're at the ★ row today (~5–6 q/s peak = ~1–2% of the smallest box). Start one notch up (t3.medium) for build/launch headroom, not because traffic needs it. * On-demand ballpark; Reserved cuts ~30–50%. A read replica ~doubles reads more cheaply than a tier jump + doubles as failover.

🟢 Recommended start (sized to reality)

Postgrest3.medium (2 DBs: laff + laff_audit)
Redist3.small

≈ ~$45/mo total → ~40k–60k sessions/day (~15× current). Audit is a 2nd database on the same box — split to its own server later, on a trigger.

⚡ Redis tiers (sized for RAM, not CPU)

InstanceRAMWhen
t3.small2 GB★ now / start
t3.medium4 GBgrowth
m7g.large8 GBheavy
+ split—on eviction

🧭 Which lever, by signal

DB CPU high→ bigger tier / read replica (scales ✅)
DB connections maxed→ PgBouncer (sizing up won't help ❌)
Redis evicting→ bigger / split Redis
API CPU high→ Beanstalk autoscale

CPU & connections are different limits: CPU grows with instance size; connections don't — that's PgBouncer's job.

Scaling levers (in order)

  • 1 · Cache more / longer in Redis (↓ DB load, free)
  • 2 · Add a read replica (↑ CPU + spreads connections)
  • 3 · Autoscale the API tier (↑ API CPU)
  • 4 · PgBouncer (fixes connection ceiling)
  • 5 · Bigger DB instance (↑ CPU only)

Redis split ladder (by measured traffic)

StageEvents/daySetup
NOW< 50k1 Redis + separate pools
150k–1Mseparate logical DB
21M–10Mseparate Redis instance
3> 10M+ ClickHouse / Kafka

Projected ~50k/day → firmly Stage 0. First split ~20× away.

🧱 Feature Modules

Each capability we bring in-house becomes a Laravel domain module. Sorted by build priority.

P0 needed for a usable platform P1 important fast-follow P2 later

💡 Click any module to open its detail page — design questions, data model and open decisions.

#ModuleReplacesPriorityNotes (from Bruce's KB)
1Identity & access ›WP users / rolesP0pivot-table access (grant/revoke = 1 row); permission-gated screens
2CRM (People) ›ActiveCampaign + class-list SheetP0Leads/Students/Partner; per-user "3D" column views; notes; double-payment detection
3Catalog & pricing ›~18 + ~8 duplicate productsP0One product, many pricing options ($697/$277/$397/$197/+lifetime)
4Courses / LMS ›Thrive ApprenticeP0video on BunnyStream ✓; time-zone-aware drips; coaching-replay auto-access
5Customer Dashboard ›Thrive Apprentice member areaP0The member-facing app (app.) — login, my courses + switching, lesson player, quizzes/answers/results, progress & couple progress
6Commerce + Cart ›ThriveCartP0Stripe/PayPal direct (Apple/Google Pay, Klarna); in-system refunds; time-zone signup
7Disputes / chargebacks ›laff-dispute-evidence-v2P1"First win" — already built, folds in
8Automation + Scheduler ›Uncanny/Thrive Automator + AC waitsP1per-minute cron "what needs to happen now?"; editable marketing vs locked logic
9Messaging ›ActiveCampaign emailP1Amazon SES; local-time sends; editable sequences
10Gamification ›— (new)P1Duolingo-style progress/badges; cohort + couple/partner progress → retention/upsell
11Revenue & Attribution ›ThriveCart reports + ClickMagickP1trusted sales screen; end-to-end attribution under one domain
12Funnel builder ›GoHighLevel wishlistP2team-editable funnels + checkout per pricing option
13Integrations ›manual entryP2QuickBooks/Wave accounting sync; Missive, WebinarJam via API
14Analytics pipeline ›(scattered)P2in-house, async Redis Stream; A/B tests; navigation tracking

Cross-cutting requirements (touch many modules)

🌍 Time-zone-aware everything 🔒 Editable marketing vs hard-coded logic ⚡ Real-time via sockets 🤖 AI-native APIs (Claude can query the business) 👁️ Per-user views & permissions 🛡️ Bugsnag/"Bear" · YubiKey · monthly key rotation
🔐

Identity & Access

P0core

Who can log in, what they are, and what each person is allowed to see and do — for ~41k customers and the staff team. Replaces WordPress users/roles and the scattered permission logic.

What it does

One identity table for everyone — customers and staff — with authentication (Sanctum tokens), roles, and fine-grained permissions. Course/product access is a pivot relationship (user ↔ product), so granting or revoking access is a single row change. Every other module asks this one "who is this and what may they do?"

🧭 Key design questions

❓What roles do we need?
Roles are named bundles of permissions. From Bruce's KB, the people who appear:
Customer / Student — sees only their own courses, progress, billing.
Coach — a filtered "coaching call" view; attendee lists, note-taking; no finances.
Support / CS — full customer lookup, notes, can issue refunds; finances maybe hidden.
Marketing (John) — funnels, emails, split tests, pricing; not customer PII / finances.
Admin / Owner (Bruce, Berner) — everything, incl. revenue & settings.
Need from you: confirm the role list + who maps to each. Should a person be able to hold multiple roles (e.g. coach + support)?
❓Do we want table-level / column-level permissions?
You asked specifically: "do we want table roles so certain users can only see certain tables?" Three levels of granularity, from coarse to fine:
Role-based (coarse): a role can/can't access a whole area (e.g. "Marketing can't open Finance"). Simple, covers 90%.
Table/resource-level: permissions per data type — "Coach may read Students, not Orders." This is your "table roles" idea.
Column/field-level: hide specific fields — Bruce's KB literally calls for this ("Bruce hides emails; Linka shows status"; finances gated). Pairs with the CRM's per-user "3D" column views.
Recommendation: build role + resource-level permissions as the foundation (a permission like orders.view, students.edit), then layer field-level visibility for the sensitive columns the CRM needs. Laravel does this cleanly with a policy/gate layer + a permission table; libraries like spatie/laravel-permission give roles+permissions out of the box. Avoid hard-coding per-user rules — drive it from data.
Need from you: is resource-level enough, or are there specific fields (beyond finances/email) that must be hideable per role/person?
✅How is access to courses/products granted? — decided
A pivot table (user ↔ product, many-to-many). Grant = insert a row; revoke = delete/expire it. Replaces the WordPress installment-lock / drip-lock dance. (From Bruce's KB.)
❓Staff login security — how far?
Bruce's KB raises YubiKey (hardware keys) for staff and a TBD password manager.
Baseline: email + password + 2FA (TOTP) for all staff.
Stronger: hardware key (YubiKey/WebAuthn) for admin/finance roles.
Need from you: 2FA for all staff (recommended minimum)? YubiKey required for which roles?
❓Customer login & the 41k migration
WordPress stores phpass password hashes. Plan: import the hashes and rehash on first successful login — no mass password reset for 41k users. Open: do customers also get optional social login (Google) later?

🗂️ Data model sketch

users id · email · password_hash · name · timezone · status · created_at roles id · name (customer|coach|support|marketing|admin) permissions id · key (e.g. orders.view, students.edit, finance.view) role_user user_id · role_id # a user can hold many roles permission_role permission_id · role_id # roles bundle permissions field_visibility role_id · resource · field · visible # column-level gating product_user user_id · product_id · granted_at · expires_at · source # THE access pivot

🔗 Depends on / feeds

Feeds → every module (auth & permission checks) Access pivot ← Commerce (payment grants access) Field visibility ↔ CRM (3D column views) Migration: WP wp_users + roles
👥

CRM (People)

P0

Replaces ActiveCampaign-as-CRM and the 39k-row class-list Google Sheet. Leads, students, partners — all in one screen.

🧭 Key design questions

❓What columns/fields does each role see? (the "3D" views)
Per-user show/hide columns — Bruce hides emails, Linka shows status, a coach gets a filtered attendee view. Ties directly to field-level permissions in Identity & Access.
Need: the canonical column list + who sees what.
❓Lead vs Student definition & lifecycle
When does a Lead become a Student? What states between (watched masterclass → bought → in progress → completed)? Drives reporting + automation triggers.
❓Double-payment detection rules
Bruce wants the CRM to flag double payments. What defines one (same user + product within N days)? Auto-flag or auto-refund?
❓Partner / couple linkage
How are two people linked as a couple? Shared account, linked accounts, or a partner field? Affects gamification's couple-progress too.

🔗 Depends on

Identity (field permissions)Courses (progress)Commerce (payments)
🏷️

Catalog & Pricing

P0

The single biggest data-model change: collapse the ~18 Thrive + ~8 ThriveCart duplicate products into one product with many pricing options.

🧭 Key design questions

❓How do duplicate products map to one product + options?
Today: full $697, masterclass $277, follow-up $397, Valentine's $197, +annual/lifetime. These are pricing options of one course, not separate products.
Need: a mapping of every current product → which course + which pricing option. (This is the catalog-mapping data task.)
❓What differs per pricing option besides price?
Drip schedule? Included modules? Bonuses? Access duration (annual vs lifetime)? Each option may bundle different access — model that explicitly.
❓Bundles
Thrive has tva_bundles. Are bundles a pricing option, or a product made of other products? Decide the shape.

🗂️ Data model sketch

products id · name · type · status # the course/offer pricing_options id · product_id · label · price_cents · currency · access_duration · drip_id checkouts id · pricing_option_id · slug # unique checkout per option

🔗 Depends on

Feeds → Commerce + CoursesMigration: tva products + ThriveCart
🎓

Courses / LMS

P0

Course delivery: modules → lessons → resources, drip scheduling, certificates — replacing Thrive Apprentice. Video on BunnyStream.

🧭 Key design questions

❓Real course titles & hierarchy
Thrive's titles aren't in post_title ("Course overview post"). Need the real title source + the course→module→lesson→resource tree. (Open data blocker.)
❓Time-zone-aware drip — exact rules
Lessons open in the customer's local time. What's the drip cadence (daily? per-module?), and what's the anchor (purchase date? cohort start?)?
❓Progress tracking granularity
Per-lesson complete? Video watch-%? (CRM + gamification both read this — Thrive tracked it in postmeta.)
✅Video hosting — decided
BunnyStream. Our DB stores metadata + Bunny IDs; playback via signed Bunny URLs.

🔗 Depends on

Identity (access pivot)Catalog (what's in each option)BunnyStreamScheduler (drips)
🛒

Commerce + Cart

P0

Own cart & checkout, Stripe + PayPal direct, order ledger, refunds — replacing ThriveCart. The highest-risk migration (the $7.9M).

🧭 Key design questions

✅Processors — decided
Stripe (primary) + PayPal, direct through LAFF's own accounts. See payments.md.
❓Subscriptions / recurring?
Annual/lifetime add-ons exist. If any renew, we need Stripe Billing + PayPal Subscriptions (dunning, proration). If all one-time, much simpler.
❓Saved-card / token migration off ThriveCart
Can repeat buyers' payment methods transfer, or re-enter on first new purchase?
❓Order ledger model — keep history of 165k orders?
Import full ThriveCart/TA order history for continuity, or start fresh + archive? (Revenue reporting needs the history.)

🔗 Depends on

Catalog (pricing options)Identity (grants access on pay)Stripe + PayPalDisputes
⚖️

Disputes / Chargebacks

P1first win

The dispute-evidence tool Berner already built (laff-dispute-evidence-v2) folds in here. A standalone, high-value piece.

🧭 To work through

❓Port the existing plugin's logic
Read the v2 plugin source; capture what it reads/writes and which services it calls. Decide day-1 vs fast-follow.
⚙️

Automation + Scheduler

P1

A per-minute scheduler ("what needs to happen now?") replacing AC "waiting" flows + Uncanny/Thrive Automator. Hard split: marketing editable, back-end logic locked.

🧭 To work through

❓Audit BOTH current automation engines
Uncanny Automator + Thrive Automator both run today — inventory every recipe so none is lost.
❓What's "editable by marketing" vs "locked logic"?
Draw the exact line: which automations can John change in a UI, which are hard-coded?
✉️

Messaging

P1

Transactional & marketing email via Amazon SES, sent in the customer's local time. Replaces ActiveCampaign email.

🧭 To work through

❓Which AC sequences/events must port?
Inventory current AC automations + templates. Keep AC short-term or cut over?
❓Deliverability / SES warm-up
41k contacts — SES sending limits, domain auth (DKIM/SPF/DMARC), IP warm-up plan.
🎮

Gamification

P1new

Duolingo-style progress, badges, cohort visibility, couple/partner progress → completion, retention, upsells. A revenue feature.

🧭 To work through

❓What's gamified, and what rewards?
Streaks? Badges per module? Cohort leaderboard (first-names-only)? Define mechanics + what (if anything) they unlock.
❓Couple/partner progress view
Depends on partner linkage (see CRM). "Here's how the two of you are doing."
📈

Revenue & Attribution

P1

A trusted sales/revenue screen + end-to-end attribution under one domain. Replaces distrusted ThriveCart reports and ClickMagick.

🧭 To work through

❓Attribution model
First-touch / last-touch / multi-touch? What sources (ad platforms) feed in? This is the ad-cost-crisis fix.
❓Which ClickMagick capabilities must we replicate?
Inventory what ClickMagick does today before absorbing it.
🪝

Funnel Builder

P2

Team-editable funnels + checkout per pricing option — the GoHighLevel-style capability John wants, without the limits.

🧭 To work through

❓How editable, by whom?
Full drag-drop page builder, or templated funnels with editable copy/offers? Ties to "editable marketing" principle. P2 — after back-end is solid.
🔌

Integrations

P2

Connect the tools we keep: QuickBooks/Wave (accounting sync), Missive (support), WebinarJam/EverWebinar — via API.

🧭 To work through

❓Accounting sync scope
QuickBooks or Wave? Push every order, or daily summaries? (Berner has done ~10k orders/mo before.)
❓Which tools stay vs go
Confirm the keep-list and what each integration must do.
📊

Analytics Pipeline

P2

In-house behavioral analytics: navigation, A/B tests, funnels — captured async via a Redis Stream so it never slows the system.

🧭 To work through

✅Capture pattern — decided
Async fire-and-forget → Redis Stream → batch-drain. Postgres now → ClickHouse later. See data-stores.
❓A/B test framework
Sticky variant assignment per user; server- or client-side; what we measure.
🧑‍🎓

Customer Dashboard

P0member app

The logged-in student experience — where a buyer lands after login to consume what they paid for. This is the Customer Vue 3 SPA at app.loveatfirstfight.com. Unlike the other modules it's not a new back-end domain — it's the front-end surface that composes Courses, Quizzes, Gamification, Identity and Commerce into one place. Replaces the Thrive Apprentice member area. Full spec: customer-dashboard.md.

What the student gets

🏠 Home / "Continue where you left off" 📚 My Courses + switch between courses ▶️ Lesson player (BunnyStream video, drip-locked in local time) 📝 Quizzes → answers → results (review past attempts) 📈 Progress, badges, cohort & couple progress 💳 My account / billing / partner details 🔔 Live notifications (sockets)

🧭 Key design questions

❓One dashboard across all courses, or a per-course home?
Single member home that aggregates progress + a "current course" context switcher.
Per-course landing each time.
Recommendation: one home that aggregates, with a course switcher — directly serves the "go between courses" goal.
❓Quiz review depth
Can students retake quizzes? See correct answers, or only their own answers + score? Likely differs for graded vs reflective quizzes (a relationship program probably leans reflective).
Need from you: what should a student see after submitting — score only, their answers, or the correct answers too?
❓Couple / partner progress & privacy
How do two accounts link (invite? shared purchase?), and what may each partner see of the other?
Need from you: the linking flow + how much of a partner's detail is visible vs private.
❓Self-service scope
Can students change their own plan, request refunds, update partner details — or are those staff-only? Also: same API must feed a future Flutter app, so keep the data contract app-ready.

🗂️ Data it reads / writes (mostly composed from other modules)

enrollments = product_user pivot # what courses they can see (Identity) lesson_progress user_id · lesson_id · completed_at · seconds_watched quiz_attempts user_id · quiz_id · score · submitted_at quiz_answers attempt_id · question_id · answer · correct partner_links user_id · partner_user_id · visibility # couple progress badges_user user_id · badge_id · earned_at # gamification

🔗 Depends on / feeds

Identity → auth + access pivot Courses/LMS → content + local-time drips Quizzes → attempts/answers/results Gamification → progress, badges, couple progress Commerce → billing view Real-time → socket notifications

🛣️ Build Roadmap

Phased so we always have something working and never risk the money. WordPress runs until the very end.

◀ We are here

Phase 0 — Research & decisions

Build this research base · answer open questions · lock decisions · get a production DB dump · read the dispute plugin.

Next

Phase 1 — Foundation (read-only mirror)

Laravel JSON API + Postgres + Sanctum. Import users/orders/courses read-only. Minimal admin SPA that views data. Prove the model holds 41k users / 165k orders.

Then

Phase 2 — Member experience (courses)

Customer SPA: login, dashboard, "my courses", lesson player, progress. Wire video storage. Port drip + certificates. Runs in parallel with WP.

Careful

Phase 3 — Commerce cutover

Integrate Stripe (+PayPal). Dual-run with ThriveCart, reconcile daily, flip "buy" buttons only after clean reconciliation. Keep rollback.

Later

Phase 4 — Funnels & automation

Rebuild quizzes, opt-ins, scarcity. Rebuild both automation engines. Migrate ActiveCampaign triggers.

Final

Phase 5 — Decommission WordPress

Final reconciliation. Freeze and archive both WP sites. URL redirects. Done.

⏰ Backstop deadline

Be live before ActiveCampaign renews 4 June 2027 (~$5,581/yr) so we don't pay another AC year. Soft, not hard — AC partial-refunds unused time. The hope is to be well ahead of it.

🧭 Open phasing question (decide with Linka)

Linka's idea: pilot with the simpler Trust Again program to prove the model.
Bruce's lean: build course-delivery / back-end (CRM + delivery) first, leave the marketing site, tackle tracking later. Both agree: stabilise current stack first, build in parallel, retire one tool per phase.

💰 Commercials & Savings

The money case for the build: tool spend retired, the renewal deadline, and the wins that dwarf the subscriptions.

Tool spend targeted

~$7k
per year (exact figure: Berner to total)

Biggest single line

$5,581
ActiveCampaign / year

Be-live-by date

4 Jun 2027
AC renewal backstop

Savings targets (rough, annual)

Tool~$/yrFate
ActiveCampaign~$5,581Replaced — SES + built-in CRM
ClickMagick~$3,500Largely absorbed — own tracking
AWS (was video backups)~$2,800 → ~$0Already moved to BunnyStream ✓
Hookdeck~$470Obsolete — traffic internal
Pabbly~$240–360Obsolete
Uncanny Automator / Thrive licenceslicencesObsolete

The wins bigger than tool cost

📊 Accurate data / trusted tracking ⏳ Time saved — weekly setup, support, debugging 📈 New revenue — gamification / retention / upsell

❓ What We Still Need

The open questions blocking real progress. The two starred items block the Courses module — the biggest unknowns.

🚧 Blockers (data)

  • ★ BLOCKER Real course-title source (not in post_title)
  • Video storage → BunnyStream (confirmed)
  • Production DB dump (is local .test current?)
  • tva_orders.status code meanings (1/4/0/2)
  • Course→module→lesson hierarchy + drip rules source
  • What is laff_data_courses2 — stale clone?
  • Map ~18+8 duplicate products → one product + pricing options

🧩 Product / scope

  • PHASING Trust-Again pilot vs back-end-first (decide w/ Linka)
  • Subscriptions/recurring, or one-time only?
  • Replace ActiveCampaign (SES + built-in CRM)
  • Single currency (USD) confirmed?
  • Password manager: RoboForm / 1Password / Bitwarden / Proton / custom?
  • Domain/branding for the new system

⚙️ Technical / infra

  • Vue admin component library choice
  • Monorepo vs 4 repos
  • Beanstalk vs ECS Fargate / App Runner
  • PgBouncer from start or later
  • WAL-G vs pgBackRest + restore drill cadence
  • AWS region + per-tier cost estimate

✅ Recently decided

  • Front-end shape (API + Vue SPAs + Nuxt)
  • 4-domain topology
  • PostgreSQL · functional + audit as 2 DBs, 1 server
  • Horizon + Redis + analytics Stream
  • AWS hosting + EC2 WAL-G PITR backups
  • Capacity model (DB is the bottleneck)