Skip to main content

max / makenotwork

todo: scope creator-applications restructure (replaces waitlist) Discussed and mapped 2026-06-03. The join wizard gets a "Choose your entry" step with three branches — free trial / benefits account / just pay. Free-trial and benefits go Pending until operator approval; just-pay routes around the application entirely (paying is the signal). Founder rate applies to any branch during the cohort window. Replaces the existing creator_waitlist table + db::waitlist module + /admin/waitlist surface with a generalized creator_applications system. Strips the five "Apply for Creator Access" CTAs scattered across the platform; fans who want to apply later use a new /settings/creator-access page. Trigger to start: when the founder cohort fill is no longer well-served by the current waitlist UX, or before opening signup beyond hand-picked invitations.
Author: Max Johnson <me@maxj.phd> · 2026-06-04 04:50 UTC
Commit: 4c868fcff8550b25a3c13ddd260e9fcc90e5797e
Parent: e746b8d
1 file changed, +56 insertions, -0 deletions
@@ -312,6 +312,62 @@ All four Run #1 deferred items closed by Run #2 sweeps; pointers below.
312 312
313 313 ---
314 314
315 + ## Creator applications restructure (replaces waitlist)
316 +
317 + Discussed and scoped 2026-06-03; no implementation yet. Rename and generalize the existing waitlist into a creator-applications system that lives inside the join wizard, replaces the standalone `/admin/waitlist` surface, and gives fans a settings-page path to apply after the fact. The trigger to start: when the founder cohort fill is no longer well-served by the current waitlist UX, or before opening signup beyond hand-picked invitations — whichever comes first.
318 +
319 + ### Model
320 +
321 + Three branches in the wizard, decided up front by the signing-up account:
322 +
323 + - **Free trial** — short pitch (1–2 sentences: what you make, why MNW). Account exists, `can_create_projects = false`, application status `pending`. Operator approval flips it.
324 + - **Benefits account** — longer disclosure (community / mission alignment, the binding-mission-statement framing from the program docs). Same `pending` state, different `application_type` so the admin queue can sort them.
325 + - **Just pay** — skip the application entirely, route to Stripe checkout. **No approval required** — paying is the signal. On subscription activation, `can_create_projects = true` immediately. No `creator_applications` row written.
326 +
327 + Founder rate (50% off, locked for life when window closes) is available on **any** branch during the cohort window — free-trial seats get $0, benefits seats may be subsidized, paid seats get the standard founder discount.
328 +
329 + ### Schema migration
330 +
331 + - [ ] Replace `creator_waitlist` with `creator_applications`. Either rename the table + add columns, or create a sibling and migrate rows. Add `application_type` enum column (`free_trial` | `benefits_account`). Normalize `status` values to `pending` | `approved` | `declined` | `spam`.
332 + - [ ] Backfill existing waitlist rows as `application_type = 'free_trial'` (preserve `pitch`, `created_at`, decision metadata, `selection_method`, `invited_by_user_id`).
333 + - [ ] Drop the `db::waitlist` module + its consumers once nothing references it. The `grant_creator_access` helper is the right primitive to keep — move it under `db::creator_applications`.
334 +
335 + ### Wizard
336 +
337 + - [ ] Insert a new "Choose your entry" step in `join_wizard.rs` flow after profile, before pitch. Three radio options + short descriptions. The chosen branch threads through to the next step.
338 + - [ ] Rebuild `wizards/steps/join/pitch.html` to branch on `application_type` — different prompt text, different length limits (free-trial short, benefits longer).
339 + - [ ] Route the paid branch around the application step entirely: profile → Stripe checkout → complete. On webhook activation, no `creator_applications` row is written; `can_create_projects` is granted on `creator_subscriptions.status = 'active'`.
340 + - [ ] Rewrite `wizards/steps/join/complete.html` so the "Apply for creator access" framing is gone (the question was already answered upstream). Free-trial / benefits accounts see "Application under review"; paid accounts see "Welcome — create your first project."
341 +
342 + ### Dashboard / settings
343 +
344 + - [ ] New `/settings/creator-access` page for fan-only accounts to submit an application after the fact. Same three branches, same pitch requirements. Lives in the dashboard tab rail, not a marketing page.
345 + - [ ] Strip the five existing "Apply for Creator Access" CTAs (`partials/tabs/user_projects.html` x2, `partials/tabs/user_creator.html` heading, `pages/creators.html` step list, `wizards/steps/join/complete.html` card). Replace dashboard surfaces with a small "Apply for creator access" link that routes to `/settings/creator-access`. Marketing page (`creators.html`) drops the "apply from your dashboard" framing in favor of "start your free trial during signup."
346 +
347 + ### Pending UX
348 +
349 + - [ ] Accounts in `pending` status can browse, buy items as a fan, manage profile and settings — they just can't reach creator dashboards. Existing `can_create_projects` guards already block project creation; new behavior is to render an "Application under review" panel (with submitted pitch + submission date) instead of returning 404 or redirecting away.
350 + - [ ] Email notification on approve / decline, distinct templates per `application_type`. Decline template names the reason; approval template points at the dashboard.
351 +
352 + ### Admin
353 +
354 + - [ ] Rename `routes/admin/waitlist.rs` → `routes/admin/applications.rs`. Generalize the approve / decline / spam handlers to read `application_type`. The `grant_creator_access` call on approve stays as-is.
355 + - [ ] Rename `dashboards/admin-waitlist.html` → `dashboards/admin-applications.html`. Add an `application_type` column and a type filter (free_trial / benefits_account / all). The existing stats block (pending / approved / spam / total_creators counts) stays; queries adjust to read the new table.
356 + - [ ] Update admin navigation (`admin_active_page: "waitlist"` → `"applications"`) and any cross-links in the admin shell.
357 + - [ ] Sitemap entry update, breadcrumb update.
358 +
359 + ### Tests + acceptance
360 +
361 + - [ ] Pin: a `pending` account cannot create projects (the existing `can_create_projects` guard already enforces this; verify the rendered panel works).
362 + - [ ] Pin: a "just pay" signup lands at `can_create_projects = true` AND an active Stripe subscription AND **no** `creator_applications` row.
363 + - [ ] Pin: admin queue lists pending applications sorted by `application_type` then `created_at`.
364 + - [ ] Pin: every removed "Apply for Creator Access" string is gone from `templates/` (grep test in `tests/regression/`).
365 + - [ ] Pin: founder rate applies regardless of branch during the cohort window (existing founder-pricing logic; new test asserts the multiplier doesn't depend on `application_type`).
366 +
367 + ### Out of scope (this restructure)
368 +
369 + - Partnership / sponsorship / residency / fellow-led-project applications — those continue via email, no form surface built. If we ever build them, the same `creator_applications` table can host them as additional `application_type` variants.
370 +
315 371 ## PoM contract guard (landed 2026-05-25)
316 372
317 373 Schema-drift guard test wired against `shared/pom-contract/`: `src/routes/pages/public/health/mod.rs::tests::pom_hetzner_health_expectations_resolve`. `health_json` body builder extracted as pure `health_json_body(overall, db_ok)` for the test. Catches the v0.5.16-class drift where a field is removed from `/api/health` without updating PoM's expectations. See `MNW/CLAUDE.md` § PoM Health Contract.