description: Lógica de negocio, reglas de producto y arquitectura técnica de TheFittClub. Fuente de verdad para cualquier implementación. globs: *

Sistema de documentos del proyecto:

Documentos técnicos complementarios:

🏆 TheFittClub V2: Master Business Logic & Requirements

This document is the Single Source of Truth for all functional requirements. Any technical implementation must satisfy these business tiers while adhering to the Edge-Native (Cloudflare/D1/RRv7) architecture.


🏗️ LAYER 1: PLATFORM GLOBAL RULES (The Ecosystem)

1. Product Matrix & Upselling

  • Free Combination: Users can own and mix Rituals, Modules, and Capsules. All must coexist in a unified Dashboard (“Mi Espacio”).
  • Dynamic Upselling: The Dashboard uses AI-detected tags (e.g., “lumbar pain”) to suggest specific Capsules or Modules (Ticket 5).
  • Access Control (Ticket 3): Access is strictly managed by user_purchases. Free products (Lead Magnets) bypass Stripe but are registered in D1.

2. Billing, Benefits & Guarantees (Ticket 3 & 9)

  • Club Discount: Active subscribers get a permanent 5% discount on one-off purchases (Modules/Capsules).
  • Refund Windows: 14 calendar days, every product, no exceptions. Rituals, Modules, Capsules and unredeemed gift vouchers alike. This is the Spanish statutory withdrawal right (arts. 102 ff. of RDL 1/2007), and it is what the published terms already promise a buyer — public/locales/{es,en}/legal.json § Derecho de desistimiento. Corrected 2026-08-09 (founder: “garantía 14 días, creí que ya estaba corregido”). This line used to read “Rituals (7 days), Modules (3 days), Capsules (0 days — No refunds)”, which was wrong on all three rows and contradicted the live sales page (ritual-core.json → pricing.guarantee, “14 días de desistimiento”). A published promise the internal SSOT disagrees with is the worse of two records, not a second opinion. The art. 103(m) waiver for immediately-accessible digital content is not available: the terms state it is valid only via an explicit checkbox at checkout, and that checkbox does not exist. Until it ships, 14 days applies without exception — do not shorten this line for Modules or Capsules on the theory that digital content is exempt.
  • Gifting (Ticket 9): Users can purchase products as gifts, generating a unique gift_vouchers code for third-party redemption.

3. Gamification & Global Stats (Ticket 8)

  • Global Streak: Any completion across any product adds to the “Días Activos” global counter and total minutes.
  • Isolation: Progress within a Ritual does NOT unlock phases in a Module. Each program track is independent in D1.
  • Async Processing: All gamification logic (streaks, badges) is handled via Cloudflare Queues to ensure <200ms response times.

🧩 LAYER 2: THE UNIVERSAL ADAPTIVE ENGINE (Building Blocks)

Every program is a “Playlist” of these relational blocks:

1. The Session Canvas (Ticket 2)

  • Canvas Order: Administrators define the sequence (e.g., PDF Intro Audio Routine PDF Tips).
  • 3-Series Routine: Routines are split into Warmup, Main, and Cool-down blocks.
  • Playback State: Video/Audio progress is persisted in user_playback_state for cross-device continuity.

2. Progressive Intelligence (Ticket 2 & 7)

  • RPE Scaling: After each session, users rate effort (1-10). If RPE >= 9, the engine stays at the current version. If 8, it scales up to Version 6 (Ticket 7).
  • AI Overrides: If an exercise is “Banned” in user_exercise_preferences, the loader automatically injects the alternative_exercise_id.

3. Personal Journal & AI Memory (Ticket 5)

  • Dual Storage: D1 stores the raw text/photo and the NLP-extracted tags (e.g., “high stress”, “diastasis”).
  • Async NLP: Analysis is performed via context.cloudflare.waitUntil to avoid UI latency.

📜 LAYER 3: PRODUCT-SPECIFIC MECHANICS

3.1 RITUALS (Continuous Transformation)

Ej: Ritual Core, Ritual Tao, Ritual Glúteos.

  • Modalities: Users choose daily: Express (5m), Base (20m), or Progressive (Versions 1-6).
  • Phase Ascent (Ticket 6): two tracks to the same gate — Fast Track demands fewer consecutive weeks but adds a weekly-minutes floor; Slow Track allows more weeks and checks only the days floor. The thresholds themselves (required_consecutive_weeks, min_days_per_week, min_minutes_per_week) are per-phase, per-track rows in phase_unlock_conditions, tuned from the Back Office — this document states the shape, not the values (T422). Read them live: SELECT track_name, required_consecutive_weeks, min_days_per_week, min_minutes_per_week FROM phase_unlock_conditions.
  • Clinical Fail-Fast (Ticket 6): If the Phase Evaluation fails, the user is locked in “Modo Preparación” with a mandatory compensation exercise for prep_quarantine_days.
  • Loop Logic (Ticket 7): When reaching the end (e.g., Day 180), the sequence loops back automatically using modular arithmetic.

3.1.1 Ritual Core Legacy (T204)

