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.
- Prospects — the 15-million-row CRM, including dedup, segmentation, list management, account rotation for outreach, and Hunter.io enrichment.
- Outreach — email campaign authoring, multi-account SMTP rotation, A/B tracking, and the “Smash” LinkedIn-scraping bot fleet.
- Boards — the engagement lifecycle (advisory boards / sprints): briefing, expert recruitment, conversation, transcript, deliverable.
- Content — production workflow for blog posts, board summaries, and marketing assets. Includes a homegrown Markdown editor and the AI co-facilitator hooks.
- Members — user/account management, segmentation, lifecycle status, suspension, merge/dedup of duplicate accounts.
- Operations — billing, invoicing, payouts (formerly via Gnosis Safe — now dormant), legal/NDA tracking, support ticket views.
- Analytics — internal dashboards, cohort metrics, board ROI rollups, the daily-digest cron.
- 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:
| 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.
Phase-2 pages this links to
/domains/a— the public web product surface (phase 2)/domains/cthrough/domains/f— remaining product domains (phase 2)/features/crm-engine— how the 15M prospects got into the database (phase 3)