ThybridOS architecture

How the codebase is laid out and how the systems fit together. Built from the repo at Desktop/thybrid/website (branch main) and the 13 Nov 2026 ops architecture report. ThybridOS is the admin and CRM that runs inside the same Next.js app as the public site.

Key point

ThybridOS is not a separate codebase. Its UI is app/admin-v2, its APIs are app/api, and its logic is app/lib, all inside the thybrid Next.js app. That one app is built with OpenNext and deployed as one Cloudflare Worker, which serves thybrid.com, the apply form and admin.thybrid.com. Nine small satellite Workers handle crons, jobs and read paths.
1Main Workerthybrid: site, ThybridOS, all write APIs
~620Logic filesapp/lib (ts/tsx)
~240ThybridOS UI filesapp/admin-v2
~100API route filesapp/api
~720Test files13,228 tests, run with npm test
~92CRM tablesNeon Postgres, Singapore

Composition of Desktop/thybrid

About 29 GB in total. Most of it is worktrees, exports and archive, not product code.

FolderSizeWhat it is
worktrees/12GOld git worktrees. Only dev-v3 is still needed.
exports/8.8GReports, wipe backups and release logs, by date.
archive/4.7GOld material.
website/3.6GThe main repo (thybrid-landing, branch main). Real product code is about 1.4 GB of this.
thybrid-leadgen/1.2GLead-gen tooling.
fran_voice/847MVoice samples.
research/, assets/, tools/, data/about 450MResearch, brand assets, scripts, data.
.env12KSingle env file with secrets. Never copy it.

Inside website/

ItemSizeRegenerable
node_modules813MYes (npm install)
infra711MNo, Terraform (large provider caches inside)
.open-next506MYes, build output
public435MNo, site media and funnel kit
.next179MYes, build output
exports45MNo
docs, app, tests, services14M, 14M, 11M, 11MNo, source

Repo map: website/

website/
  app/                 Next.js app router (site + ThybridOS + APIs)
    admin-v2/          ThybridOS UI and server actions
    api/               HTTP routes (apply, booking, cron, slack, stripe, zoom, meta...)
    lib/               business logic (~620 files)
    ve/                landing and form (live /apply funnel)
    apply, book, rewire, sanctuary, gallery ...   public pages
  db/migrations/       Neon SQL migrations (35 files)
  tests/               ~720 test files
  scripts/             tooling (118 files)
  docs/                OPS, CRM, BOOKING, DECISIONS, ROLES, SECURITY ...
  public/              static assets, shared/funnel form kit
  infra/               Terraform: AWS, Cloudflare, Access
  services/            ads-sync, alarm-slack, meta-api, meta-browser, llm-modal, stt-modal, notion-cc
  cron-worker/  jobs-worker/  leads-worker/  hot-worker/  media-worker/
  crm-sync-worker/  adset-analyzer-worker/  reports-worker/  mcp-worker/
  *-site/              static report sites (automations, qa, seoaeo, uxopt, adsreport, appflow)
  wrangler.jsonc       main Worker config (KV, R2, queue, service binding)
  wrangler.dev.jsonc   dev Worker config
  package.json         next 16, react 18, @opennextjs/cloudflare, wrangler 4

ThybridOS inside the app

UI: app/admin-v2

Pages: applicant, ask, audit, automations, calendar, calls, campaigns, connections, digest, enroll, exports, inbox, marketing, payments, people, pipeline, reports, reviews, sessions, sign-in, tasks, team. Shared pieces: AdminShell.tsx, HomeClient.tsx, HomeViz.tsx, and server actions such as applicant-actions.ts, book-actions.ts, call-actions.ts, connections-actions.ts.

API: app/api

