Skip to main content

max / makenotwork

Add tips, revenue splits, doc improvements, discover sort rename Tips feature: - Tips table, project_members table, revenue_splits table (migration 058) - Tip checkout route (POST /stripe/checkout/tip/{recipient_id}) - Tip webhook handler (checkout.session.completed dispatch) - Tip notification email - tips_enabled/notify_tip user preferences - Tip button partial on user profile and project pages - Tip checkout params and metadata in payments module Revenue splits infrastructure: - project_members table with split percentages - revenue_splits table linking to tips or transactions - DB queries for member CRUD, split recording, split queries Documentation: - Rename "Service Level Agreement" to "What We Guarantee" across all docs - Add shutdown cost estimate to guarantees page - Add debt-free statement to how-we-work and economics pages - Add PolyForm Noncommercial rationale to how-we-work - Add AI policy mention to how-we-work - Surface residency program on how-we-work - Update earn-back/content-archive from "not yet implemented" to "launching before beta ends" - Add pricing calculator link to how-we-work and economics - Add storefront customization section to profile guide - Add small-ticket pricing note to pricing calculator - Grey out Big Files/Streaming tiers on pricing calculator - Add Ko-fi comparison gaps to todo.md - Tips and embeds feature plans (docs/internal/) Discover sort: - Rename DiscoverSort::Popular to MostSold (sort by sales_count) v0.3.26 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author: Max J. <87768334+MaxJMath@users.noreply.github.com> · 2026-04-23 03:10 UTC
Commit: 99c743da79ebb454823eed3ae7d14007ddae2a7b
Parent: 435d0d3
45 files changed, +1817 insertions, -64 deletions
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "makenotwork"
3 - version = "0.3.25"
3 + version = "0.3.26"
4 4 edition = "2024"
5 5 license-file = "LICENSE"
6 6
@@ -0,0 +1,264 @@
1 + # Embeddable Widgets
2 +
3 + Lightweight embeds that let creators put MNW buy buttons, audio previews, and product cards on external websites.
4 +
5 + ---
6 +
7 + ## Why
8 +
9 + Ko-fi's embed model is how many creators discover the platform — a button on a blog, a widget in a stream overlay, a card in a portfolio site. MNW currently requires fans to visit makenot.work directly. Embeds extend the storefront to wherever the creator already has an audience: their personal site, a blog post, a forum, a link-in-bio page.
10 +
11 + This also complements the tips feature — a "support this creator" embed is the simplest possible widget and the most natural entry point for fans who haven't visited MNW before.
12 +
13 + ---
14 +
15 + ## How It Works
16 +
17 + 1. Creator goes to an item or their profile in the dashboard
18 + 2. Clicks "Get embed code"
19 + 3. Copies an HTML snippet (iframe or script tag)
20 + 4. Pastes it into their external site
21 + 5. Visitors see a styled card/button that links to MNW for checkout
22 +
23 + All embeds are read-only views. No checkout happens inside the embed — clicking "Buy" or "Support" opens MNW in a new tab (or a popup, see overlay variant below). This avoids cross-origin payment complexity and keeps Stripe Checkout on our domain.
24 +
25 + ---
26 +
27 + ## Embed Types
28 +
29 + ### 1. Buy Button
30 +
31 + Minimal embed. Shows item title, price, and a buy button. Clicking opens the purchase page on MNW.
32 +
33 + ```
34 + Dimensions: ~300x60px (horizontal strip)
35 + Content: Item title | Price | [Buy] button
36 + URL: /embed/i/{item_id}/button
37 + ```
38 +
39 + Use case: inline in a blog post, sidebar widget, link-in-bio page.
40 +
41 + ### 2. Product Card
42 +
43 + Richer embed. Shows cover art, title, creator name, price, and description excerpt.
44 +
45 + ```
46 + Dimensions: ~350x400px (vertical card) or ~600x200px (horizontal card)
47 + Content: Cover image, title, creator, price, description (truncated), [Buy] button
48 + URL: /embed/i/{item_id}/card
49 + Variants: ?layout=vertical (default) | ?layout=horizontal
50 + ```
51 +
52 + Use case: portfolio site, project page, "my latest release" section.
53 +
54 + ### 3. Audio Preview
55 +
56 + For audio items. Shows cover art, title, 30-second preview player, and buy button. Preview plays directly in the embed (no redirect needed for preview — only for purchase).
57 +
58 + ```
59 + Dimensions: ~350x120px (horizontal)
60 + Content: Cover image (small), title, 30-sec waveform/progress bar, play/pause, price, [Buy] button
61 + URL: /embed/i/{item_id}/player
62 + Audio source: /embed/i/{item_id}/preview.mp3 (30-sec clip, generated server-side)
63 + ```
64 +
65 + Use case: music blog, artist website, social media link page.
66 +
67 + ### 4. Tip Button
68 +
69 + For creators with tips enabled. Shows creator name/avatar and a "Support" button.
70 +
71 + ```
72 + Dimensions: ~250x50px (horizontal strip)
73 + Content: Creator avatar (small) | "Support @username" | [Tip] button
74 + URL: /embed/u/{username}/tip
75 + ```
76 +
77 + Use case: personal website footer, blog sidebar, about page.
78 +
79 + ### 5. Project Card
80 +
81 + Shows project cover, title, creator, item count, and a link to the project page.
82 +
83 + ```
84 + Dimensions: ~350x300px (vertical card)
85 + Content: Project cover, title, creator, item count, description (truncated), [View] button
86 + URL: /embed/p/{project_slug}/card
87 + ```
88 +
89 + Use case: creator's external portfolio showing their MNW projects.
90 +
91 + ---
92 +
93 + ## Technical Design
94 +
95 + ### Routes
96 +
97 + | Method | Path | Returns | Auth |
98 + |--------|------|---------|------|
99 + | GET | `/embed/i/{item_id}/button` | HTML page (iframe content) | None |
100 + | GET | `/embed/i/{item_id}/card` | HTML page (iframe content) | None |
101 + | GET | `/embed/i/{item_id}/player` | HTML page (iframe content) | None |
102 + | GET | `/embed/i/{item_id}/preview.mp3` | 30-sec audio clip | None |
103 + | GET | `/embed/u/{username}/tip` | HTML page (iframe content) | None |
104 + | GET | `/embed/p/{project_slug}/card` | HTML page (iframe content) | None |
105 +
106 + All embed routes are public (no auth required). They serve self-contained HTML pages designed to be loaded in iframes.
107 +
108 + ### Embed HTML Structure
109 +
110 + Each embed is a standalone HTML page with:
111 + - Inline CSS (no external stylesheet dependency)
112 + - MNW brand styling (beige background, charcoal text, violet accent — matches platform)
113 + - Responsive within its container
114 + - No JavaScript required for basic embeds (button, card, project card)
115 + - Minimal JS for audio preview player only
116 + - All links open in `_blank` (new tab) via `target="_blank" rel="noopener"`
117 +
118 + ### Embed Code Generator
119 +
120 + On the item dashboard page and creator settings, add an "Embed" section that shows:
121 +
122 + ```html
123 + <!-- Buy Button -->
124 + <iframe src="https://makenot.work/embed/i/{item_id}/button"
125 + width="300" height="60" frameborder="0"
126 + title="Buy {item_title} on Makenot.work"></iframe>
127 +
128 + <!-- Product Card -->
129 + <iframe src="https://makenot.work/embed/i/{item_id}/card"
130 + width="350" height="400" frameborder="0"
131 + title="{item_title} on Makenot.work"></iframe>
132 +
133 + <!-- Audio Preview -->
134 + <iframe src="https://makenot.work/embed/i/{item_id}/player"
135 + width="350" height="120" frameborder="0"
136 + title="Preview {item_title} on Makenot.work"></iframe>
137 + ```
138 +
139 + Copy-to-clipboard button for each variant.
140 +
141 + ### CORS & Security
142 +
143 + - Embed routes set `X-Frame-Options: ALLOWALL` (or omit the header) to permit iframe embedding on any domain
144 + - Embed routes set `Content-Security-Policy: frame-ancestors *` to allow embedding anywhere
145 + - All other MNW routes retain `X-Frame-Options: DENY` (no change to existing security)
146 + - Embed pages contain no forms, no auth, no cookies — purely read-only
147 + - Links to checkout/purchase pages open in new tabs on makenot.work where normal auth and CSRF apply
148 +
149 + ### Audio Preview Generation
150 +
151 + For the audio player embed, generate a 30-second preview clip:
152 +
153 + - **When**: On first request to `/embed/i/{item_id}/preview.mp3`, generate and cache
154 + - **How**: ffmpeg on the server — extract 30 seconds starting at a configurable offset (default: 0s, creator can set preview start time in item settings)
155 + - **Format**: MP3 128kbps (small, universally playable)
156 + - **Storage**: Cache in S3 alongside the original file (`{s3_key}.preview.mp3`)
157 + - **Cache**: Serve from S3 cache on subsequent requests. Invalidate if source file changes.
158 + - **Fallback**: If item has no audio (non-audio item type), `/preview.mp3` returns 404
159 +
160 + Optional enhancement (deferred): let creators set preview start/end times in item settings. Default to first 30 seconds.
161 +
162 + ### Caching
163 +
164 + - Embed HTML responses: `Cache-Control: public, max-age=300` (5 minutes). Short enough that price changes reflect quickly, long enough to avoid hammering the DB on popular embeds.
165 + - Preview audio: `Cache-Control: public, max-age=86400` (1 day). Regenerate only on source file change.
166 + - Cover images: already served from S3/CDN with existing cache headers.
167 +
168 + ---
169 +
170 + ## Data Model Changes
171 +
172 + ### Item table addition (optional)
173 +
174 + | Column | Type | Notes |
175 + |--------|------|-------|
176 + | `preview_start_seconds` | INT, nullable | Where the 30-sec preview starts (default 0) |
177 +
178 + This is optional for v1 — default to first 30 seconds. Add later if creators want control.
179 +
180 + ### No other schema changes needed
181 +
182 + Embeds are read-only views over existing data. No new tables required.
183 +
184 + ---
185 +
186 + ## What Embeds Do NOT Do
187 +
188 + - **No checkout inside the embed.** Clicking "Buy" opens MNW in a new tab. Stripe Checkout requires our domain. This is simpler, more secure, and avoids cross-origin iframe payment issues.
189 + - **No authentication.** Embeds are always the public/anonymous view. If the fan already owns the item, the embed still shows the buy button — they'll see "already in library" when they click through.
190 + - **No tracking.** No analytics cookies, no referrer tracking, no pixel. The embed is a static view. We know someone loaded it (server log) but we don't track who or where.
191 + - **No JavaScript widget/SDK.** Just iframes. A JS snippet that injects an iframe is a possible future enhancement (easier copy-paste for non-technical creators), but v1 is plain iframe embeds.
192 +
193 + ---
194 +
195 + ## Overlay Variant (Deferred)
196 +
197 + A future enhancement: instead of opening a new tab, clicking "Buy" opens a popup/modal on the external site that loads the MNW checkout page. This keeps the fan on the creator's site.
198 +
199 + Implementation: a small JS script (`<script src="https://makenot.work/embed/widget.js">`) that intercepts embed buy-button clicks and opens a centered popup window. The popup loads the normal MNW purchase page. On successful checkout, the popup closes and the embed updates to show "Purchased."
200 +
201 + This requires:
202 + - `widget.js` served from MNW
203 + - postMessage communication between popup and parent
204 + - Popup fallback for browsers that block popups
205 +
206 + Deferred because iframes work today and the popup UX has edge cases (popup blockers, mobile browsers). Revisit after v1 embeds ship and we get creator feedback.
207 +
208 + ---
209 +
210 + ## UI: Embed Code in Dashboard
211 +
212 + ### Item dashboard (`/dashboard/items/{id}`)
213 + - New "Embed" section or tab
214 + - Shows all applicable embed variants for that item type:
215 + - All items: Buy Button, Product Card
216 + - Audio items: + Audio Preview
217 + - Each variant: live preview + copyable code snippet
218 + - Layout toggle for product card (vertical/horizontal)
219 +
220 + ### Creator settings or profile dashboard
221 + - Tip Button embed code (if tips enabled)
222 +
223 + ### Project dashboard (`/dashboard/projects/{id}`)
224 + - Project Card embed code
225 +
226 + ---
227 +
228 + ## Implementation Order
229 +
230 + 1. **Buy button embed** — simplest, most useful, proves the routing and CORS setup
231 + 2. **Product card** — richer, uses cover images, validates the styling approach
232 + 3. **Tip button** — depends on tips feature being implemented first
233 + 4. **Audio preview player** — most complex (ffmpeg preview generation, JS player in embed)
234 + 5. **Project card** — straightforward once product card pattern exists
235 + 6. **Embed code generator UI** — add to dashboard after at least button + card work
236 + 7. **Overlay popup** (deferred) — revisit based on creator feedback
237 +
238 + ---
239 +
240 + ## Templates
241 +
242 + New template directory: `templates/embeds/`
243 +
244 + ```
245 + templates/embeds/
246 + button.html -- buy button strip
247 + card.html -- product card (vertical + horizontal)
248 + player.html -- audio preview with mini player
249 + tip_button.html -- tip/support button
250 + project_card.html -- project card
251 + ```
252 +
253 + Each template is a full HTML page (not a partial — no `{% extends "base.html" %}`). Inline styles only. No external CSS or JS dependencies. Must render correctly inside an iframe with no parent page context.
254 +
255 + ---
256 +
257 + ## Testing
258 +
259 + - Integration tests for each embed route (returns 200, correct content-type, no auth required)
260 + - Test that non-public items return 404 on embed routes
261 + - Test CORS/frame headers are set correctly on embed routes and NOT changed on other routes
262 + - Test audio preview generation (mock ffmpeg or use a test fixture)
263 + - Test embed code generator produces valid HTML
264 + - Manual test: embed on a local HTML file, verify rendering and click-through
@@ -0,0 +1,177 @@
1 + # Tips Feature
2 +
3 + One-time payments to a creator without a product attached. No file delivery, no license keys, no inventory. Just money in, receipt out.
4 +
5 + ---
6 +
7 + ## Why
8 +
9 + Ko-fi's core feature. Many creators receive more from tips than from sales — especially early on when they have an audience but haven't built a catalog yet. Tips also lower the barrier for fans: "I like what you do" is easier than "I want to buy this specific thing." Adding tips makes MNW viable for creators who aren't ready to sell products but want to accept support while they build.
10 +
11 + Tips also feed the embeddable widget feature — a "support this creator" button on an external site is the simplest possible embed.
12 +
13 + ---
14 +
15 + ## How It Works
16 +
17 + 1. Creator enables tips on their profile (off by default, toggle in settings)
18 + 2. Fan visits `/u/username` or `/p/project-slug`, sees a "Support" button
19 + 3. Fan enters an amount (minimum $1, no maximum) and an optional short message
20 + 4. Redirected to Stripe Checkout on the creator's connected account
21 + 5. On success: transaction recorded, creator notified, fan sees confirmation
22 + 6. No item delivered, no library entry created — just a payment record and optional message
23 +
24 + ---
25 +
26 + ## Scope
27 +
28 + ### In Scope
29 + - Enable/disable tips per creator (profile-level toggle)
30 + - Fan-chosen amount with minimum ($1)
31 + - Optional short message (280 chars, plain text)
32 + - Stripe Checkout session on creator's connected account (same direct-charge model as purchases)
33 + - Webhook handler for completed tips
34 + - Tips appear in creator's transaction history and analytics
35 + - Tips appear in fan's payment history
36 + - Email notification to creator on tip received
37 + - Tip button on creator profile page and project pages
38 + - Tips included in data export
39 + - Tips count toward earn-back credit calculation
40 +
41 + ### Out of Scope (for now)
42 + - Recurring tips / monthly support (subscriptions already cover this)
43 + - Tip goals / fundraising progress bars (separate feature, see todo.md)
44 + - Anonymous tips (Stripe requires identity on their end anyway)
45 + - Tipping on individual items (too close to PWYW, which already exists)
46 +
47 + ---
48 +
49 + ## Data Model
50 +
51 + ### New table: `tips`
52 +
53 + | Column | Type | Notes |
54 + |--------|------|-------|
55 + | `id` | UUID PK | |
56 + | `tipper_id` | UUID FK → users | Fan who tipped |
57 + | `recipient_id` | UUID FK → users | Creator who received |
58 + | `project_id` | UUID FK → projects, nullable | If tipped from a project page |
59 + | `amount_cents` | INT, CHECK > 0 | |
60 + | `message` | TEXT, nullable | 280 char limit enforced in app |
61 + | `status` | VARCHAR(20) | pending → completed / failed |
62 + | `stripe_payment_intent_id` | VARCHAR(255) | |
63 + | `stripe_checkout_session_id` | VARCHAR(255) | |
64 + | `created_at` | TIMESTAMPTZ | |
65 + | `completed_at` | TIMESTAMPTZ, nullable | |
66 +
67 + Indexes: `(recipient_id, created_at DESC)`, `(tipper_id, created_at DESC)`.
68 +
69 + **Why a separate table instead of reusing `transactions`?** Transactions have `item_id` as a core concept, and the webhook handler branches on metadata type to determine post-checkout behavior (license keys, file access grants, library entries, sales count increments). Tips need none of that. A separate table keeps the webhook handler clean and avoids nullable `item_id` semantics leaking into transaction queries. Tips still appear in analytics and export by joining or unioning where needed.
70 +
71 + ### User table addition
72 +
73 + | Column | Type | Notes |
74 + |--------|------|-------|
75 + | `tips_enabled` | BOOLEAN DEFAULT false | Creator opt-in |
76 +
77 + ---
78 +
79 + ## Routes
80 +
81 + | Method | Path | Handler | Auth |
82 + |--------|------|---------|------|
83 + | POST | `/stripe/checkout/tip/{recipient_id}` | Create tip checkout session | Logged in |
84 + | GET | `/stripe/tip/success?session_id={id}` | Tip success redirect | Logged in |
85 +
86 + Webhook handling reuses `POST /stripe/webhook` — add a new metadata type `TipCheckoutMetadata` with `tipper_id`, `recipient_id`, `project_id`, `message`. The webhook handler dispatches on metadata type (same pattern as existing item vs subscription vs fan-plus checkout discrimination).
87 +
88 + ---
89 +
90 + ## Checkout Session
91 +
92 + Same direct-charge model as item purchases:
93 +
94 + ```
95 + session created on creator's connected account via with_stripe_account()
96 + application_fee_amount omitted (0% platform fee)
97 + metadata: { type: "tip", tipper_id, recipient_id, project_id?, message? }
98 + mode: "payment" (one-time, not subscription)
99 + ```
100 +
101 + Amount is fan-chosen. The checkout form on MNW collects the amount and message, then creates the Stripe session with that amount. Stripe Checkout handles the actual payment UI.
102 +
103 + ---
104 +
105 + ## UI
106 +
107 + ### Creator profile page (`/u/username`)
108 + - If `tips_enabled`: show "Support" button below bio/links
109 + - Clicking opens a small inline form: amount input ($1 min), optional message textarea, submit button
110 + - Submit POSTs to `/stripe/checkout/tip/{recipient_id}`, redirects to Stripe
111 +
112 + ### Project page (`/p/slug`)
113 + - Same "Support" button if creator has tips enabled
114 + - `project_id` included in metadata so creator can see which project inspired the tip
115 +
116 + ### Creator dashboard
117 + - Tips tab or section in analytics showing: total tips received, recent tips with amounts and messages
118 + - Tips included in revenue totals and charts (distinguished from sales in breakdown)
119 +
120 + ### Fan payment history
121 + - Tips appear as "Tip to @username" with amount and date
122 +
123 + ### Creator settings
124 + - Toggle: "Accept tips on your profile and project pages"
125 +
126 + ---
127 +
128 + ## Notifications
129 +
130 + - Email to creator on tip received: "@username tipped you $X" with message if present
131 + - Reuses existing email notification infrastructure (Postmark)
132 + - Respects creator's notification preferences (new `tip_notifications` toggle, default on)
133 +
134 + ---
135 +
136 + ## Export
137 +
138 + Tips included in creator data export as `tips.csv`:
139 + - date, amount, tipper_username, message, status
140 +
141 + Tips included in fan data export as `tips_sent.csv`:
142 + - date, amount, recipient_username, message, status
143 +
144 + ---
145 +
146 + ## Analytics
147 +
148 + - Tips contribute to revenue totals on dashboard
149 + - Revenue chart distinguishes tips from sales (separate series or breakout)
150 + - "Tips received" count as a dashboard metric
151 + - Tips count toward earn-back credit calculation (creator earned revenue on the platform)
152 +
153 + ---
154 +
155 + ## Edge Cases
156 +
157 + - **Creator disables tips after receiving some**: Existing tip records remain. No new tip button shown. Pending checkouts still complete (Stripe session already created).
158 + - **Creator doesn't have Stripe connected**: Tip button not shown (same guard as purchase buttons).
159 + - **Fan tips themselves**: Prevented — recipient_id != session user check.
160 + - **Minimum amount**: $1.00 (below this, Stripe's $0.30 fixed fee makes it irrational for the fan).
161 + - **Maximum amount**: No platform maximum. Stripe's own limits apply.
162 + - **Message content**: Plain text only, 280 chars, no markup. Displayed as-is to creator. Standard content policy applies (harassment via tip messages = moderation action on tipper's account).
163 +
164 + ---
165 +
166 + ## Migration Path
167 +
168 + 1. Migration: add `tips` table, add `tips_enabled` column to `users`
169 + 2. `db::tips` module: `create_tip`, `complete_tip`, `tips_for_recipient`, `tips_by_user`
170 + 3. `payments/checkout.rs`: `create_tip_checkout_session`
171 + 4. `routes/stripe/checkout/tips.rs`: POST handler
172 + 5. `routes/stripe/webhook/checkout.rs`: add `TipCheckoutMetadata` branch
173 + 6. Templates: tip button partial, tip form, success page
174 + 7. Dashboard: tips in analytics, tips in transaction history
175 + 8. Settings: tips toggle
176 + 9. Export: tips in data export
177 + 10. Tests: checkout creation, webhook completion, analytics aggregation, export inclusion
@@ -195,6 +195,23 @@ v0.3.23. Audit grade A. ~1,233 tests.
195 195 - [ ] Shipping address collection at checkout
196 196 - [ ] Order management in creator dashboard (mark shipped, tracking number)
197 197
198 + ### Ko-fi Comparison Gaps (2026-04-22)
199 + Weak points identified vs Ko-fi. Ordered by effort/impact.
200 +
201 + #### Easy Wins
202 + - [ ] Tips/donations — accept one-time payments without a product attached (Ko-fi's core feature, trivial on Stripe, no inventory/file delivery needed)
203 + - [ ] Embeddable widgets — buy button / audio preview / checkout popup for external sites (Ko-fi's embed model is how many creators discover the platform)
204 + - [ ] Fundraising goals — display campaign target + progress bar on project page (simple DB field + UI, high engagement signal)
205 +
206 + #### Medium Effort
207 + - [ ] Commissions — listing with portfolio, slot limits, client messaging, upfront payment (Ko-fi has full workflow; artists expect this)
208 + - [ ] Physical product listings — already planned above in Phase 20C
209 +
210 + #### Structural Gaps (acknowledged, not urgent)
211 + - [ ] Zero-cost entry — Ko-fi free tier costs $0 and takes 0% on tips. MNW's minimum is $10/mo. Earn-back credit softens this but doesn't eliminate the barrier for artists earning nothing yet. No action needed — this is a deliberate model difference, not a bug.
212 + - [ ] Social integrations — Ko-fi integrates with Discord (roles for supporters), WordPress, Zapier. MNW has none. Consider Discord webhook or Zapier integration post-beta.
213 + - [ ] Moderation team size — Ko-fi has dedicated Trust & Safety staff. MNW is one person. Acknowledged in docs, hiring is priority #2 in surplus allocation.
214 +
198 215
199 216 ### Phase 21: Scheduled Content — Remaining
200 217 - [ ] Pre-save + pre-order, countdown display, calendar view
@@ -0,0 +1,72 @@
1 + -- Tips, project members, and revenue splits.
2 + --
3 + -- Project members allow multi-author projects with configurable revenue splits.
4 + -- Tips are one-time payments to a creator without a product attached.
5 + -- Revenue splits apply to tips AND regular item/project purchases.
6 +
7 + -- ── Project Members ──
8 +
9 + CREATE TABLE project_members (
10 + id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
11 + project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
12 + user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
13 + role VARCHAR(50) NOT NULL DEFAULT 'member',
14 + split_percent SMALLINT NOT NULL CHECK (split_percent >= 0 AND split_percent <= 100),
15 + added_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
16 + added_by UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
17 + UNIQUE (project_id, user_id)
18 + );
19 +
20 + CREATE INDEX idx_project_members_project ON project_members (project_id);
21 + CREATE INDEX idx_project_members_user ON project_members (user_id);
22 +
23 + -- ── Tips ──
24 +
25 + CREATE TABLE tips (
26 + id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
27 + tipper_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
28 + recipient_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
29 + project_id UUID REFERENCES projects(id) ON DELETE SET NULL,
30 + amount_cents INT NOT NULL CHECK (amount_cents > 0),
31 + message VARCHAR(280),
32 + status VARCHAR(20) NOT NULL DEFAULT 'pending',
33 + stripe_payment_intent_id VARCHAR(255),
34 + stripe_checkout_session_id VARCHAR(255),
35 + stripe_transfer_group VARCHAR(255),
36 + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
37 + completed_at TIMESTAMPTZ
38 + );
39 +
40 + CREATE INDEX idx_tips_recipient ON tips (recipient_id, created_at DESC);
41 + CREATE INDEX idx_tips_tipper ON tips (tipper_id, created_at DESC);
42 +
43 + -- ── Revenue Splits ──
44 + -- Records the actual split of a payment after it completes.
45 + -- Created for both tips and item purchases when the project has members.
46 +
47 + CREATE TABLE revenue_splits (
48 + id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
49 + -- Exactly one of tip_id or transaction_id is set
50 + tip_id UUID REFERENCES tips(id) ON DELETE CASCADE,
51 + transaction_id UUID REFERENCES transactions(id) ON DELETE CASCADE,
52 + recipient_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
53 + amount_cents INT NOT NULL CHECK (amount_cents >= 0),
54 + split_percent SMALLINT NOT NULL,
55 + stripe_transfer_id VARCHAR(255),
56 + status VARCHAR(20) NOT NULL DEFAULT 'pending',
57 + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
58 + completed_at TIMESTAMPTZ,
59 + CHECK (
60 + (tip_id IS NOT NULL AND transaction_id IS NULL)
61 + OR (tip_id IS NULL AND transaction_id IS NOT NULL)
62 + )
63 + );
64 +
65 + CREATE INDEX idx_revenue_splits_tip ON revenue_splits (tip_id) WHERE tip_id IS NOT NULL;
66 + CREATE INDEX idx_revenue_splits_transaction ON revenue_splits (transaction_id) WHERE transaction_id IS NOT NULL;
67 + CREATE INDEX idx_revenue_splits_recipient ON revenue_splits (recipient_id, created_at DESC);
68 +
69 + -- ── User tips toggle ──
70 +
71 + ALTER TABLE users ADD COLUMN tips_enabled BOOLEAN NOT NULL DEFAULT false;
72 + ALTER TABLE users ADD COLUMN notify_tip BOOLEAN NOT NULL DEFAULT true;
@@ -0,0 +1,149 @@
1 + # Platform Economics
2 +
3 + What it costs to run Makenot.work, how subscriptions cover it, and where the money goes.
4 +
5 + ---
6 +
7 + ## Why Publish This
8 +
9 + Most platforms treat their economics as proprietary. We think that's backwards. If you're paying us $10-40/month, you should know what that money does. This page is a plain-language accounting of our cost structure, what it takes to keep the lights on, and what happens with the difference between costs and revenue.
10 +
11 + ---
12 +
13 + ## What It Costs to Run
14 +
15 + Our costs fall into two categories: fixed costs that exist regardless of how many people use the platform, and per-creator costs that scale with each new subscription.
16 +
17 + ### Fixed Costs
18 +
19 + | Category | Range | What's In It |
20 + |----------|-------|-------------|
21 + | Infrastructure | $135-550/mo | Application servers, database, cache, object storage, load balancer |
22 + | Operations | $47-215/mo | Domains, SSL, DNS, monitoring, security scanning, log management |
23 + | Business | $220-580/mo | Payment processing on our own billing, legal, insurance, compliance |
24 + | Development | $0-100/mo | Hosting, CI, development environments |
25 + | **Total** | **$402-1,445/mo** | |
26 +
27 + The range reflects what minimal vs. fully-provisioned operation looks like. At current scale, we spend roughly **$600/month** on fixed costs.
28 +
29 + ### Per-Creator Costs
30 +
31 + Each creator on the platform costs us money to serve — storage, bandwidth, payment processing, and a share of infrastructure load. The amount depends on the tier, because delivering video costs more than delivering audio, which costs more than delivering text.
32 +
33 + | Tier | Your Price | Our Cost | Our Margin |
34 + |------|-----------|----------|-----------|
35 + | Basic | $10/mo | $3-4/mo | $6-7/mo |
36 + | Small Files | $20/mo | $4-6/mo | $14-16/mo |
37 + | Big Files | $30/mo | $6-11/mo | $19-24/mo |
38 + | Streaming | $40/mo | $7-12/mo | $28-33/mo |
39 +
40 + Costs include storage, CDN, transcoding, payment processing fees, and Stripe's per-account fees for handling creator payouts. The ranges reflect that a creator uploading weekly to a large audience costs more than one uploading monthly to a small one.
41 +
42 + Flat pricing means high-activity creators are subsidized by the average. We think this is fair — your subscription price shouldn't punish you for success. See the [pricing calculator](/pricing) to compare what you'd keep here versus other platforms at any revenue level.
43 +
44 + ---
45 +
46 + ## Break-Even
47 +
48 + At current fixed costs (~$600/month), the platform breaks even at roughly **36 creators** with a realistic mix of tiers. Fewer if the mix skews toward higher tiers, more if it skews toward Basic.
49 +
50 + That's a low number. It's low because we don't have costs that other platforms have: no sales team, no marketing budget, no investor relations, no office space, no algorithmic recommendation infrastructure, no data analytics pipeline. Those things cost real money, and that money has to come from somewhere — usually from taking a cut of your earnings or selling ads against your audience. We'd rather not have the costs in the first place.
51 +
52 + ---
53 +
54 + ## Where the Surplus Goes
55 +
56 + At any point beyond break-even, the platform generates more in subscriptions than it spends on infrastructure. Here is what that surplus funds, in priority order:
57 +
58 + 1. **A livable wage.** This is a full-time job. The person building and running the platform needs to pay rent and buy groceries. This is the first claim on any surplus, because a platform whose maintainer can't afford to eat is not sustainable.
59 +
60 + 2. **Hiring.** Right now this is a one-person operation. That's a known risk — it's addressed honestly in our [FAQ](../support/faq.md#what-if-the-founder-is-unable-to-run-the-platform). Adding a second person is the top financial priority once the platform has stable membership covering operating costs. After that, the goal is a small team — enough to provide reliable support, faster development, and independent moderation review.
61 +
62 + 3. **Reserves.** A bad month, a viral spike in CDN costs, or a legal issue shouldn't kill the platform. We maintain reserves to absorb the unexpected without passing it on to you as a price increase.
63 +
64 + 4. **Development.** New features, better infrastructure, improved tools. Everything on the [roadmap](./roadmap.md) costs time and sometimes money.
65 +
66 + ### The Residency Program
67 +
68 + The first hires won't be traditional software engineering recruits. MNW runs a residency program modeled on a medical residency or traditional apprenticeship: we hire exceptionally smart people who lack programming experience — often people leaving academia — and train them into full-stack generalists by working across the entire codebase.
69 +
70 + The goal is not retention. It's graduation. Residents who complete the program leave as strong, independent engineers. MNW benefits from their work during the residency and from a growing network of skilled alumni afterward.
71 +
72 + This matters to you because it means your subscription funds real training and real jobs — not a hiring pipeline optimized for credential-holders, but an investment in people who wouldn't otherwise get a shot at this kind of work. It also means the platform gets maintained by people who understand it deeply, because they learned to build software by building *this* software.
73 +
74 + That's it. There are no shareholders, no dividends, no investor returns. Surplus goes to labor, training, resilience, and reinvestment.
75 +
76 + ### What Surplus Does Not Fund
77 +
78 + - Investor returns (we have no investors)
79 + - Stock buybacks (we have no stock)
80 + - Executive compensation beyond a livable wage
81 + - Acquisitions or expansion for expansion's sake
82 + - Marketing or paid user acquisition
83 +
84 + ---
85 +
86 + ## The Margin Question
87 +
88 + You might look at the per-creator margin table and think: "You're making $14-16 on my $20 subscription. That's a 70-80% margin. Isn't that a lot?"
89 +
90 + It is, relative to cost of goods. But those margins fund everything listed above — not just the infrastructure to serve your content, but the salary of the person maintaining the platform, the legal costs of operating a payment-adjacent business, the reserves against a bad quarter, and the development of new features you'll use next year.
91 +
92 + A percentage-cut platform hides this math. When Bandcamp takes 15% of a $10 album sale, you don't see their cost structure — you just see $1.50 disappear. Our model puts the cost on the table: here's what you pay, here's what it costs us, here's where the rest goes.
93 +
94 + We think this is more honest, even when the margins look wide. The alternative is a percentage cut that scales with your success and funds the same things less transparently.
95 +
96 + ---
97 +
98 + ## Ownership
99 +
100 + Makenot.work will never be sold to private equity, a competitor, or any outside buyer. The only future owners of this company are the people who use it.
101 +
102 + We don't have the details yet — the legal structure, the governance model, the transition timeline. These are big decisions that require legal advice and real thought, and we'd rather get them right than announce something premature. What we can commit to now is the boundary: no outside sale, ever. When we're ready to figure out the rest, we'll do it with the community, not behind closed doors.
103 +
104 + ---
105 +
106 + ## Why These Prices Won't Go Up
107 +
108 + The most common way a platform raises prices is that it was never sustainable at its original prices. Ride-sharing companies burned billions in investor money to keep fares artificially low, then raised them once competition was gone. Streaming services launched at a loss to build subscriber counts, then hiked prices once everyone was locked in.
109 +
110 + We are not doing that. Here's why:
111 +
112 + **There's no hidden subsidy.** The platform is self-funded from personal savings, not investor money being burned down. Both the founder and the company are completely debt-free — no loans, no lines of credit, no financial obligations beyond operating costs. Current prices cover current costs with room to spare. There is no cliff where the real economics kick in.
113 +
114 + **Margins widen with growth, they don't shrink.** Fixed costs barely move as the creator count grows — the same servers, the same monitoring, the same legal and compliance overhead. Each new subscription adds mostly margin. A platform with 500 members costs roughly the same to operate as one with 100, but earns five times as much.
115 +
116 + **We don't have the costs that force other platforms to raise prices.** No sales team. No office. No investor returns. No algorithmic infrastructure. No paid user acquisition funnels. These are the line items that eat margins at other companies and eventually get passed to users. We spend money on things like sponsoring events, hackathons, and community programs — but that's a rounding error compared to the growth marketing budgets that force other platforms to raise prices.
117 +
118 + **Hiring is funded by the surplus, not by price increases.** The margin between what you pay and what your tier costs to serve is wide enough to fund salaries, reserves, and development at current prices. We don't need more revenue per creator to grow the team — we need more creators at the same price.
119 +
120 + **Hosting costs trend down, not up.** Storage, bandwidth, and compute have gotten cheaper every year for two decades. CDN pricing is a commodity. Cloud providers compete on price. The long-term trend works in our favor, not against it.
121 +
122 + None of this is a guarantee against the unexpected — a payment processor doubling its fees or a regulatory change could force adjustments. But the ordinary pressures that cause platforms to raise prices (growth costs, investor returns, executive compensation, marketing budgets) don't apply here. The model works at current prices with room to grow.
123 +
124 + ---
125 +
126 + ## Price Stability
127 +
128 + We will not raise prices beyond inflation unless there are substantial changes in the hosting and delivery infrastructure market. The things that would justify a price increase:
129 +
130 + - Major cloud providers significantly increase storage or bandwidth pricing
131 + - CDN costs rise due to market consolidation or regulatory changes
132 + - Payment processors increase their fees in ways we can't absorb
133 + - New compliance requirements add unavoidable costs
134 +
135 + The things that will never justify a price increase:
136 +
137 + - We want to grow faster
138 + - We want to hire more people
139 + - Competitors charge more
140 +
141 + If we ever raise prices, we'll give 90 days notice, explain exactly what changed, and grandfather existing members at their current rate for at least 12 months.
142 +
143 + ---
144 +
145 + ## See Also
146 +
147 + - [How We Work](./how-we-work.md) — Business model and pricing
148 + - [What We Guarantee](./guarantees.md) — Binding commitments, in writing
149 + - [Roadmap](./roadmap.md) — What we're building next
@@ -0,0 +1,130 @@
1 + # Generative AI Policy
2 +
3 + How Makenot.work defines generative AI, why it matters, and how it affects what you see and sell on the platform.
4 +
5 + ---
6 +
7 + ## Why This Policy Exists
8 +
9 + Most generative AI tools are built on training sets that contain copyrighted work used without permission or payment. Artists, musicians, writers, and developers whose work was scraped to build these models were never asked and never compensated. This policy exists because we think that matters.
10 +
11 + We are not against new tools. We are against tools built on mass uncompensated use of other people's work. If that changes — if models start being trained on properly licensed, compensated datasets — this policy will evolve. Until then, the default is skepticism.
12 +
13 + ---
14 +
15 + ## What We Mean by "Generative AI"
16 +
17 + On this platform, **generative AI** refers to any tool whose existence depends on training sets that are either:
18 +
19 + 1. **Not publicly disclosed**, or
20 + 2. **Known to contain copyrighted material used without compensation** to the rights holders
21 +
22 + This includes derivative products — any application, plugin, or service that relies on the API or model weights of a covered tool. If the underlying model is covered, the wrapper is covered. "I didn't use ChatGPT, I used an app that calls the ChatGPT API" is the same thing.
23 +
24 + ### What this covers
25 +
26 + - Large language models with undisclosed or disputed training data (GPT, Claude, Llama, Mistral, etc.)
27 + - Image generators trained on scraped artwork (Midjourney, DALL-E, Stable Diffusion, etc.)
28 + - Music generators trained on copyrighted recordings (Suno, Udio, etc.)
29 + - Code generators trained on public repositories without clear contributor consent (GitHub Copilot, etc.)
30 + - Any application, plugin, or service built on top of these models via their APIs
31 +
32 + ### What this does not cover
33 +
34 + - Tools trained entirely on the creator's own work
35 + - Tools trained on verifiably public domain material
36 + - Tools with fully disclosed training sets composed of properly licensed, compensated content
37 + - Traditional automation and digital tools: EQ, compression, batch processing, non-generative spell check, programmatic effects, scripting, macros
38 +
39 + The distinction is not about what the tool does. It is about how the tool was built.
40 +
41 + ---
42 +
43 + ## The Three Tiers
44 +
45 + Every item published on Makenot.work must declare one of three tiers. This is required at publish time — there is no unlabeled option.
46 +
47 + ### Handmade
48 +
49 + No generative AI tools were used at any stage of creating this product — from brainstorming to final output. Traditional digital tools (DAWs, image editors, IDEs, effects processors) are fine. The line is generative AI as defined above.
50 +
51 + ### Assisted
52 +
53 + This product was created by a human with generative AI tools as part of the process. Choosing this tier requires a **disclosure statement**: a brief, honest explanation of what tools were used, for what purpose, and at what stage. This disclosure is visible to fans on the item page before purchase.
54 +
55 + Examples of good disclosure:
56 + - "I used GPT-4 to help outline the chapter structure. All writing is mine."
57 + - "Background textures were generated with Stable Diffusion and painted over. Character art and environments are hand-drawn."
58 + - "Code completion (Copilot) was used during development. Game design, art, and music are original."
59 +
60 + The disclosure must accurately represent the scope of AI use. If you say you used AI for brainstorming but the final product contains AI-generated art, that is misrepresentation and will be treated as fraud under our [Acceptable Use Policy](../legal/acceptable-use.md).
61 +
62 + ### Generated
63 +
64 + This product was primarily generated by AI tools. The human contribution is direction, curation, or assembly rather than direct authorship of the creative output.
65 +
66 + ---
67 +
68 + ## How Fans Use This
69 +
70 + Fans can filter what they see on the platform:
71 +
72 + - **Handmade only** — only items with no generative AI involvement
73 + - **Human-led** — Handmade and Assisted items (excludes Generated)
74 + - **Everything** — no filter
75 +
76 + These filters apply to the Discover page, search results, and tag browsing. The tier is also displayed on every item and project page.
77 +
78 + ---
79 +
80 + ## Enforcement
81 +
82 + The tier system is self-reported by creators. We enforce it through:
83 +
84 + 1. **The disclosure statement.** Assisted-tier creators put their AI use in writing. If the actual product contradicts the disclosure, that is documented misrepresentation.
85 + 2. **Community reports.** Fans and fellow creators can flag items they believe are misclassified.
86 + 3. **Moderation review.** Misrepresenting your tier — particularly claiming Handmade when generative AI was used — is treated as fraud. Consequences follow the [Acceptable Use Policy](../legal/acceptable-use.md), up to and including account termination.
87 +
88 + We would rather have honest disclosure than a platform full of false Handmade claims. If you used AI, say so, explain how, and let your audience decide. That is the point of the Assisted tier.
89 +
90 + ---
91 +
92 + ## AI in the Platform Itself
93 +
94 + We will never build generative AI tools or features into the product you use. No AI writing assistants, no AI-generated thumbnails, no AI recommendations. The platform you interact with will always be free of generative AI.
95 +
96 + **Discovery** on Makenot.work is an explicit function of your active choices — purchases, follows, likes, search, and tags. We do not track your behavior to build a profile, and we do not use machine learning to guess what you might want. What you see is determined by what you've told us you care about, not by a model. The discovery and feed algorithms are public and readable:
97 +
98 + - [discover.rs](https://makenot.work/git/max/makenotwork/tree/main/server/src/db/discover.rs) — Search, browse, and all filtering/sorting logic for the Discover page. Uses PostgreSQL trigram matching for fuzzy text search. Sorting is newest, popular (by sales count), or price — no behavioral signals.
99 + - [follows.rs](https://makenot.work/git/max/makenotwork/tree/main/server/src/db/follows.rs) — Feed generation. Your feed shows items from users, projects, and tags you follow, ordered newest first. No algorithmic reordering.
100 + - [tags.rs](https://makenot.work/git/max/makenotwork/tree/main/server/src/db/tags.rs) — Tag facets and hierarchical browsing. Tag counts reflect actual item counts, not weighted relevance.
101 +
102 + **Security and spam filtering** are the exception to a blanket no-ML stance. We will always use the best available tools to protect the platform and its users. At the time of writing, our security and spam toolchains do not use LLMs or generative AI, but we reserve the right to adopt whatever keeps the platform safe. We will never use these tools to influence what you see or recommend content.
103 +
104 + **Platform development** uses LLM-assisted tooling — most of the code is written with the help of tools that fall under our own generative AI definition. We are transparent about this in our commit history. We think there is a meaningful difference between using these tools to build infrastructure and selling their output as creative work, and our tier system reflects that distinction.
105 +
106 + A note from the founder:
107 +
108 + > The honest truth is that I would prefer not to use these tools. In my non-legal opinion, they are unethically built. They are also, frankly, mind-numbingly boring. At the same time, they allow us to write simple code and features at an impressive pace. As the codebase grows, they become less useful and less coherent. Already, before we are out of beta, their usage is diminishing in favor of a more human approach as the focus moves from scaffolding to testing and refinement. We will always be honest about what we use on our end. I will always try to be honest about how I feel about those tools. And as always, we would love to someday replace them with tools that we make or that our community makes — tools that are well-built, ethical, and that I can feel good about using.
109 + >
110 + > — Max
111 +
112 + ---
113 +
114 + ## This Definition Will Change
115 +
116 + The generative AI landscape moves fast. New models launch, training data disclosures shift, lawsuits settle, licensing norms emerge. This policy is a living document. When we update it, we will:
117 +
118 + - Publish the change with a version date
119 + - Explain what changed and why
120 + - Give creators reasonable time to update their tier classifications if the definitions shift
121 +
122 + If a model that is currently covered demonstrates verifiable, fully compensated training data in the future, it may be reclassified. The principle stays the same: we follow the ethics of the training data, not the capabilities of the tool.
123 +
124 + ---
125 +
126 + ## See Also
127 +
128 + - [Acceptable Use Policy](../legal/acceptable-use.md) — What happens when rules are broken
129 + - [Our Story](./story.md) — Why this platform exists
130 + - [What We Guarantee](./guarantees.md) — Binding commitments, in writing
@@ -1,6 +1,6 @@
1 - # Service Level Agreement
1 + # What We Guarantee
2 2
3 - Binding commitments from Makenot.work to every creator on the platform. These are not aspirations — they are verifiable guarantees backed by public source code and versioned documentation. If we break them, you can see it in the code and export your data immediately.
3 + Things we promise, in writing, that you can verify in the code. If we break any of these, you can see it and leave.
4 4
5 5 ---
6 6
@@ -10,9 +10,9 @@ Binding commitments from Makenot.work to every creator on the platform. These ar
10 10
11 11 - No platform percentage cut, ever.
12 12 - No transaction fees, payout fees, or skimming.
13 - - This is a permanent structural commitment, not a promotional rate.
13 + - This is how it works, not a promotional rate.
14 14
15 - **Your subscription and your fan revenue are separate.** Your $10-40/month covers platform access. Revenue from fans is untouched.
15 + Your $10-40/month covers platform access. Revenue from fans is untouched.
16 16
17 17 ---
18 18
@@ -69,6 +69,8 @@ If you leave, your fans come with you.
69 69 4. Fan notification — we help communicate the transition to your audience.
70 70 5. Source code remains available for reference.
71 71
72 + **What it costs to keep the lights on during shutdown:** Platform infrastructure runs on roughly $600/month in fixed costs — a single application server, database, object storage, and DNS. A full 90-day wind-down costs under $2,000 in hosting. Fan payments go directly to creator-controlled Stripe accounts, so there are no pending payouts to settle on our side — Stripe handles that independently. The founder and the company carry zero debt, and the platform is backed by personal savings sufficient to cover years of operation at current costs, with no investors or creditors who could force an early shutdown. A worst-case wind-down is a small, manageable expense — not a financial crisis.
73 +
72 74 ---
73 75
74 76 ## Price Stability
@@ -105,11 +107,11 @@ No browsing profiles. No behavioral tracking. No selling data. Verifiable in the
105 107
106 108 ## Enforcement
107 109
108 - These guarantees are enforceable through three mechanisms:
110 + If you think we've broken any of these:
109 111
110 - 1. **Source code:** Technical claims are verifiable in the public codebase.
111 - 2. **Published documentation:** This document is versioned and timestamped.
112 - 3. **Structural accountability:** Our business model depends on honoring these commitments. Breaking them would be self-destructive.
112 + 1. **Check the code.** Technical claims are verifiable in the public codebase.
113 + 2. **Check the docs.** This document is versioned and timestamped.
114 + 3. **Leave.** Export your data, take your audience, and cancel. We've made that as easy as possible because we'd rather you be able to leave than feel trapped.
113 115
114 116 ---
115 117
@@ -119,7 +121,7 @@ The following guarantees are commitments we are building toward. They are not ye
119 121
120 122 ### Content Archive
121 123
122 - *The 12-month clock will not start counting until after the alpha period ends.*
124 + *Launching before we leave beta — among the first priorities after our initial round of community engagement and testing.*
123 125
124 126 Any content that has existed on the platform for 12 months or more (not including comped months from the earn-back credit program) will remain hosted and accessible to fans even if the creator stops paying for their account.
125 127
@@ -71,7 +71,7 @@ Your subscription funds the platform. We have no reason to take a cut of your re
71 71
72 72 Every tier also includes a separate download budget for general-purpose compressed downloads (zips, bundles, supplementary materials). Big Files and Streaming creators can request a per-file size increase beyond 20GB from their dashboard.
73 73
74 - The prices reflect what it actually costs to store and deliver each content type.
74 + The prices reflect what it actually costs to store and deliver each content type. Use the [pricing calculator](/pricing) to see exactly what you'd keep at any revenue level, with a side-by-side comparison against other platforms.
75 75
76 76 ### Choosing Your Tier
77 77
@@ -104,7 +104,7 @@ The prices reflect what it actually costs to store and deliver each content type
104 104
105 105 ### Earn-Back Credit Program
106 106
107 - *Not yet implemented. The 12-month clock will not start counting until after the alpha period ends.*
107 + *Launching before we leave beta — among the first priorities after our initial round of community engagement and testing.*
108 108
109 109 If you earn less on the platform than you paid in subscription fees during a 12-month period, the difference will be credited as free months for the following year (capped at 12 months). Credits will be calculated annually on your account anniversary.
110 110
@@ -119,7 +119,7 @@ Base tiers include all platform software features. Some capabilities with real m
119 119 - No setup fees, no hidden charges
120 120 - Upgrade or downgrade at any time
121 121
122 - See our [Service Level Agreement](./guarantees.md) for pricing commitments.
122 + See our [written guarantees](./guarantees.md) for pricing commitments.
123 123
124 124 ---
125 125
@@ -142,47 +142,65 @@ Your audience is your business. We facilitate the connection; you own it.
142 142
143 143 ### Content Archive Policy
144 144
145 - *Not yet implemented. The 12-month clock will not start counting until after the alpha period ends.*
145 + *Launching before we leave beta — among the first priorities after our initial round of community engagement and testing.*
146 146
147 - Content that has been on the platform for 12 months or more (not including comped months from the earn-back credit program) stays hosted even if you cancel. Your fans keep access. You just can't upload new content without reactivating. See our [Service Level Agreement](./guarantees.md) for the full commitment.
147 + Content that has been on the platform for 12 months or more (not including comped months from the earn-back credit program) stays hosted even if you cancel. Your fans keep access. You just can't upload new content without reactivating. See our [written guarantees](./guarantees.md) for the full commitment.
148 148
149 149 ---
150 150
151 - ## Discovery: Intentional
151 + ## No Algorithm
152 152
153 - We use search and hierarchical tags. Fans find content because they're looking for it.
153 + There is no recommendation engine. No trending page. No feed designed to maximize engagement. Fans find your work through search, tags, and links — the same way people find anything worth finding on the internet.
154 154
155 - This means you need to bring an audience (or build one elsewhere). We're infrastructure for creator-fan relationships, not a discovery engine.
155 + This means you need to bring an audience or build one elsewhere. We host and sell your work. We don't pretend to be a marketing department.
156 +
157 + ---
158 +
159 + ## Community
160 +
161 + Every project can have a discussion forum powered by [Multithreaded](https://forums.makenot.work) — threaded conversations with no algorithmic sorting, built-in moderation tools, and a public mod log. It's a place for your audience to talk to each other and to you, without a third-party platform owning the conversation.
162 +
163 + The platform-wide forum is where feedback, feature requests, and creator-to-creator discussion happen. See [Forums](../support/forums.md).
156 164
157 165 ---
158 166
159 167 ## Source Available
160 168
161 - Source code is publicly available. You can audit our privacy practices, data handling, and every claim on this site by reading the code.
169 + The source code is public. Read it if you want to verify anything we say on this site.
170 +
171 + We use the PolyForm Noncommercial license rather than a permissive license like MIT or GPL. The reason is simple: permissive licenses let corporations take community-built software and use it to compete against the people who made it, without giving anything back. PolyForm Noncommercial means anyone can read, audit, and learn from the code — but no company can clone this platform and run it for profit.
172 +
173 + Your content is never used to train AI models. See our [Generative AI Policy](./generative-ai.md) for how we define generative AI and how it affects what's allowed on the platform.
162 174
163 175 ---
164 176
165 177 ## Self-Funded
166 178
167 - No outside investors means no one can force us to squeeze creators. Without investor timelines, we can keep prices stable for years, add features when they're ready, say no to profitable-but-harmful choices, and shut down gracefully if needed.
179 + No outside investors. No debt — the founder and the company both carry a zero balance. Nobody can make us raise prices, add ads, or sell the company. There are no creditors, no loan payments, and no financial obligations beyond operating costs. If we can't sustain this on subscriptions, we'll wind down honestly — not pivot into something exploitative.
180 +
181 + Prices won't go up unless infrastructure costs force it. If they ever do, we'll say exactly what changed, give 90 days notice, and grandfather everyone at their current rate.
182 +
183 + ### Where Your Money Goes
168 184
169 - Our commitment: we will never raise prices beyond inflation unless there are substantial changes in the hosting and delivery infrastructure market. If we ever do, we'll explain exactly what changed, give 90 days notice, and grandfather existing creators.
185 + Surplus from subscriptions funds, in order: a livable wage for the maintainer, hiring, reserves, and development. The first hires will come through a residency program — training people without traditional credentials into full-stack engineers by working across the real codebase. The goal is graduation, not retention. Your subscription funds real jobs and real training, not a pipeline optimized for people who already have access. See [Platform Economics](./economics.md) for the full breakdown.
170 186
171 187 ---
172 188
173 189 ## Who This Is For
174 190
175 - Creators who:
191 + Artists, musicians, writers, developers, and makers who:
192 + - Are tired of platforms that profit more from their work than they do
176 193 - Have an audience (even small) or are building one through other channels
177 - - Want to start their projects on a pro-creator platform
178 - - Want direct relationships with fans
179 - - Value ownership over convenience
180 - - Prefer predictable costs over revenue sharing
194 + - Want direct relationships with the people who support their work
195 + - Want to own their data, their audience, and their revenue
196 + - Prefer predictable costs over giving up a percentage of every sale
181 197 - Care about privacy and transparency
182 198
183 199 ---
184 200
185 201 ## See Also
186 202
187 - - [Service Level Agreement](./guarantees.md) — Binding commitments
203 + - [Platform Economics](./economics.md) — What it costs to run, where the money goes
204 + - [Generative AI Policy](./generative-ai.md) — Content tiers and disclosure requirements
205 + - [What We Guarantee](./guarantees.md) — Binding commitments, in writing
188 206 - [FAQ](../support/faq.md) — Quick answers
@@ -85,6 +85,7 @@ Everything listed here is live and working.
85 85 - **Rich link previews**: Your content shows up properly when shared on social media, search engines, and podcast apps
86 86 - **Documentation**: Creator guide covering the full platform
87 87 - **Transactional email**: Password reset, email verification, purchase receipts, subscription updates, sale and follower notifications
88 + - **Community forums**: Per-project discussion forums powered by [Multithreaded](https://forums.makenot.work) — threaded conversations, moderation tools, mod logs, no algorithmic sorting
88 89 - **Git source browser**: Browse server-hosted repositories with syntax highlighting
89 90 - **SSH git access**: Clone and push to hosted repositories with SSH key authentication
90 91 - **Email-first issue tracker**: File issues and reply via email, close via commit message
@@ -156,6 +157,8 @@ Expand payment options over time. ACH/SEPA payouts, lower-cost processors, micro
156 157 - DRM that punishes paying customers
157 158 - Features that create platform lock-in
158 159 - Attention-harvesting engagement tricks
160 + - Generative AI tools or features for users — no AI writing assistants, no AI-generated recommendations, no AI anything in the product you interact with
161 + - Algorithmic discovery based on tracked behavior — what you see is a direct function of your purchases, follows, and likes, not a model's guess about what you might engage with
159 162
160 163 ---
161 164
@@ -170,4 +173,4 @@ We'd rather build what creators actually need than guess. If something on this p
170 173 ## See Also
171 174
172 175 - [How We Work](./how-we-work.md) — Business model and pricing
173 - - [Service Level Agreement](./guarantees.md) — Binding commitments
176 + - [What We Guarantee](./guarantees.md) — Binding commitments, in writing
@@ -22,9 +22,9 @@ Your subscription funds the platform. We have no financial incentive to take a c
22 22
23 23 Makenot.work is self-funded. No venture capital, no angel investors, no outside money. One person built it, one person runs it.
24 24
25 - This is a deliberate choice with real consequences. Growth is slower. Features take longer. There's no marketing budget, no sales team, no growth hacks.
25 + Growth is slower. Features take longer. There's no marketing budget, no sales team, no growth hacks.
26 26
27 - But it also means: no board meetings about monetization strategy. No pressure to raise prices. No investors pushing for an exit. No acqui-hire that shuts everything down. We can keep prices stable, add features when they're ready, and say no to profitable-but-harmful choices.
27 + But there are also no board meetings about monetization strategy. No pressure to raise prices. No investors pushing for an exit. No acqui-hire that shuts everything down. Prices stay stable, features ship when they're ready, and nobody can force us to make profitable-but-harmful choices.
28 28
29 29 If the platform can't sustain itself on subscriptions, it will wind down honestly, not pivot into something exploitative.
30 30
@@ -32,18 +32,22 @@ If the platform can't sustain itself on subscriptions, it will wind down honestl
32 32
33 33 The source code is publicly available under the PolyForm Noncommercial license. You can read every line. Audit our privacy claims. Verify that we handle data the way we say we do. See exactly what happens when you upload a file, make a purchase, or delete your account.
34 34
35 - This isn't a marketing gesture. It's accountability. When we say "we don't track you" or "your data is exportable," you can check.
35 + When we say "we don't track you" or "your data is exportable," you can check. That's the point.
36 36
37 - ## What We Believe
37 + ## What This Means in Practice
38 38
39 - Platforms should be infrastructure, not landlords. A good platform does three things: hosts your content reliably, processes payments honestly, and stays out of the way. Everything else is the platform serving its own interests, not yours.
39 + A good platform does three things: hosts your content reliably, processes payments honestly, and stays out of the way. Everything else is the platform serving its own interests, not yours.
40 40
41 41 Your fans are your fans. Your revenue is your revenue. Your data is your data. A platform that respects this doesn't need to take a percentage, because it doesn't pretend to own the relationship between you and the people who support your work.
42 42
43 + Platforms should be infrastructure, not landlords.
44 +
43 45 ---
44 46
45 47 ## See Also
46 48
47 49 - [How We Work](./how-we-work.md) — Pricing, payment flow, and data portability
48 - - [Service Level Agreement](./guarantees.md) — Binding commitments
50 + - [Platform Economics](./economics.md) — What it costs to run, where the money goes
51 + - [Generative AI Policy](./generative-ai.md) — What we mean by generative AI and how content is classified
52 + - [What We Guarantee](./guarantees.md) — Binding commitments, in writing
49 53 - [Roadmap](./roadmap.md) — What we're building next
@@ -45,6 +45,14 @@ Add links to your website, social media, other platforms, or booking/contact inf
45 45
46 46 Don't overthink this. If you have a website, link it. If you're active on social media, link your main one or two. Booking inquiries? Add an email link. The goal is to let fans find you elsewhere when they want to.
47 47
48 + ## Customizing Your Storefront
49 +
50 + Your profile isn't a template — it's a canvas. You can write custom CSS and rearrange elements on your page to make it look and feel like your own site, within a structure that keeps the experience consistent for fans browsing the platform.
51 +
52 + Think of it like the old MySpace or early YouTube: the platform provides the frame, you control the aesthetic. Change colors, fonts, spacing, and layout to match your visual identity. The consistent navigation and purchase flow stay intact so fans always know how to find, buy, and access your work — but everything in between is yours to shape.
53 +
54 + You don't need to know CSS to have a good-looking page. The defaults work. But if you want your storefront to feel like *yours* rather than a profile on someone else's site, the tools are there.
55 +
48 56 ## What Fans See
49 57
50 58 When someone visits your profile, they see:
@@ -1,16 +1,20 @@
1 1 # Content Moderation & Enforcement
2 2
3 - How we balance creative freedom with maintaining a platform free from harassment, and what happens when accounts violate our policies.
3 + What happens when accounts violate our policies, and what you should know about how moderation works right now.
4 4
5 5 ---
6 6
7 - ## Our Approach
7 + ## Current Limitations
8 +
9 + Moderation is currently handled by one person. That means decisions are fast but not independently reviewable. We know this is a weakness — independent appeal review is a planned commitment in our [written guarantees](../about/guarantees.md#planned-guarantees), and hiring a second person is the top financial priority. Until then, moderation decisions are made directly and in good faith, and every decision can be appealed.
8 10
9 - We have a dual mandate: supporting creative expression while ensuring Makenot.work remains a space free from harassment and harm.
11 + We'd rather be honest about this than pretend we have a trust and safety team.
10 12
11 - We enforce policies against harassment, illegal content, and fraud to keep the platform safe for creators and fans. We reserve the right to refuse service to creators whose conduct harms this environment.
13 + ---
14 +
15 + ## Our Approach
12 16
13 - **Context and intent matter.** We evaluate work as a whole, not isolated elements. Satire, critique, historical documentation, and artistic exploration are considered in full context.
17 + Context and intent matter. We evaluate work as a whole, not isolated elements. Satire, critique, historical documentation, and artistic exploration are considered in full context. We enforce policies against harassment, illegal content, and fraud. We reserve the right to refuse service to anyone whose conduct makes the platform worse for everyone else.
14 18
15 19 ---
16 20
@@ -119,4 +119,4 @@ Data protection inquiries: dpo@makenot.work
119 119
120 120 - [Terms of Service](./terms-of-service.md) — Full legal terms
121 121 - [Acceptable Use Policy](./acceptable-use.md) — Content rules
122 - - [Service Level Agreement](../about/guarantees.md) — Data export and portability commitments
122 + - [What We Guarantee](../about/guarantees.md) — Data export and portability commitments
@@ -98,5 +98,5 @@ Questions? Email legal@makenot.work.
98 98
99 99 - [Privacy Policy](./privacy-policy.md) — Data collection and handling
100 100 - [Acceptable Use Policy](./acceptable-use.md) — Content rules
101 - - [Service Level Agreement](../about/guarantees.md) — Platform commitments
101 + - [What We Guarantee](../about/guarantees.md) — Platform commitments
102 102 - [How We Work](../about/how-we-work.md) — Business model and pricing
@@ -6,7 +6,7 @@ One person runs this platform. Responses are direct and personal.
6 6
7 7 Your answer might already be here:
8 8 - [FAQ](./faq.md) — common questions and hard questions
9 - - [Service Level Agreement](../about/guarantees.md) — what we commit to
9 + - [What We Guarantee](../about/guarantees.md) — what we commit to
10 10 - [How We Work](../about/how-we-work.md) — pricing, payments, data export
11 11
12 12 ## Email
@@ -25,13 +25,13 @@ Yes. Fan accounts are completely free. You only pay for content you choose to bu
25 25 Through our payment system. Payments go directly to your linked bank account. You control payout timing.
26 26
27 27 ### What if I earn nothing — do I still pay?
28 - Yes. The subscription covers platform access, not a share of revenue. We may accept applications for fee remission for supported causes and open source work.
28 + Yes. The subscription covers platform access, not a share of revenue. We know $10/month is real money if you're just starting out or making work that doesn't sell in volume. That's a real tension with this model, and we don't pretend otherwise. The tradeoff is that when you do sell, you keep everything — there's no percentage cut that grows as you grow. We're also building an [earn-back credit program](#what-if-i-dont-earn-back-my-subscription-cost) to soften this for artists whose revenue doesn't cover their subscription. We may accept applications for fee remission for supported causes and open source work.
29 29
30 30 ### What if I don't earn back my subscription cost?
31 31 We're planning an earn-back credit program: if you earn less on the platform than you paid in subscription fees over 12 months, the difference will be credited as free months for the following year (capped at 12 months). The 12-month clock will not start counting until after the alpha period ends. Note: comped months will not count toward content archive eligibility (see [Content Archive](../about/guarantees.md#planned-guarantees)).
32 32
33 33 ### What's the catch?
34 - No catch. We make money from subscriptions, so our interests align with yours. We want you to succeed and stay.
34 + We make money from subscriptions regardless of whether you sell anything. That means we don't need to take a cut of your sales, show ads, or mine your data. Our incentive is to keep the platform working well enough that you don't cancel — which is the same as your incentive.
35 35
36 36 ### Can I leave?
37 37 Anytime. Export all your data, take your fans, cancel subscription. No lock-in, no exit fees.
@@ -88,16 +88,16 @@ The code is public, the documentation is versioned, and you control your data at
88 88 Account info you provide, content you upload, transactions you conduct. No browsing profiles, no behavioral tracking. Verifiable in the source code.
89 89
90 90 ### Will you ever take VC money?
91 - No. Outside investment creates pressure to maximize extraction. We answer to creators, not shareholders.
91 + No. Outside investment means someone eventually needs a return. Returns come from raising fees, adding ads, or selling data. We'd rather stay small and stay honest.
92 92
93 93 ### Will you ever run ads?
94 - No. Advertising means optimizing for attention instead of creator success.
94 + No. Ads mean tracking. Tracking means your fans become the product. We'd rather charge you $10/month and leave your audience alone.
95 95
96 96 ### Will you ever take a cut of revenue?
97 - No. This is the core commitment. Changing it would mean becoming a different platform entirely.
97 + No. If we did, we'd be a different platform — one that profits from your success instead of just hosting it.
98 98
99 99 ### Will you ever sell the company?
100 - Not to private equity or competitors. The long-term plan is to sell the company to its creators.
100 + Makenot.work will never be sold to private equity, a competitor, or any outside buyer. The only people this company will ever be sold to are the artists and makers who use it. What that looks like — the legal structure, the governance, the timeline — is something we want to figure out carefully as the platform matures and stabilizes. We won't rush a half-baked answer to a question this important. What we will commit to now is the boundary: no outside sale, ever.
101 101
102 102 ## Risk & Sustainability
103 103
@@ -105,13 +105,13 @@ Not to private equity or competitors. The long-term plan is to sell the company
105 105 The payment processor holds funds in your account, not ours. No commingling of creator revenue with operating funds. A shutdown would not affect your payment account balance. The [SLA](../about/guarantees.md) guarantees 90 days notice with full export access maintained throughout.
106 106
107 107 ### How long can you sustain this?
108 - A few years minimum at current costs. The model is profitable with a small number of creators relative to competitors. Self-funded, no debt.
108 + A few years minimum at current costs. The platform breaks even at roughly 36 creators with a realistic tier mix. Self-funded, no debt. See [Platform Economics](../about/economics.md) for the full cost structure and where the money goes.
109 109
110 110 ### Is this a full-time operation?
111 111 Yes.
112 112
113 113 ### What if the founder is unable to run the platform?
114 - We'd accelerate the plan to sell the company to its creators.
114 + This is a real risk and we won't pretend otherwise. Right now, Makenot.work is one person. Adding a second person is the top financial priority once the platform has stable membership covering its operating costs. Until then, the mitigations are: source code is public, all data is exportable at any time, the [shutdown protocol](../about/guarantees.md#shutdown-protocol) guarantees 90 days notice with full export access, and your payment account funds are held separately from platform operating funds. The long-term goal is to sell the company to its creators, but that's a goal, not a guarantee.
115 115
116 116 ## Content Policy
117 117
@@ -119,7 +119,7 @@ We'd accelerate the plan to sell the company to its creators.
119 119 Content that dehumanizes, harasses, or incites violence. See [Acceptable Use](../legal/acceptable-use.md) for the full policy.
120 120
121 121 ### What's your stance on AI-generated content?
122 - Creators can indicate what tools were used. AI disclosure isn't required, but creators who advertise as AI-free and aren't will be disciplined.
122 + Every item on the platform must declare one of three tiers: **Handmade** (no generative AI), **Assisted** (human-made with AI tools, disclosure required), or **Generated** (primarily AI output). Fans can filter to see only Handmade, only human-led work (Handmade + Assisted), or everything. Misrepresenting your tier is treated as fraud. See our full [Generative AI Policy](../about/generative-ai.md) for definitions, examples, and enforcement.
123 123
124 124 ### Do you comply with law enforcement requests?
125 125 We prioritize creator privacy, with exceptions for content that is illegal or threatens the platform's existence. We cannot share encryption keys because we don't have them.
@@ -132,6 +132,6 @@ Still stuck? [Contact Support](./contact.md).
132 132
133 133 ## See Also
134 134
135 - - [Service Level Agreement](../about/guarantees.md) — Binding commitments
135 + - [What We Guarantee](../about/guarantees.md) — Binding commitments, in writing
136 136 - [How We Work](../about/how-we-work.md) — Business model
137 137 - [Contact](./contact.md) — Reach a human
@@ -151,7 +151,7 @@ macro_rules! bind_item_discover_filters {
151 151 ///
152 152 /// When a search term is present but no explicit sort is requested, results
153 153 /// are ordered by relevance (`match_score DESC`). Otherwise, the caller can
154 - /// choose `popular`, `price_asc`, `price_desc`, or the default `newest`.
154 + /// choose `most_sold`, `price_asc`, `price_desc`, or the default `newest`.
155 155 #[tracing::instrument(skip_all)]
156 156 pub async fn discover_items(
157 157 pool: &PgPool,
@@ -256,7 +256,7 @@ pub async fn discover_items(
256 256 "match_score DESC NULLS LAST, i.created_at DESC"
257 257 } else {
258 258 match filters.sort_by {
259 - Some(DiscoverSort::Popular) => "sales_count DESC, i.created_at DESC",
259 + Some(DiscoverSort::MostSold) => "sales_count DESC, i.created_at DESC",
260 260 Some(DiscoverSort::PriceAsc) => "i.price_cents ASC, i.created_at DESC",
261 261 Some(DiscoverSort::PriceDesc) => "i.price_cents DESC, i.created_at DESC",
262 262 _ => "i.created_at DESC",
@@ -273,14 +273,14 @@ impl_str_enum!(AppealDecision {
273 273 #[serde(rename_all = "snake_case")]
274 274 pub enum DiscoverSort {
275 275 Newest,
276 - Popular,
276 + MostSold,
277 277 PriceAsc,
278 278 PriceDesc,
279 279 }
280 280
281 281 impl_str_enum!(DiscoverSort {
282 282 Newest => "newest",
283 - Popular => "popular",
283 + MostSold => "most_sold",
284 284 PriceAsc => "price_asc",
285 285 PriceDesc => "price_desc",
286 286 });
@@ -900,7 +900,7 @@ mod tests {
900 900 #[test]
901 901 fn discover_sort_round_trip() {
902 902 assert_eq!(DiscoverSort::Newest.to_string(), "newest");
903 - assert_eq!("popular".parse::<DiscoverSort>().unwrap(), DiscoverSort::Popular);
903 + assert_eq!("most_sold".parse::<DiscoverSort>().unwrap(), DiscoverSort::MostSold);
904 904 assert_eq!("price_asc".parse::<DiscoverSort>().unwrap(), DiscoverSort::PriceAsc);
905 905 assert_eq!("price_desc".parse::<DiscoverSort>().unwrap(), DiscoverSort::PriceDesc);
906 906 assert!("invalid".parse::<DiscoverSort>().is_err());
@@ -179,6 +179,9 @@ define_pg_uuid_id!(
179 179 ItemSectionId,
180 180 ImportJobId,
181 181 MediaFileId,
182 + TipId,
183 + ProjectMemberId,
184 + RevenueSplitId,
182 185 );
183 186
184 187 #[cfg(test)]