THUMOS ADMIN
THUMOS ADMIN
Overview Applications Bookings Members Squads Cycles Courses Manual
Quick Actions
Open Editor Stripe Dashboard
Applications
All 0 Pending 0 Invited 0 Rejected 0 Enrolled 0
NameEmailAgeWhat they doSubmittedStatusActions
Bookings
Upcoming Past All
WhenGuestCalendarApplicationActions
All Members
NameEmailPlanSquadStreakRankStatusActions
Squads
Cycles
#StartEndStatusWinnerActions
Manual
Overview
Applications
Bookings & Calendar
Onboarding
Telegram Bot
Scoring & Ranks
Infrastructure

System Manual

How It All Works

THUMOS runs on one Cloudflare Worker (thumos-api) + one D1 database (thumos-db). Every page, bot, and admin tool reads from and writes to the same database. There is one source of truth.

The Member Journey (current primary funnel — application-gated)

  1. Discovery — they land on thumos.academy (price is hidden; all CTAs → /apply)
  2. Application — they fill out /apply (name, age, occupation, what they want, why now, income range). Saved to D1 applications. PRAGMA pings Thumos CRM with #application.
  3. Book the call — inline slot picker on the same page. Shows Sam's real free times (freeBusy auto-subtracts his calendar). They pick a slot.
  4. Calendar + Meet — worker creates a Google Calendar event on the "THUMOS Consults" calendar with an auto-generated Meet link. Sam ([email protected]) is invited as attendee. Both get Google invite emails with .ics.
  5. Confirmation email — Resend email from [email protected] with the Meet link. PRAGMA pings Thumos CRM with #booking.
  6. The call — Q / Sam runs the call. Decision: enroll, reject, or follow up.
  7. Enrollment — if yes, Q sends the Stripe checkout link or admin-creates the user. Stripe webhook → D1 users row + welcome email.
  8. Onboarding — 3 steps: sign the commitment, set milestones (body/women/money), write first gratitude post.
  9. Telegram Link — "Join Squad" button opens a bot DM that auto-links Telegram to their account.
  10. Daily Life — every weekday they post Action: + Grateful: in their squad. Bot detects, records, responds.
  11. Courses + Cycle — watch videos, mark complete. Every 30 days declare milestones hit/miss. Winning squad gets a debrief with Sam.

Warm/DM traffic that already knows the price can still use /checkout directly — Stripe → same webhook path.

Post Detection

The Telegram bot watches for messages that have Action: AND Grateful: at the start of a line. Both required. One post per weekday — duplicates silently ignored. Weekend posts are recorded but don't count toward score.

Streak = consecutive weekdays posted. Weekends don't break it. Miss a weekday → streak resets to 0.

Scoring System

Personal score per cycle = (posts ÷ weekdays × 50) + (milestones hit ÷ 3 × 50) = max 100 per cycle

Squad score = same formula but aggregated across all squad members, percentage-based

Cumulative score persists across cycles and determines rank.

RankPointsTypical Timeline
Initiate0-1990-3 months
Journeyman200-4993-6 months
Adept500+8-12 months

Cycles

~30 days per cycle. Leaderboard resets each cycle. Rank persists forever.

Start a cycle → resets all squad scores, creates new cycle record. Old cycle marked "ended".

End a cycle → pick winning squad. They get a private debrief with Sam.

New members mid-cycle: excluded from squad score that cycle.

Milestones

3 per user per cycle: Body, Women, Money. Set during onboarding or cycle start.

Visible to squad immediately. Cannot be changed once submitted.

At cycle end: declare hit or miss. Early completion allows optional new milestone (no extra points).

Automated Systems

SystemWhenWhat
Stripe webhookOn paymentCreates user + sends welcome email
Post detectionEvery message in squadChecks format → records post → responds with 🔥
8pm reminderEvery hour (checks user timezone)If it's 8pm for a user and they haven't posted → bot messages squad
Score recalc5:00 UTC dailyRecalculates all squad scores
Bot auto-linkUser taps deep linkLinks Telegram ID to THUMOS account
Group welcomeUser joins squadBot sends welcome message with post format

Invite Codes