admin/ai, audit, broadcasts, connections, conversations, google, marketing, people, privacy, segments
cron/sweep, ad-alerts, funnel-digest, crm-sync, invariants, journey-tick, meta-digest, social-tick, health
apply, booking, booker, otp, phoneApplication and booking flow
slack, stripe, zoom, whatsapp, ses, email, metaWebhooks and integrations
call-bot, call-transcript, recCall recording and scoring
v1, reports, marketing, evPublic API, reports, events

Logic: app/lib

Domains: admin-v2, ai, ask, automations, booker, booking-native, brand, call-bot, calls, command-centre, connections, conversions, crm-read, email-campaigns, exports, invariants, journey, marketing, personal-notify, privacy, recorder, social, sync, webhooks, weekly-digest, zoom-native. Plus flat files for the apply flow (apply-final*.ts), ads (ads-report.ts, adset-scoreboard.ts), applicant messages and stage moves.

Cloudflare Workers

WorkerJobWhere in repo
thybridthybrid.com, apply form, ThybridOS at admin.thybrid.com, all write APIsapp/ via OpenNext
thybrid-hotFast booking slot readshot-worker/
thybrid-mediaFilms under /m/media-worker/
thybrid-sweepEvery app cron, plus the call-score queue consumercron-worker/
thybrid-jobsMorning jobs: Google offline conversions, Clarity digest, marketing collectorsjobs-worker/
thybrid-leadsLead-gen helpers, watchdog on sweep heartbeat, WhatsApp health checkleads-worker/
thybrid-adset-analyzerDaily ad set check against real applicationsadset-analyzer-worker/
thybrid-crm-syncMonthly cold backup of Neon to R2crm-sync-worker/
thybrid-reportsCommand Centre at dash.thybrid.comreports-worker/
thybrid-mcpRead-only data connector for Claudemcp-worker/
thybrid-devdev.thybrid.com test copy. Writes to the same prod data.same code, wrangler.dev.jsonc
thybrid-oldOld static siteworktree old-site
static report Workersautomations, qa, seoaeo, uxopt, adsreport, appflow*-site/

Systems map

flowchart LR
  V1["Visitor / applicant"] --> W1
  V1 --> W2
  V1 --> W3
  subgraph CF["Cloudflare"]
    W1["thybrid: site + ThybridOS + APIs"]
    W2["thybrid-hot"]
    W3["thybrid-media"]
    W4["thybrid-sweep: crons"]
    W5["thybrid-jobs"]
    W6["thybrid-leads"]
    W7["thybrid-adset-analyzer"]
    W8["thybrid-crm-sync"]
    W9["thybrid-reports"]
    W10["thybrid-mcp"]
    KV[("KV")]
    R2[("R2")]
    D1[("D1 leads")]
    Q["Queue call-score"]
    ACC["Cloudflare Access"]
  end
  subgraph AWS["AWS Singapore"]
    DDB[("DynamoDB applications")]
    ADS[("DynamoDB ads-daily")]
    LMB["Lambda ads-sync"]
    SM["Secrets Manager"]
  end
  NEON[("Neon Postgres CRM")]
  SL["Slack"]
  RS["Resend"]
  ZM["Zoom"]
  ST["Stripe"]
  META["Meta"]
  W1 --> DDB
  W1 --> NEON
  W1 --> KV
  W1 --> SL
  W1 --> RS
  W1 --> ZM
  W1 --> ST
  W1 --> META
  W1 --> Q
  W4 -->|"calls app routes"| W1
  Q --> W4
  W5 --> NEON
  W7 --> META
  W7 --> DDB
  W8 --> NEON
  W8 --> R2
  LMB --> META
  LMB --> ADS
  LMB --> SM
  ACC --> W1
  ACC --> W9

Data stores

StoreWhereHolds
DynamoDB thybrid-applicationsAWS SingaporeMaster record of every application. Point-in-time recovery on.
DynamoDB thybrid-ads-dailyAWS SingaporeDaily Meta spend rows.
Neon PostgresSingaporeCRM: people, pipeline, calendar, calls, tasks, notes, marketing. About 92 tables. Applications are mirrored, not mastered here.
KV (one shared namespace)CloudflareLive switches, heartbeats, form drafts, rate limits.
R2 thybrid-crm-archiveCloudflareMonthly Neon snapshots, job output.
R2 thybrid-site-mediaCloudflareSite films.
D1 thybrid-leadsCloudflareLead-gen data.

