Studio New Account Churn Risk Report
Generates a live, interactive churn risk dashboard scoped to members who joined in the last 90 days, for any MarianaTek studio using the connected MCP server.
Step 1: Identify the MCP server
Check which MarianaTek studio MCP is connected and available. An example includes:
Cousteau / Cousteau Admin
Use whichever studio MCP the user has connected and is asking about. If multiple are connected, ask the user which studio they want the report for.
Step 2: Pull live member data
Paginate through ALL members — studios can have thousands of accounts. Fetch in batches of 10 pages at a time (page_size: 100 per page), continuing until a page returns fewer than 100 results (indicating the last page).
Batch loop:
- Fetch pages 1–10 concurrently
- Check if any page returned fewer than 100 results → that's the last page, stop
- If all 10 returned 100 results, fetch pages 11–20, then 21–30, etc.
- Continue until the last page is found
Extract for each member:
id
first_name + last_initial (note: some MCPs use these separate fields instead of full_name)
completed_class_count
date_joined
archived_at
Filter to:
- Active members only (
archived_at is null)
- Joined within the last 90 days — compute
today - 90 days and exclude anyone whose date_joined is older than that cutoff
Step 3: Classify risk tiers
Apply these rules in priority order — check from top to bottom and assign the first matching category:
- New account —
date_joined is within the last 7 days (recency always wins, regardless of class count)
- Never attended — 0 classes completed
- Critical — 1 class completed
- High risk — 2–3 classes completed
- Watch — 4–5 classes completed
- Engaged — 6+ classes completed
Compute:
- Total new accounts (all members in the 90-day window)
- Count per tier
- % per tier (of total new accounts)
Step 4: Render the report widget
Use visualize:read_me with modules ["chart", "data_viz"] then visualize:show_widget to render the report.
Report layout (match this exactly)
Metric cards row (4 cards):
- Total new accounts (last 90 days)
- Never attended — count of Never attended tier — muted/secondary color
- Critical — count of Critical tier — danger color
- High risk — count of High risk tier — warning color
Two charts side by side:
Left — Doughnut chart (6 tiers):
- New account = #378ADD (blue)
- Never attended = #888780 (gray)
- Critical = #E24B4A (red)
- High risk = #EF9F27 (amber)
- Watch = #F5C842 (yellow)
- Engaged = #97C459 (green)
- Custom HTML legend above with tier name, count, and percentage
Right — Bar chart (member count by class bracket):
- Brackets: [0, 1, 2–3, 4–5, 6–10, 11+]
- Colors: gray for 0, red for 1, amber for 2–3, yellow for 4–5, blue/teal for 6+
- X axis label: "Classes attended"
Members table — show Critical, High risk, and Never attended only (exclude Watch, Engaged, and New account):
- Columns: Name | Joined | Classes | Risk level
- Sort order: Critical first, then High risk, then Never attended; within each tier sort by days_ago descending (longest since joining first)
- Risk level column width: 140px (wide enough so "Never attended" fits on one line without wrapping)
- No max-height cap — show ALL rows, do not truncate or scroll
- Row backgrounds:
- Critical rows:
background: var(--color-background-danger)
- Never attended rows:
background: var(--color-background-secondary)
- High risk rows: alternating transparent /
var(--color-background-secondary)
- Risk badges:
- Critical: bg=#E24B4A, text=#FCEBEB
- High risk: bg=#EF9F27, text=#412402
- Never attended: bg=#888780, text=#F1EFE8
- "Joined" column: show as a relative date, e.g. "14 days ago" or "52 days ago"
Action buttons row (.no-print):
- "Draft re-engagement email ↗" →
sendPrompt('Draft a re-engagement email for my at-risk new members')
- "Download PDF" → client-side via
window.print()
Print stylesheet:
<style>
@media print {
.no-print { display: none !important; }
body { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}
</style>
Chart.js config notes
- Load from:
https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.js
- Every canvas needs
role="img", aria-label, and fallback text
- Disable default legend:
plugins: { legend: { display: false } }
- Use
responsive: true, maintainAspectRatio: false
- Canvas wrapper:
position: relative; width: 100%; height: 220px
- All chart colors are hardcoded hex (canvas cannot resolve CSS variables)
Design system
- Metric cards:
background: var(--color-background-secondary), border-radius: var(--border-radius-md), padding 1rem
- 4-card grid:
display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px
- Table:
border: 0.5px solid var(--color-border-tertiary), border-radius: var(--border-radius-lg)
- No max-height or overflow-y on the table wrapper — all rows must be visible
- All text uses CSS variables for dark mode compatibility — never hardcode
color: #333 etc.
- Buttons: plain
<button> tags (pre-styled by the host)
- No emoji, no gradients, no drop shadows
- Sentence case everywhere
Step 5: Follow-up
After rendering, be ready to:
- Draft a re-engagement email targeting new at-risk members
- Drill into a specific member's profile
- Adjust the window (e.g. "show me just the last 30 days")
- Re-run with updated live data
1---2name: studio-new-account-churn-risk3description: Generates a live new-account churn risk report for a MarianaTek fitness studio, focused exclusively on members who joined in the last 90 days. Use this skill whenever the user asks about new member churn, new account engagement, early retention, new member risk, recently joined members, or whether new members are coming back. Triggers on phrases like "new account churn", "new member report", "new members at risk", "early retention", "recently joined", "90 day members", "are new members coming back", or any request to analyze engagement or churn risk specifically for new or recent members. Always use this skill for these requests — do not attempt to generate the report from memory or without pulling live MCP data.4---56# Studio New Account Churn Risk Report78Generates a live, interactive churn risk dashboard scoped to members who joined in the last 90 days, for any MarianaTek studio using the connected MCP server.910## Step 1: Identify the MCP server1112Check which MarianaTek studio MCP is connected and available. An example includes:13- `Cousteau` / `Cousteau Admin`1415Use whichever studio MCP the user has connected and is asking about. If multiple are connected, ask the user which studio they want the report for.1617## Step 2: Pull live member data1819**Paginate through ALL members** — studios can have thousands of accounts. Fetch in batches of 10 pages at a time (page_size: 100 per page), continuing until a page returns fewer than 100 results (indicating the last page).2021Batch loop:221. Fetch pages 1–10 concurrently232. Check if any page returned fewer than 100 results → that's the last page, stop243. If all 10 returned 100 results, fetch pages 11–20, then 21–30, etc.254. Continue until the last page is found2627Extract for each member:28- `id`29- `first_name` + `last_initial` (note: some MCPs use these separate fields instead of `full_name`)30- `completed_class_count`31- `date_joined`32- `archived_at`3334Filter to:351. Active members only (`archived_at` is null)362. **Joined within the last 90 days** — compute `today - 90 days` and exclude anyone whose `date_joined` is older than that cutoff3738## Step 3: Classify risk tiers3940Apply these rules **in priority order** — check from top to bottom and assign the first matching category:41421. **New account** — `date_joined` is within the last 7 days (recency always wins, regardless of class count)432. **Never attended** — 0 classes completed443. **Critical** — 1 class completed454. **High risk** — 2–3 classes completed465. **Watch** — 4–5 classes completed476. **Engaged** — 6+ classes completed4849Compute:50- Total new accounts (all members in the 90-day window)51- Count per tier52- % per tier (of total new accounts)5354## Step 4: Render the report widget5556Use `visualize:read_me` with modules `["chart", "data_viz"]` then `visualize:show_widget` to render the report.5758### Report layout (match this exactly)5960**Metric cards row** (4 cards):611. Total new accounts (last 90 days)622. Never attended — count of Never attended tier — muted/secondary color633. Critical — count of Critical tier — danger color644. High risk — count of High risk tier — warning color6566**Two charts side by side**:6768Left — Doughnut chart (6 tiers):69- New account = #378ADD (blue)70- Never attended = #888780 (gray)71- Critical = #E24B4A (red)72- High risk = #EF9F27 (amber)73- Watch = #F5C842 (yellow)74- Engaged = #97C459 (green)75- Custom HTML legend above with tier name, count, and percentage7677Right — Bar chart (member count by class bracket):78- Brackets: [0, 1, 2–3, 4–5, 6–10, 11+]79- Colors: gray for 0, red for 1, amber for 2–3, yellow for 4–5, blue/teal for 6+80- X axis label: "Classes attended"8182**Members table** — show Critical, High risk, and Never attended only (exclude Watch, Engaged, and New account):83- Columns: Name | Joined | Classes | Risk level84- Sort order: Critical first, then High risk, then Never attended; within each tier sort by days_ago descending (longest since joining first)85- Risk level column width: 140px (wide enough so "Never attended" fits on one line without wrapping)86- No max-height cap — show ALL rows, do not truncate or scroll87- Row backgrounds:88 - Critical rows: `background: var(--color-background-danger)`89 - Never attended rows: `background: var(--color-background-secondary)`90 - High risk rows: alternating transparent / `var(--color-background-secondary)`91- Risk badges:92 - Critical: bg=#E24B4A, text=#FCEBEB93 - High risk: bg=#EF9F27, text=#41240294 - Never attended: bg=#888780, text=#F1EFE895- "Joined" column: show as a relative date, e.g. "14 days ago" or "52 days ago"9697**Action buttons row** (`.no-print`):981. "Draft re-engagement email ↗" → `sendPrompt('Draft a re-engagement email for my at-risk new members')`992. "Download PDF" → client-side via `window.print()`100101Print stylesheet:102```html103<style>104 @media print {105 .no-print { display: none !important; }106 body { -webkit-print-color-adjust: exact; print-color-adjust: exact; }107 }108</style>109```110111### Chart.js config notes112- Load from: `https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.js`113- Every canvas needs `role="img"`, `aria-label`, and fallback text114- Disable default legend: `plugins: { legend: { display: false } }`115- Use `responsive: true, maintainAspectRatio: false`116- Canvas wrapper: `position: relative; width: 100%; height: 220px`117- All chart colors are hardcoded hex (canvas cannot resolve CSS variables)118119### Design system120- Metric cards: `background: var(--color-background-secondary)`, `border-radius: var(--border-radius-md)`, padding 1rem121- 4-card grid: `display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px`122- Table: `border: 0.5px solid var(--color-border-tertiary)`, `border-radius: var(--border-radius-lg)`123- No max-height or overflow-y on the table wrapper — all rows must be visible124- All text uses CSS variables for dark mode compatibility — never hardcode `color: #333` etc.125- Buttons: plain `<button>` tags (pre-styled by the host)126- No emoji, no gradients, no drop shadows127- Sentence case everywhere128129## Step 5: Follow-up130131After rendering, be ready to:132- Draft a re-engagement email targeting new at-risk members133- Drill into a specific member's profile134- Adjust the window (e.g. "show me just the last 30 days")135- Re-run with updated live data