Free members use invite links: thumos.academy/invite?code=FORGEDAY1

CodeSquadFor
FORGEDAY1Squadron LambdaOG fight camp / BDE members
FORGETHETASquadron ThetaSecond group

To add new codes: edit INVITE_CODES in worker.js and redeploy.

Telegram Groups

GroupPurposeInvite
THUMOSAll members + Sam. Topics enabled.Link
Squadron Lambda (Λ)First squadLink
Squadron Theta (Θ)Second squadLink

Bot: @ThumosAI

Infrastructure

ComponentServiceURL
APICloudflare Workerthumos-api.q-2f4.workers.dev
DatabaseCloudflare D1thumos-db
Main siteCloudflare Pagesthumos.academy
EditorCloudflare Pageseditor.thumos.academy
AdminCloudflare Pagesadmin.thumos.academy
VideosCloudflare StreamStream IDs in D1
PaymentsStripeProduct: prod_UILptFYD8wxzKO
EmailResend[email protected]
BotTelegram@ThumosAI

7-Day Guarantee

Not a trial. Full access from day 1. If they do the work (daily posts, course engagement) and it's not for them after 7 days, full refund. Manual process — review and process through Stripe dashboard.

Deploy Commands

# Deploy API (Worker)
cd selene/markets/thumos/deploy_api && npx wrangler deploy

# Deploy main site
npx wrangler pages deploy "selene/markets/thumos/deploy_main" --project-name=thumos-academy --commit-dirty=true

# Deploy editor
npx wrangler pages deploy "selene/markets/thumos/deploy_editor" --project-name=thumos-editor --commit-dirty=true

# Deploy admin
npx wrangler pages deploy "selene/markets/thumos/deploy_admin" --project-name=thumos-admin --commit-dirty=true

# Or: git push (auto-deploys main site)

Applications

What this is

The primary funnel as of April 2026. Price is hidden on the main site — every CTA drives to thumos.academy/apply. Lead has to apply before they can even see the Forge offer.

Purpose: qualify. We don't want people who need a credit-card button; we want people who'll do the work. The application forces them to articulate what they actually want, and the call lets us tell them the exact thing they need to do — whether the Forge is that move or not.

The form fields

FieldRequiredWhy
nameyesobvious
emailyesfor follow-up + confirmation
agenoqualification signal (18–28 is sweet spot)
occupationnocontext for the call
goalyes"What do you want?" — most important answer
why_nownourgency / stakes — reveals readiness
income_rangenoinforms payment-plan offer
instagramnovibe check before the call
sourceautoUTM params + referrer, captured silently

Status flow

  1. pending — default on submit. Needs review.
  2. invited — reviewed, good fit, moved forward (booking exists or invite sent).
  3. rejected — reviewed, not a fit right now.
  4. enrolled — they paid and became a member.

Status is set from the Applications tab. Click any application row → detail modal → status buttons + notes field. Pending rows also have inline Invite/Reject buttons.

PRAGMA ping

Every submitted application posts a #application message via PRAGMA bot into the Thumos CRM topic of the main PRAGMA supergroup. The ping includes everything they wrote so you can react from Telegram without opening the admin.

D1 schema

applications (
  id, name, email, age, occupation, goal, why_now,
  income_range, instagram, status, source, notes,
  submitted_at, reviewed_at
)

Migration: deploy_api/migrate_applications.sql

Bookings & Calendar

What this is

Sovereign booking system — ported from Meridian's booking-worker, now running inside the main thumos-api worker. No Cal.com, no Calendly. Multi-tenant by calendar slug, D1-backed, Google Calendar + Meet integrated, Resend-wired.

How a booking happens

  1. Applicant fills out /apply → application row saved → PRAGMA pinged
  2. Apply page flips to the inline slot picker (same page, no redirect)
  3. JS fetches /api/book/thumos-apply/dates?month=YYYY-MM — worker generates slots from availability_rules, subtracts existing bookings, subtracts Sam's real calendar events via Google freeBusy API, returns dates where anything is free
  4. Applicant picks a date → /api/book/thumos-apply/slots?date=… returns open times for that day (same filter logic)
  5. Applicant picks a slot → POST /api/book/thumos-apply/book with the chosen UTC time, name, email, application_id
  6. Worker: inserts booking row → creates Google Calendar event on THUMOS Consults with a unique Meet link, invites Sam + guest → fires Resend branded confirmation with the Meet link → PRAGMA pings CRM with #booking