Data flow

Lead to payment

flowchart TD
  A["Meta ad or Instagram"] --> B["Homepage"]
  B --> C["Apply form, 3 screens"]
  C --> D["Application saved: DynamoDB"]
  D --> E["CRM copy: Neon"]
  D --> F["Review card: Slack"]
  D --> H["Email 01: Resend"]
  D --> I["Lead event: Meta CAPI, consent only"]
  F --> J["Closer reads in Slack or ThybridOS"]
  J -->|"Not a fit"| K["Email 02 decline"]
  J -->|"Good fit"| L["Closer messages on WhatsApp by hand"]
  L --> M["Book call in ThybridOS: Zoom meeting"]
  M --> N["Emails 03 and 04"]
  M --> O["Slack card 65 min before"]
  O --> P["Zoom call, 30 min"]
  P --> Q["Outcome card in Slack"]
  Q -->|"No-show"| R["Email 05"]
  Q -->|"Sold"| S["Stripe invoice drafted in ThybridOS"]
  S --> T["Payment webhook records it"]

Where an application is written

sequenceDiagram
  participant P as Applicant
  participant S as thybrid Worker
  participant K as KV
  participant D as DynamoDB
  participant N as Neon CRM
  participant SL as Slack
  participant E as Resend
  participant M as Meta CAPI
  P->>S: Screen 1, contact details
  S->>K: Draft saved
  S->>D: Draft row
  P->>S: Submit last screen
  S->>D: Application row
  S->>N: CRM contact and pipeline stage
  S->>M: Lead event (consent only)
  S->>SL: Review card
  S->>E: Email 01 received

Scheduled jobs (Bangkok time)

WhenWorkerJob
Every minutethybrid-leadsLead-gen bridge, watchdog on sweep heartbeat
Every 5 minthybrid-sweepMain sweep: review reminders, host 1-hour card, outcome asks, emails 04 and 05, journeys, broadcasts, social posts, connection warnings
Every 5 minthybrid-sweepZoom recordings and transcripts poll
:17, :33, :43 hourlythybrid-sweepCRM sync, data-truth checks, health check of Resend, Stripe, Meta, Slack
03:00Lambda ads-syncYesterday's Meta numbers to DynamoDB and Notion
07:41thybrid-crm-syncHeartbeat, full Neon backup on the 1st
09:05 to 09:45sweep, jobs, analyzerDashboard rebuild, Google offline conversions, ad alerts, Clarity digest, ad set check
14:20 to 14:50thybrid-sweepFunnel digest, Meta card, weekly review (Monday), measurement card
17:00thybrid-sweepCommand Centre scoreboard
20:30thybrid-leadsLead-gen digest

Infrastructure and security

External services

SlackReview cards, outcome cards, alarms, digests
ResendAll applicant and team email
ZoomMeetings, recordings, transcripts
StripeInvoicing and payment webhooks
MetaAds, pixel, Conversions API, DMs
Google AdsOffline conversions upload
Microsoft ClarityRecordings and heatmaps, consent only
NotionCommand Centre, bookings
WhatsApp Cloud APIBuilt, switched off. Humans send from their phones.
OpenRouterCall scoring and Ask ThybridOS

Transfer plan to Desktop/thybridos

  1. Copy website/ without node_modules, .next, .open-next and .env. About 1.4 GB, git history kept.
  2. Disable or rename the Worker deploy in the copy so it cannot overwrite production.
  3. Run npm install and npm test in the copy to confirm it builds.
  4. Docs already in thybridos/thybrid-docs: Build Plan and Product Overview.