Re-cut of the 63-item backlog around one question: what is the shortest path to a product worth showing strangers, and what comes after it.
Order is unchanged from the previous revision. This revision re-costs the work against a real team, corrects estimates that assumed greenfield where code already exists, and adds per-item specs and acceptance criteria.
Costing assumes a standing team of five:
| Role | Count | Reads as |
|---|---|---|
| Backend | 2 | Supabase schema, RLS, migrations, triggers, API routes, Workers |
| Frontend | 2 | React Server Components, forms, feeds, client state, design system |
| Designer | 1 | Flows, specs, design-system extensions, QA against the built thing |
| Delivery | 4 eng | Designer is not a parallel build stream |
Units. eng-wks is one engineer working one week. cal-wks is calendar time for the whole
team on that item. They differ because most items do not split four ways.
Parallelism factor. Each item carries how many engineers it genuinely absorbs:
The designer is a lead indicator, not a lane. Design for item N+1 happens while engineering builds item N. Where an item is marked design-gated, engineering cannot start until the flows exist. Those are the items that stall a team when design runs late โ the designer's queue must lead the build queue by roughly one item throughout.
Overheads. All figures below are build-only. Add 30% for review, QA, the bug tail and deployment. The Calendar section applies this; per-item tables do not.
Four estimates were wrong, and one sizing convention was.
| Item | Was | Now | Why |
|---|---|---|---|
| 33 Search | L (4 wks) | M (2 wks) | api/search/route.ts and queries/search.ts already exist โ ilike across profiles, organisations, projects, articles. Not greenfield |
| 35 Transactional email | L (4 wks) | M (2.5 wks) | lib/email/ has a working Resend client, types and a user-email service. Domain auth, templates and preference centre remain |
| 25 Content reporting | S (0.5) | S (1 wk) | Split-out report button still needs a table, RLS, four entry points and an outcome notice. 0.5 was optimistic |
| 08 Legal pages | M (1.5) | M (1 wk) | In flight and further along than the backlog records |
Sizing convention. The previous revision used S=0.5, M=1.5, L=4, XL=9, XXL=18 dev-weeks โ roughly a third of the source backlog's own scale (S=2, M=3, L=6, XL=12, XXL=20). That gap was never reconciled and is the single largest source of disagreement between the two documents.
This revision keeps the compressed scale, for one defensible reason: the backlog's scale prices items for a team with no context on this codebase, and this team has 798 source files and 76 migrations of accumulated context. Where the two scales disagree, the backlog's figure is the outside view and should be treated as the pessimistic bound. The Calendar section carries both.
Articles, projects, comments, organisations, publish and hard-delete flows, automated moderation, mobile. That is a working content platform.
Verified against the tree, three things the backlog lists as unstarted are partly built:
ilike across four entity types, paginated, wired to a SearchBarNewEventDialog component exists; no schema, no calendarThe gap between "works" and "survives public traffic" is narrower than 63 items suggest โ but it is not zero, and the items that close it are currently scattered across Phase 2.
~6 eng-wks ยท ~3 cal-wks. Everything here is either a legal obligation or a thing that breaks the moment the platform is public. Nothing here is optional and nothing else belongs.
| # | Item | Size | eng-wks | Par | Owner | Why it can't wait |
|---|---|---|---|---|---|---|
| 08 | Legal pages (wip) | M | 1.0 | ร1 | FE | ToS, Privacy, Cookie. No EU signups without them |
| 15 | Feed filters (wip) | S | 0.5 | ร1 | FE | Already in flight โ finish it |
| 28 | Security hardening | M | 1.5 | ร2 | BE+FE | Turnstile on signup. Without it, bot floods in week one |
| 27 | Rate limiting & monitoring | M | 1.5 | ร1 | BE | Sentry and rate limits. You need to see what breaks |
| 30 | SEO & metadata | S | 0.5 | ร1 | FE | OG cards, sitemap. A content platform nobody can share isn't launched |
| 25 | Content reporting โ report button only | S | 1.0 | ร2 | BE+FE | DSA notice-and-action route |
08 โ Legal pages. Three static routes plus a consent modal. Cookie consent must gate analytics scripts, not merely record a preference โ a banner that sets a flag while GTM has already fired is not consent. Consent state in a first-party cookie readable server-side, so the modal does not flash on every load. Designer: modal states and the mobile treatment.
15 โ Feed filters. In flight on feat/tozn-441-feed-filters. Remaining: finish the
uncommitted FeedFilters.tsx / InputSelectBadge.tsx work, then resolve the filter-detection
bug already documented in docs/plans/feed-ssr-unfiltered.md โ Object.keys(filters).length > 0
counts keys whose value is undefined, so ?published=abc reads as a filtered request.
28 โ Security hardening. Turnstile on signup, login and password reset. XSS sanitation of all TipTap rich-text output โ server-side on write, never client-side only. Cloudflare Pro bot protections. Backend owns sanitation and token verification; frontend owns widget placement and challenge-failure states.
27 โ Rate limiting & monitoring. Sentry with source maps through the OpenNext build. Rate limits on auth, write and upload routes, keyed per user and per IP โ Workers KV or Durable Objects, not in-memory, because Workers isolates do not share state. Analytics/GTM behind the #08 consent gate.
30 โ SEO & metadata. generateMetadata on every public route, OG images for articles and
projects, sitemap.xml from published content, robots.txt, PWA manifest. Must not regress the
static-prerender path โ a cookies() call added here makes public pages dynamic.
25 โ Content reporting (button only). reports table, RLS allowing insert-by-any-
authenticated-user and read-by-staff-only, report action on articles, projects, comments and
profiles, reason taxonomy, duplicate suppression per reporter per object. Ships without a queue.
On splitting #25. The full item is M and includes a moderation queue that assumes the admin console exists. The legal obligation is narrower: a route for users to flag illegal content. A report button writing to a table, plus a person reading it, discharges that. The queue waits for #32.
Launch 0 is done when: an EU visitor can accept or reject cookies and rejection actually suppresses analytics; a bot cannot mass-register; an error in production reaches Sentry with a readable stack; a shared article renders a correct OG card; and any logged-in user can report any piece of content.
Deliberately out: notifications, search, i18n, versioning, payments. None block a beta, and three are XL.
Reordering note. Items 27, 28 and 30 sit in Phase 2 in the source backlog. Turnstile and error monitoring are launch-day infrastructure, not month-six polish. Moving them up is the single most consequential change in this document.
Why ~3 cal-wks and not 1.5. Six eng-wks across four engineers looks like 1.5 weeks. It is not: #08 and #15 are single-owner frontend items that serialise against each other, and #27 is single-owner backend. The critical path is FE1 running 08 โ 15 โ 30 at two weeks, plus integration and the consent/analytics interaction. Three weeks is the honest figure.
~19 eng-wks ยท ~7 cal-wks. Launch 0 gets people in the door. This is what stops them leaving. Ordered by retention impact per eng-week.
Tier A โ a reason to come back
| # | Item | Size | eng-wks | Par | Owner | Note |
|---|---|---|---|---|---|---|
| 35 | Transactional email | M | 2.5 | ร1 | BE | Must come first; 16 and 26 both sit on it |
| 16 | Notifications, first release | L | 4.0 | ร2 | BE+FE | The single biggest return-visit driver |
| 42 | Article reactions | S | 0.5 | ร1 | FE | Cheapest engagement signal, and it feeds ranking later |
| 38 | Notes & bookmarks | M | 1.5 | ร2 | BE+FE | A personal library makes the platform sticky |
Tier B โ a reason to bring others
| # | Item | Size | eng-wks | Par | Owner | Note |
|---|---|---|---|---|---|---|
| 26 | User-to-user invites | L | 4.0 | ร2 | BE+FE | The growth loop; alpha badges already prime it |
| 39 | Connections & blocking | M | 2.0 | ร2 | BE+FE | The social graph; blocking is a safety floor |
| 40 | Privacy settings | M | 1.5 | ร1 | FE | Depends on 39 |
Tier C โ findability
| # | Item | Size | eng-wks | Par | Owner | Note |
|---|---|---|---|---|---|---|
| 33 | Search | M | 2.0 | ร2 | BE+FE | Re-sized down โ partial build exists |
35 โ Transactional email. Builds on the existing Resend client. Remaining: SPF/DKIM/DMARC on
the sending domain, a template system beyond the single hard-coded ID in lib/email/templates.ts,
plain-text fallbacks, per-type routing with unsubscribe and a preference centre, bounce and
complaint suppression, transactional/marketing separation with consent records. Domain warm-up
is calendar time, not work โ start DNS in Launch 0 so reputation is building before #16 needs it.
16 โ Notifications, first release. Five live groups only: posts, projects, articles, organisation membership, own membership. Bell with unread count, dropdown, dedicated page, read/seen state. Cross-account addressing so a notification belongs to an organisation or a person โ this is the schema decision that is expensive to retrofit; get it right now. Interval-polled count, realtime deferred. Registration hooks so later features add types without a migration. Design-gated: bell, panel, empty and overflow states.
42 โ Article reactions. Extends the existing reactions table. Optimistic UI, per-user
uniqueness enforced in the database rather than the client.
38 โ Notes & bookmarks. Extends the existing bookmarks table with private notes. Personal
library view with filtering. RLS: owner-only read and write, no exceptions.
26 โ User-to-user invites. Per-user invite links with attribution, acceptance bound at signup, quota and abuse limits, inviter-facing status list. Depends on #35 for delivery. Attribution must survive the auth round trip โ cookie set pre-signup, consumed in the callback.
39 โ Connections & blocking. Rewire the existing connection system into profile pages and re-enable blocking. Blocking must be enforced in RLS or shared query helpers, not per-call โ every feed, search and comment path has to honour it, and a per-call check will be missed somewhere. This is the item most likely to overrun.
40 โ Privacy settings. Settings area binding visibility rules to the #39 enforcement layer. Adds no new enforcement of its own.
33 โ Search. Replace ilike with Postgres full-text: tsvector columns, GIN indexes,
websearch_to_tsquery, trigger-maintained on write. Ranking, filters, result-type tabs,
permission-aware results honouring drafts and #39 blocks. Re-index hooks for later content
types. No external search infrastructure at this volume.
Unchanged: 35 โ 16 โ 42 โ 26 โ 39 โ 40 โ 38 โ 33.
Two streams, as before:
BE1+FE1 35 โโโโ 16 โโโโโโโโ 26 โโโโโโโโ
BE2+FE2 42 โโ 38 โโ 39 โโ 40 โโ 33
Design 16 โโ 26 โโ 39/40 โโ 33
Tier C sits last by intent. At current content volume browsing works and feed filters cover it; ship search when the archive is large enough that browsing fails.
A user who leaves for a week receives a reason to return that is not an email blast; blocking holds across every surface including search; and an invited user's attribution survives signup.
~11 eng-wks ยท ~5 cal-wks. Chosen over the creator-economy track. Reasoning below.
12 Versioning (M)
โโโ 13 Articles โ reviews (M)
โโโ 23 Educational Resources (L) โ 52 Quizzes (L)
| # | Item | Size | eng-wks | Par | Owner | Note |
|---|---|---|---|---|---|---|
| 12 | Content versioning | M | 1.5 | ร1 | BE | Blocks everything below it |
| 23 | Educational Resources | L | 4.0 | ร3 | BE+FE | Widest item in this launch |
| 13 | Articles โ reviews | M | 2.0 | ร2 | BE+FE | Binds to a version, not to a row |
| 52 | Quizzes | L | 3.5 | ร2 | BE+FE | Anti-cheat before PRG is on the line |
12 โ Content versioning. Immutable snapshot on every publish and republish. History and diff
views. Reviews, citations and later PRG rewards bind to a version_id. Restore from an earlier
version. Interaction with retention windows and hard deletion โ a version cannot outlive a GDPR
erasure. Storage and pruning policy, because unbounded snapshots of TipTap JSON grow fast.
Versioning goes first, and this is not negotiable. Reviews and citations bind to a specific version of a piece, not to whatever the author edits it into afterwards. Ship reviews before versioning and every review collected becomes unbindable โ retrofitting means invalidating them. #12 is M. Doing it after is not.
23 โ Educational Resources. Category/subcategory hierarchy and subject pages, resource authoring, Foundation curation workflow, reference and citation handling. Curation is Foundation-run here; the DAO inclusion queue is Phase 4. Design-gated โ the heaviest design load in the roadmap, and the designer must lead by two items, not one.
13 โ Articles โ reviews. Structured peer review against a pinned version. Reviewer eligibility, review lifecycle, public display. The attestation surface Phase 4 later pays PRG against โ keep the review record shaped so an attestor signature can attach without a migration.
52 โ Quizzes. Authoring, question bank, answer storage, taking, scoring, attempt history, per-learner progress. Answers never reach the client. Scoring is server-side, and the question payload excludes the correct answer โ retrofitting that after Learn2Earn pays PRG means re-issuing every grade.
The alternative track is 19 โ 21 โ 20 โ 22 (Stripe, tipping, funding, paywalls) at roughly 31 eng-weeks, and 20/21/22 all want the admin console (#32, XL) underneath them for refunds and disputes.
Learning is ~3ร cheaper, differentiates the platform, matches the conservation positioning, and carries no regulatory surface. Its weakness is that it pays nobody.
The hedge: after the learning track, ship 19 (Stripe) โ 21 (Tipping) as a narrow slice โ about 13 further eng-weeks. That proves the money rail works and gives contributors a reason to show up, without committing to funding rounds, paywalls, tax reporting and dispute handling before anyone has asked for them.
Stripe Connect onboarding is the long pole inside #19, and it is partly external: KYC verification states are Stripe's timeline, not yours.
Total for learning plus tipping: ~24 eng-weeks.
Build-only figures above, +30% overhead applied, four engineers.
| Milestone | eng-wks | +30% | Compressed scale | Backlog scale |
|---|---|---|---|---|
| Launch 0 โ public beta | 6 | 7.8 | ~3 wks | ~6 wks |
| + Launch 1 โ retention | 25 | 32.5 | ~10 wks | ~20 wks |
| + Launch 2 โ learning | 36 | 46.8 | ~15 wks | ~30 wks |
| + Stripe & tipping | 49 | 63.7 | ~21 wks | ~40 wks |
Read the two right-hand columns as a range, not a choice. The compressed column assumes the team keeps its current context and nobody leaves. The backlog column is the outside view. Plan against the compressed figure, commit externally against the backlog one.
Calendar time does not scale with headcount inside a launch. Launch 0 is ~3 calendar weeks with four engineers and ~6 with one โ but it is also ~3 with eight, because the critical path is one frontend engineer running three serialised items. Launch 1 parallelises best: two clean streams for most of its length.
The designer is the hidden critical path. Items 16, 23, 26, 39/40 and 52 are design-gated. One designer feeding four engineers works only while the design queue leads by a full item. It does not survive Launch 2, where #23 alone is a multi-week design effort โ that is the point to either buy contract design or accept that engineering idles.
Named here so they stop occupying planning attention. Order unchanged.
| # | Item | Why not yet |
|---|---|---|
| 43 | Recommendation & ranking (XXL) | Needs a user base and engagement history that don't exist yet |
| 45 | Messaging (XL) | Large, and DM abuse surface is real operational load |
| 46 | Notifications second pass (XL) | Wait until the first pass has told you what's missing |
| 34 | Internationalisation (XL) | See below โ decide, don't drift |
| 32 | Admin console (XL) | Needed before funding or paywalls; not before them |
| 24 | Open Calls (XL) | Depends on #32 and #16 |
| 47โ63 | Token economy | Start #48 when token work gets a real date, not before |
i18n (#34). Its cost scales with shipped surface area, so every month it waits it gets more expensive. Either commit to it in the next twelve months or accept the retrofit consciously โ what is expensive is leaving it undecided while the surface grows. Concretely: the cheap mitigation is a string-extraction discipline from now on, which costs little and preserves the option.
Regulatory assessment (#48). A 4โ12 week external gate on ~85 eng-weeks of Phase 4 work. Irrelevant until token work has a date. Fatal if started at Phase 4 time rather than before it. The moment the token economy gets a quarter, this starts.
Tokenomics (#47). The published parameters let $OZN be minted below intended cost: tipping earns 10 PRG per US$1 while 100 PRG staked wins 1 $OZN for 50 PRG, so self-dealing between accounts mints $OZN for the transaction fee alone. This is a live problem in a public document, not a future build task โ the white paper is already published with these figures. Fixing the parameters is cheap now and expensive once contracts are audited.
Three constraints decide whether those numbers hold: the designer's queue must lead the build queue throughout; blocking (#39) must be enforced in one place rather than per-call; and versioning (#12) must land before reviews. Everything beyond that is a decision for a team that has users.