Sam's availability (currently)

Mon–Sat, 09:00–22:00 Asia/Bangkok. Sundays off. 30-min slots, 12-hour minimum lead, 14-day booking horizon.

The outer window (when Sam is willing to take calls) lives in D1 availability_rules. Inside that window, the worker auto-checks Sam's real calendar ([email protected]) via freeBusy and removes any slots that conflict with his existing events. So applicants only ever see slots Sam is both willing and free to take.

To change the outer window, edit the availability_rules rows directly in D1. To block specific dates (e.g. Sam is traveling April 28–30), insert into date_overrides with type='block'. There's no admin UI for this yet — SQL only.

Bookings tab

The Bookings admin tab lists confirmed calls. Filters: Upcoming / Past / All. Each row links to the underlying application if one exists. Cancel button:

  1. Marks status='cancelled' in D1
  2. Deletes the Google Calendar event with sendUpdates=all — both parties get a Google cancellation notice
  3. PRAGMA pings CRM with #booking #cancelled

Google Calendar integration

Uses a service account ([email protected]) with domain-wide delegation impersonating [email protected]. The worker signs an RS256 JWT, exchanges it for an access token at oauth2.googleapis.com/token, then hits the Calendar API.

Events land on the secondary THUMOS Consults calendar (owned by Q, shared with Sam with edit permission). This keeps them separate from Q's personal calendar.

Required OAuth scope on the domain-wide delegation: https://www.googleapis.com/auth/calendar

To rotate the service account key: IAM → Service Accounts → thumos-booking → Keys → create new, delete old, re-run wrangler secret put GOOGLE_SA_PRIVATE_KEY.

Multi-tenant by slug

The calendars table is keyed by slug. Right now there's one: thumos-apply (30-min intro calls). To add another — e.g. existing-member 1:1s at a different price or different availability — insert a new calendars row + availability_rules, and the same /api/book/:slug/... endpoints work without any code change.

D1 tables

calendars (slug, name, timezone, slot_duration, slot_gap, owner_email, from_email, meet_url, booking_lead, booking_horizon, ...)
availability_rules (calendar_id, day_of_week, start_time, end_time, active)
bookings (calendar_id, application_id, slot_start, slot_end, guest_name, guest_email, meet_url, google_event_id, status, notes)
date_overrides (calendar_id, date, type, start_time, end_time)

Migrations: migrate_bookings.sql, migrate_bookings_meet.sql, migrate_sam_availability.sql

Common SQL ops

Change Sam's window to Mon–Fri only:

DELETE FROM availability_rules
WHERE calendar_id = (SELECT id FROM calendars WHERE slug='thumos-apply')
  AND day_of_week = 6;

Block April 28 (Sam traveling):

INSERT INTO date_overrides (calendar_id, date, type)
VALUES ((SELECT id FROM calendars WHERE slug='thumos-apply'),
        '2026-04-28', 'block');

Change slot length to 45 min:

UPDATE calendars SET slot_duration = 45
WHERE slug = 'thumos-apply';

Run via: npx wrangler d1 execute thumos-db --remote --command "..."

New Member Onboarding

How They Get Here

Two paths into onboarding:

PathURLWhat happens before
Paidthumos.academy/checkoutPay $1,997 or 3x$699 on Stripe → webhook creates account → welcome email with login → they log in → redirected to onboarding
Invitedthumos.academy/invite?code=XEnter name, email, password + invite code → account created instantly → auto-logged in → redirected to onboarding

Both paths end at thumos.academy/onboarding. The page checks auth and onboarded status — if already onboarded, redirects to portal.

Step 1: The Commitment

What they see: A commitment statement (not terms and conditions). Sam's video will play here explaining what they're stepping into — currently a placeholder until Sam records it.

