Treehouse — the internal back-office

If the public marketing site is what the world saw of Currnt, Treehouse is what Currnt actually was. The customer-facing surface was a thin storefront; Treehouse is where the company lived. 33 controllers, eight functional pillars, hundreds of pages — none of them ever served a public user.

The eight pillars

Treehouse organizes itself into eight functional groups. Each group is a cluster of controllers + Twig views + a set of background jobs.

  1. Prospects — the 15-million-row CRM, including dedup, segmentation, list management, account rotation for outreach, and Hunter.io enrichment.
  2. Outreach — email campaign authoring, multi-account SMTP rotation, A/B tracking, and the “Smash” LinkedIn-scraping bot fleet.
  3. Boards — the engagement lifecycle (advisory boards / sprints): briefing, expert recruitment, conversation, transcript, deliverable.
  4. Content — production workflow for blog posts, board summaries, and marketing assets. Includes a homegrown Markdown editor and the AI co-facilitator hooks.
  5. Members — user/account management, segmentation, lifecycle status, suspension, merge/dedup of duplicate accounts.
  6. Operations — billing, invoicing, payouts (formerly via Gnosis Safe — now dormant), legal/NDA tracking, support ticket views.
  7. Analytics — internal dashboards, cohort metrics, board ROI rollups, the daily-digest cron.
  8. System — feature-flag administration, cron job management, queue inspection, and read-only views into the dispenserd lanes.

Representative routes

The full Treehouse route surface is too large to list here — routes.js is 2,278 lines and a meaningful subset goes via dynamic controllers. The below is a curated cross-section showing the shape:

A representative cross-section of /admin/* and /treehouse/* routes. Not exhaustive.
Method Path Handler Notes
GET /admin AdminController.dashboard Pillar landing; widget grid.
GET /admin/prospects ProspectController.list Searchable, segmented, paginated 25/page.
GET /admin/prospects/:id ProspectController.detail Activity timeline + dedup candidates.
POST /admin/prospects/import ProspectController.import CSV; queues `import_prospects` lane.
GET /admin/outreach/campaigns CampaignController.list All active and historical campaigns.
POST /admin/outreach/send CampaignController.send Queues `send_outreach` jobs, 1 per recipient.
GET /admin/boards BoardController.list Filter by status: draft / active / closed.
GET /admin/boards/:id/transcripts BoardController.transcripts Per-board conversation log.
POST /admin/content/posts PostController.create Triggers AI co-facilitator nudging hook.
GET /admin/members MemberController.list Internal-only view; not the public profile page.
POST /admin/members/:id/merge MemberController.merge Dedup two accounts into one.
GET /admin/ops/invoices InvoiceController.list Filter by client, status, fiscal quarter.
GET /admin/analytics AnalyticsController.dashboard Cohort metrics, refreshed nightly.
GET /admin/system/cron SystemController.cron 62 jobs; last run + next run.
GET /admin/system/queue SystemController.queue Live view into dispenserd lanes.

The headline flow: SDR contact → board invite

The single most-trafficked Treehouse workflow takes a brand-new prospect from the 15M-row CRM all the way to sitting on an advisory board for a paying client. It crosses six controllers and two queue lanes.

Step 1: SDR opens /admin/prospects, filters by industry + seniority + last-contact > 60d.
Step 2: Bulk-selects ~50 rows, "Add to campaign" → CampaignController.addProspects.
Step 3: ProspectController writes campaign_membership rows.
Step 4: CampaignController.send → POSTs N jobs to dispenserd lane `send_outreach`.
Step 5: dispenserd worker picks up each job, renders one of 177 email templates,
        sends via the next SMTP account in rotation (Mandrill fallback).
Step 6: Recipient clicks tracked link → /track/:campaign/:prospect → records open.
Step 7: Replies hit a parsing webhook → InboundController.parse → matches to prospect.
Step 8: SDR sees reply in /admin/prospects/:id, marks as "interested".
Step 9: BoardController.invite generates a one-time invite URL → emails it.
Step 10: Recipient accepts → user account created, joined to board, expert role assigned.

This is the seat of revenue. Every other workflow in Treehouse is, in some way, in service of making this loop tighter.

Dormant Treehouse features

Several Treehouse pillars contain features that no longer have live data flowing through them. They’re catalogued on the sunset page. The biggest is the engagement marketplace — a pillar inside Boards where experts could browse open sprints and self-apply. The schema still exists; no rows since 2023.