A distinct product, not a tier of the new Ritual Core. Canonical id: prod_ritual_core_legacy (T65’s pm_rcl_standard reconciles to this single id).

  • What it is: a reduced Ritual Core granted to the legacy cohort — single-track, none of the new Ritual Core’s added functions/modalities. The new prod_ritual_core (Express/Base/Progressive modalities) is the forward product; legacy members do not receive it.

  • Who gets it (cohort law): only members who bought a “Core y Suelo Pélvico Poderosos – <edición>” edition and paid it in full (Σ of their transactions for that edition ≥ the edition’s program price). Abandoned-installment / partial payers are excluded. “Ritual Core Inicial” also grants access; the discontinued bare “Ritual Core” grants nothing.

    Corrected 2026-08-09 (founder: “Ritual Core Inicial murió y ya no existe, no se nombra”). The catalogue today holds exactly two: Ritual Core Legacy (sales never reopen) and Ritual Core (waiting list).

    What Ritual Core Inicial actually was, per the vault’s Capa-0 record (CONTEXTO_SESION_2026-05-17.md, slug membresia-ritual-core): the **≈5.0K lifetime revenue (14% of legacy). It is a retired product name: never in member-facing copy, a price table or a menu. The same vault entry records that confusing it with “Core y Suelo Pélvico Poderosos” (the €400-500 one-off, 86% of revenue) was one of the errors already corrected once — they are unrelated products.

    It is NOT deleted from this rule, and must not be. The line reads as naming a product because it is really an entitlement rule over historical Zenler purchase strings, and ritual-core-inicial is a member of ACCESS_GRANTING_MEMBERSHIPS in app/lib/domain/legacy-membership.ts. Retired as a name, load-bearing as a record.

    One stale label in that classifier, and it is cosmetic. The def still carries active: true, false since the 2026-11-20 closure. Its whole reach is presentational: admin.payments.tsx groups the membership filter into active/inactive, and admin.payments.$id.tsx appends a ”· inactive” suffix. It does not decide which rows appear, who is counted, or who gets access.

    What it does NOT do — recorded because an earlier draft of this section got it wrong (2026-08-09). That draft warned that ACCESS_GRANTING_MEMBERSHIPS containing ritual-core-inicial meant an expired ≈$8/month subscription would grant Ritual Core Legacy in the T386 wave. It does not, on two independent counts. isLegacyProduct (the only function that reads that set) has no production caller — the seed’s tests are all that reach it. And the actual Legacy entitlement runs through a different, much narrower predicate: LEGACY_PRODUCT_MEMBERSHIP is "core-suelo-pelvico" and nothing else, so the cheap membership is already excluded by construction. The founder’s correction was the right one: the Back Office holds the correct cohort, extracted by the scripts. Do not re-raise this as a migration risk without first re-reading both predicates.

  • Eligibility SSOT: the cohort classifier + the canonical per-edition price map (PRICE_PER_EDITION) live in app/lib/domain/legacy-membership.ts; the paid-in-full math is summariseFulfilment (payment-fulfilment.ts). The same price map backs the Back-Office paid-in-full badge (T203).

  • Content: real legacy content (clips/sessions) is T65. T204 defines the product shell + entitlement only.

3.2 MODULES (Targeted Recovery)

Ej: Cesárea (MVP), Diástasis, Postura, Caderas Libres.

  • Duration: 4-8 weeks (20-40 effective days).
  • Flow: On-demand progress. No blocking evaluations.
  • Active Components: Context, Techniques, Bitácora (Metrics), and Journal (AI).

3.3 CAPSULES (Rescue Pills)

Ej: SOS Lumbar, Despertar Pélvico (Free), Reto Hipopresivos 30D.

  • Duration: 1-21 days.
  • Flow: Direct consumption. Clinical metrics (Bitácora) and Journal are DISABLED to reduce friction.
  • Rewards: Contribute to Global Streak and grant a completion Badge.

🛠️ ARCHITECTURAL GUARDRAILS (The Architect’s Code)

  1. Loader-First: Data fetching belongs in RRv7 loaders. No client-side useEffect for initial data.
  2. D1 Relational Purity: No JSON arrays for core relations. Use junction tables and normalized rows (e.g. member_conditions keyed off physical_profiles, exercise_materials, phase schedule links).
  3. Compound Keys: Use composite primary keys where appropriate for idempotency (e.g. product_user_progress: user_id + product_id; onboarding: product_id + question_id).
  4. Edge runtime in Workers: Request handlers and loaders must stay Edge-safe: no Node-only fs / path / Node crypto in app code bound to Workers. Tooling (catalog sync, seeds, Drizzle kit) may use Node locally; keep those scripts out of Worker bundles (see drizzle/seeds/*).
  5. Spec-driven development: No implementation without an approved spec under _docs/03-tickets/02-active/ (then _docs/03-tickets/04-done/ when locked). _docs/03-tickets/03-qa/ is reserved for strict QA contracts when a spec explicitly requires them—not a prerequisite for every feature.

Catalog note (implementation detail)

Editorial content is relational in D1 (training_sessions and related tables). The legacy routines table for Ritual Core Phase 1 is still populated from TypeScript (app/lib/catalog/data/ritual-core/phase-1) until TD-007 is retired — this is handled automatically by npm run db:seed (Phase 2 of drizzle/seeds/run.ts). See thefittclub-private-catalog-data.md.


Architectural Decision Log:

  • [2026-04-04] V2 Pivot: Catalog moved from TS files to D1 Relational Schema.
  • [2026-04-04] Async Logic: Gamification moved to Cloudflare Queues; AI NLP moved to waitUntil.
  • [2026-04-24] Schema split: Drizzle definitions live under app/db/schema/ (domain modules + barrel index.ts).
  • [2026-04-26] Docs: Dual catalog pipeline documented — relational canvas + legacy routines TS sync (thefittclub-private-catalog-data.md).
  • [2026-04-26] Docs: Brand identity documentation system established — see thefittclub-brand.md and related files.