The commitment text:

  • "I am here to become the man I am capable of being. Not to observe. Not to consume. To become."
  • "I will post my daily action and gratitude every weekday without exception."
  • "I will set three honest milestones — one for each realm."
  • "I will show up to the calls."
  • "I will hold my brothers to the same standard I hold myself."
  • "I understand that my failure belongs to the men beside me."

What they do: Type their full name and today's date. This replaces a checkbox — writing it makes it real.

What's saved: Nothing yet — the commitment is a ritual, not data. Future: store the signed commitment in D1.

Design intent: Abundance energy, not compliance. Alan's feedback: "put them in a state of abundance, not obligation." Sam's video will set the tone. The dark aesthetic may change to something more expansive.

Step 2: Your Milestones

What they see: An AI prompt they copy-paste into Claude or ChatGPT. The AI walks them through a guided conversation to discover what they actually want to work on.

How the prompt works:

  1. Asks which domain feels most alive — Women, Money, or Body
  2. Goes deep on ONE domain at a time (one question at a time, never a list)
  3. If they're stuck, flips to anti-vision: "What do you NOT want?"
  4. Sharpens into a concrete 30-day milestone (binary, specific, uncomfortable)
  5. Repeats for each domain
  6. Outputs 3 clean lines: WOMEN: / MONEY: / BODY:

Key principles in the prompt:

  • Never hand them a milestone — guide them to their own conclusion
  • If they list 6 goals, stop them: "Pick one."
  • If they're already strong in a domain (like Body), respect it — don't manufacture struggle
  • Match their energy. Call out deflection gently.
  • 10-20 minutes if done right

What they do: Paste their 3 milestones into the input fields (Women, Money, Body).

What's saved: 3 milestones saved to D1 milestones table with current cycle ID.

Prompt location: Embedded in onboarding.html inside a copy-paste box.

Step 3: First Post

What they see: A mock post card showing the daily format. The "Action" is pre-filled: "I joined the Forge. My milestones are set. I am beginning." They type one thing they're grateful for.

What they do: Write their gratitude → click "Post it — Enter the Forge"

What happens:

  1. Milestones saved to D1 (POST /onboarding/milestones)
  2. User marked as onboarded = 1 in D1
  3. "You're in" screen appears with 4 links

"You're In" Screen

After completing step 3, they see 4 action items:

ItemLinkWhat it does
Join SquadBot deep link: t.me/ThumosAI?start=LINK_{userId}Opens bot DM → auto-links their Telegram account → bot sends squad invite + THUMOS group link
Join THUMOSt.me/+4deDUZpuZ7k1ZWMxOpens THUMOS main Telegram group
Enter Portal/portalGoes to member dashboard
Start: Breathe Like A Dragon/courses/c01First course, lesson 1

Below these: "Don't have Telegram? Download it here" link + "Need help? Message Q directly" link to Q's Telegram DM.

After Onboarding

Once onboarded, visiting /onboarding redirects to /portal. They're in the system:

  • Portal shows their real data (streak, squad, milestones, leaderboard)
  • Telegram bot tracks their daily posts
  • Courses are accessible with progress tracking
  • 8pm reminder kicks in if they don't post

What's Not Built Yet

  • Sam's commitment video — placeholder in step 1
  • Photo signature — currently text name+date, future: upload photo of handwritten signature
  • Anti-vision pairing — each milestone paired with "what happens if I don't" (fuel)
  • Sovereign Declaration — deeper values exercise for month 2-3 members who plateau
  • Auto-squad assignment — paid members currently get no squad, need manual assignment
  • Portal aesthetic — currently dark, planned redesign to clean white

Telegram Bot

What It Is

@ThumosAI is a Cloudflare Worker-powered bot. It has no separate server — it runs on the same thumos-api Worker as everything else. Telegram sends messages to /telegram endpoint via webhook.

How Post Detection Works

  1. Member posts a message in their squad Telegram group
  2. Telegram sends the message to our Worker webhook
  3. Worker checks: does the message have Action: AND Grateful: at the start of a line?
  4. If yes → look up the user by their Telegram ID in D1
  5. Check if they already posted today (UTC date) → if yes, silently ignore
  6. Record the post in daily_posts table (who, when, which squad, weekday/weekend)
  7. Calculate their new streak (consecutive weekdays with posts)
  8. Bot responds in the group: 🔥 username — Day X

Important: The bot NEVER stores message content. Only records that a post happened and when.

Post Format Rules

RequirementDetail
Both fields requiredAction: AND Grateful: — both must be present
Start of lineMust be at the beginning of a line, not mid-sentence
Colon requiredAction: works. Action test does not.
Case insensitiveaction: and ACTION: both work
One per dayFirst valid post counts. Duplicates silently ignored.
WeekendsRecorded but not counted toward score. Don't break streaks.

Streak Rules

Streak = consecutive weekdays with a recorded post. Counted backwards from today.

  • Post Mon-Fri → streak goes up
  • Miss a weekday → streak resets to 0
  • Saturday/Sunday → ignored (don't help, don't hurt)
  • Post on weekend → recorded but streak doesn't increase

8pm Reminder

A cron job runs every hour. For each active member, it checks: "Is it 8pm in their timezone?" If yes and they haven't posted today, the bot messages their squad group: [name] hasn't posted today.

Timezone is stored per user in D1 (detected from browser on signup). Default: America/New_York.

Known issue: If the Worker is redeployed while messages are in-flight, Telegram may mark them as delivered but the Worker didn't process them. Posts are lost — Telegram won't retry.

Account Linking

Members need their Telegram account linked to their THUMOS account for posts to be tracked.

Automatic (onboarding): "Join Squad" button on the onboarding completion screen is a deep link: https://t.me/ThumosAI?start=LINK_{userId}. When they tap it, the bot auto-links their Telegram ID.

Manual: In a DM or group, send /link [email protected]. Bot looks up the email in D1 and links the Telegram ID.

Admin: Directly update D1: UPDATE users SET telegram_user_id='...' WHERE email='...'

Bot Commands

CommandWhereWhat
/startDMWelcome message with post format
/start LINK_XDMAuto-link Telegram to THUMOS account (X = user ID)
/link emailDM or groupManual link by email
/streakGroupShow your streak
/leaderboardGroupShow squad rankings
/chatidAnywhereShow chat ID (debug)

Group Welcome

When a new member joins a registered squad group, the bot automatically sends a welcome message with their name and the daily post format.

Groups

GroupChat IDPurpose
THUMOS-1003912158998Main group — all members + Sam. Topics enabled.
Squadron Lambda (Λ)-1003992128318First squad
Squadron Theta (Θ)-1003673790148Second squad

To add a new squad: create Telegram group → add @ThumosAI as admin → use /chatid to get the ID → add squad in Admin panel or D1.

Troubleshooting

ProblemCauseFix
Bot doesn't respond to postsWorker was redeployed while messages in-flightPost again — next message will work
Member posts but no 🔥Telegram ID not linkedDM bot: /link email
Already posted but shows 0dDuplicate check blocked (curl test or timezone mismatch)Check D1 for existing today post
Wrong timezone reminderUser timezone not setUpdate in D1: UPDATE users SET timezone='...'
Bot not receiving messages at allWebhook deregisteredVisit thumos-api.q-2f4.workers.dev/telegram/setup

Scoring & Ranks

Personal Score (per cycle)

(posts ÷ weekdays × 50) + (milestones_hit ÷ 3 × 50) = max 100

Example: 18 posts out of 22 weekdays = 40.9 pts. Hit 2 of 3 milestones = 33.3 pts. Total = 74.2 pts.

Squad Score (per cycle)

Same formula but aggregated across all squad members. Percentage-based so squad size doesn't matter.

Stored in squads.cycle_total_score. Recalculated nightly at midnight UTC.

Cumulative Score

Personal score carries over between cycles. Stored in users.cumulative_score. Determines rank.

Ranks

RankPointsTimeline
Initiate0-1990-3 months
Journeyman200-4993-6 months
Adept500+8-12 months

Rank persists forever. Leaderboard resets each cycle.

Cycles

  • ~30 days per cycle
  • Start: squad scores reset, new cycle record created
  • End: pick winning squad → private debrief with Sam
  • New members mid-cycle: excluded from squad score

Milestones

  • 3 per user per cycle: Body, Women, Money
  • Set during onboarding or cycle start
  • Visible to squad. Cannot be changed.
  • Declare hit/miss at cycle end

Infrastructure

Architecture

Everything runs on Cloudflare. One Worker (thumos-api) handles all API requests. One D1 database (thumos-db) stores all data. Three Pages projects serve the websites.

Services

ComponentServiceURL/ID
APICloudflare Workerthumos-api.q-2f4.workers.dev
DatabaseCloudflare D1thumos-db (c90051c3...)
Main siteCloudflare Pagesthumos.academy
EditorCloudflare Pageseditor.thumos.academy
AdminCloudflare Pagesadmin.thumos.academy
VideosCloudflare StreamStream IDs in D1 lessons table
PaymentsStripeprod_UILptFYD8wxzKO
Transactional emailResend[email protected] (booking confirmations) · [email protected] (onboarding)
Member botTelegram@ThumosAI (squad groups, daily posts)
CRM botTelegramPRAGMA → Thumos CRM topic #768 (applications + bookings pings)
Calendar + MeetGoogle WorkspaceTHUMOS Consults calendar (on [email protected]) + service account thumos-booking@theotherside-490901

Worker Secrets

All set via npx wrangler secret put <NAME> inside deploy_api/.

SecretWhat
STRIPE_SECRET_KEYStripe payments
STRIPE_WEBHOOK_SECRETStripe webhook signature verification
RESEND_API_KEYTransactional email (booking + welcome)
TELEGRAM_BOT_TOKENTHUMOS member bot (@ThumosAI)
PRAGMA_BOT_TOKENPRAGMA bot — CRM pings
PRAGMA_GROUP_IDPRAGMA supergroup ID (-1002616802728)
THUMOS_CRM_THREAD_IDThumos CRM topic inside that group (768)
GOOGLE_SA_EMAILService account email for Calendar API
GOOGLE_SA_PRIVATE_KEYService account PEM private key
GOOGLE_IMPERSONATE_USERUser the SA impersonates ([email protected])
GOOGLE_CALENDAR_IDTHUMOS Consults calendar ID (where events land)
SAM_EMAILSam's email — attendee on every booking ([email protected])
SAM_CALENDAR_IDSam's calendar ID — queried via freeBusy to subtract his real events ([email protected])

D1 Tables

Core

TableWhatKey Fields
usersMembersemail, plan, squad_id, rank, telegram_user_id, timezone
sessionsAuth tokensuser_id, token, expires_at
squadsSquadronsname, telegram_group_id, cycle scores
daily_postsPost trackinguser_id, squad_id, posted_at, counted
milestonesUser goalsuser_id, cycle_id, realm, text, declared_hit
cycles30-day roundsstart_date, end_date, status, winning_squad_id
progressCourse completionuser_id, course_slug, lesson_id
courses / lessons / lesson_flagsCourse content + audit flags

Applications + Booking (added 2026-04-19)

TableWhatKey Fields
applications/apply submissionsname, email, goal, why_now, income_range, status, notes
calendarsMulti-tenant calendarsslug, timezone, slot_duration, booking_lead, booking_horizon
availability_rulesWorking windows per calendarday_of_week, start_time, end_time
bookingsScheduled callsslot_start, guest_email, application_id, meet_url, google_event_id, status
date_overridesBlocked datesdate, type

Deploy Commands

# API (Worker)
cd selene/markets/thumos/deploy_api && npx wrangler deploy

# Main site
npx wrangler pages deploy "selene/markets/thumos/deploy_main" --project-name=thumos-academy --commit-dirty=true

# Editor
npx wrangler pages deploy "selene/markets/thumos/deploy_editor" --project-name=thumos-editor --commit-dirty=true

# Admin
npx wrangler pages deploy "selene/markets/thumos/deploy_admin" --project-name=thumos-admin --commit-dirty=true

# Or: git push (auto-deploys main site)

Worker Secrets

Set via npx wrangler secret put NAME from deploy_api/:

  • STRIPE_SECRET_KEY
  • STRIPE_WEBHOOK_SECRET
  • RESEND_API_KEY
  • TELEGRAM_BOT_TOKEN
Course Health
CourseLessonsRed FlagsOrangeResolved