max / makenotwork
104 files changed,
+10910 insertions,
-1754 deletions
| @@ -0,0 +1,317 @@ | |||
| 1 | + | #!/usr/bin/env bash | |
| 2 | + | # | |
| 3 | + | # Idempotently create the 16 Stripe Prices that back creator-tier subscriptions | |
| 4 | + | # (4 tiers x {standard, founder} x {monthly, annual}). Re-running is safe: each | |
| 5 | + | # price is keyed by `lookup_key`, so an existing price with the right key and | |
| 6 | + | # the right amount is left alone. | |
| 7 | + | # | |
| 8 | + | # What it does on each price: | |
| 9 | + | # - If no price exists with the lookup_key -> create it. | |
| 10 | + | # - If a price exists with that key and the right amount -> reuse it. | |
| 11 | + | # - If a price exists with that key but a different amount -> archive the old | |
| 12 | + | # one (active=false) and create a new price with `transfer_lookup_key=true`, | |
| 13 | + | # which moves the key onto the new price atomically. | |
| 14 | + | # | |
| 15 | + | # Existing subscriptions are not affected: Stripe Subscriptions are pinned to | |
| 16 | + | # the specific Price ID at signup, regardless of whether that Price is later | |
| 17 | + | # archived or its lookup_key is transferred. Only new checkouts pick up the new | |
| 18 | + | # price. | |
| 19 | + | # | |
| 20 | + | # Old manually-created prices that don't have a lookup_key are NOT touched. | |
| 21 | + | # Run with --archive-old-on-tier-products to also archive every non-matching | |
| 22 | + | # active price on the four tier products (use after verifying the new set | |
| 23 | + | # works end-to-end). | |
| 24 | + | # | |
| 25 | + | # Usage: | |
| 26 | + | # STRIPE_SECRET_KEY=sk_live_... ./deploy/stripe_seed_creator_tier_prices.sh | |
| 27 | + | # STRIPE_SECRET_KEY=sk_test_... ./deploy/stripe_seed_creator_tier_prices.sh --dry-run | |
| 28 | + | # | |
| 29 | + | # Reads the tier-price source of truth from | |
| 30 | + | # `_private/docs/mnw/server-internal/business/assumptions.toml` so docs, Rust | |
| 31 | + | # enum, and Stripe stay in lockstep. If you change prices, edit that toml | |
| 32 | + | # (and `CreatorTier::price_cents`), then re-run this. | |
| 33 | + | # | |
| 34 | + | # Output: prints CREATOR_TIER_*_PRICE_ID env-var assignments suitable for | |
| 35 | + | # pasting into the server's environment file. | |
| 36 | + | ||
| 37 | + | set -euo pipefail | |
| 38 | + | ||
| 39 | + | DRY_RUN=0 | |
| 40 | + | ARCHIVE_OLD=0 | |
| 41 | + | for arg in "$@"; do | |
| 42 | + | case "$arg" in | |
| 43 | + | --dry-run) DRY_RUN=1 ;; | |
| 44 | + | --archive-old-on-tier-products) ARCHIVE_OLD=1 ;; | |
| 45 | + | *) echo "unknown arg: $arg" >&2; exit 2 ;; | |
| 46 | + | esac | |
| 47 | + | done | |
| 48 | + | ||
| 49 | + | : "${STRIPE_SECRET_KEY:?STRIPE_SECRET_KEY must be set}" | |
| 50 | + | ||
| 51 | + | API="https://api.stripe.com/v1" | |
| 52 | + | AUTH=(-u "${STRIPE_SECRET_KEY}:") | |
| 53 | + | ||
| 54 | + | # Monthly prices in whole dollars. Founder = exactly 50% of standard. Annual = | |
| 55 | + | # monthly * 12 * 0.9, rounded to the nearest whole dollar (matches the displayed | |
| 56 | + | # prices in site-docs/about/pricing.md and site-docs/guide/tiers.md). | |
| 57 | + | # | |
| 58 | + | # Tiers: basic small_files big_files everything | |
| 59 | + | declare -A STANDARD_MONTHLY=( | |
| 60 | + | [basic]=16 | |
| 61 | + | [small_files]=24 | |
| 62 | + | [big_files]=36 | |
| 63 | + | [everything]=60 | |
| 64 | + | ) | |
| 65 | + | ||
| 66 | + | # Product display names — these appear on Stripe dashboard and customer | |
| 67 | + | # receipts. One product per tier; four prices hang off each. | |
| 68 | + | declare -A PRODUCT_NAME=( | |
| 69 | + | [basic]="Creator Tier — Basic" | |
| 70 | + | [small_files]="Creator Tier — Small Files" | |
| 71 | + | [big_files]="Creator Tier — Big Files" | |
| 72 | + | [everything]="Creator Tier — Everything" | |
| 73 | + | ) | |
| 74 | + | ||
| 75 | + | # Round monthly cents to the displayed annual price (whole dollars). | |
| 76 | + | annual_cents() { | |
| 77 | + | local monthly_cents=$1 | |
| 78 | + | # bash arithmetic is integer-only, so compute in cents using nearest-int rounding. | |
| 79 | + | # exact = monthly * 12 * 90 / 100; we round to nearest whole dollar (multiple of 100 cents). | |
| 80 | + | local exact=$(( monthly_cents * 12 * 90 / 100 )) | |
| 81 | + | # Round to nearest 100 cents. | |
| 82 | + | local remainder=$(( exact % 100 )) | |
| 83 | + | if (( remainder >= 50 )); then | |
| 84 | + | echo $(( exact - remainder + 100 )) | |
| 85 | + | else | |
| 86 | + | echo $(( exact - remainder )) | |
| 87 | + | fi | |
| 88 | + | } | |
| 89 | + | ||
| 90 | + | # stripe_get path query_string | |
| 91 | + | stripe_get() { | |
| 92 | + | local path=$1 | |
| 93 | + | local query=${2:-} | |
| 94 | + | curl -sS -G "${AUTH[@]}" "${API}/${path}" ${query:+--data-urlencode "$query"} | |
| 95 | + | } | |
| 96 | + | ||
| 97 | + | # Find or create the Product for a tier. Reuses an existing product by metadata | |
| 98 | + | # tag `mnw_tier=<slug>` so re-running doesn't duplicate. | |
| 99 | + | ensure_product() { | |
| 100 | + | local tier_slug=$1 | |
| 101 | + | local name=${PRODUCT_NAME[$tier_slug]} | |
| 102 | + | ||
| 103 | + | # Search by metadata.mnw_tier. | |
| 104 | + | local resp | |
| 105 | + | resp=$(stripe_get "products/search" "query=metadata['mnw_tier']:'${tier_slug}' AND active:'true'") | |
| 106 | + | local existing | |
| 107 | + | existing=$(echo "$resp" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['data'][0]['id'] if d.get('data') else '')") | |
| 108 | + | if [[ -n "$existing" ]]; then | |
| 109 | + | echo "$existing" | |
| 110 | + | return | |
| 111 | + | fi | |
| 112 | + | ||
| 113 | + | if (( DRY_RUN )); then | |
| 114 | + | echo "prod_DRYRUN_${tier_slug}" | |
| 115 | + | return | |
| 116 | + | fi | |
| 117 | + | ||
| 118 | + | local created | |
| 119 | + | created=$(curl -sS "${AUTH[@]}" "${API}/products" \ | |
| 120 | + | -d "name=${name}" \ | |
| 121 | + | -d "metadata[mnw_tier]=${tier_slug}") | |
| 122 | + | echo "$created" | python3 -c "import json,sys; print(json.load(sys.stdin)['id'])" | |
| 123 | + | } | |
| 124 | + | ||
| 125 | + | # Find a price by lookup_key. Echoes "id|unit_amount" or empty. | |
| 126 | + | find_price_by_lookup() { | |
| 127 | + | local key=$1 | |
| 128 | + | local resp | |
| 129 | + | resp=$(stripe_get "prices" "lookup_keys[]=${key}") | |
| 130 | + | echo "$resp" | python3 -c " | |
| 131 | + | import json,sys | |
| 132 | + | d = json.load(sys.stdin) | |
| 133 | + | if d.get('data'): | |
| 134 | + | p = d['data'][0] | |
| 135 | + | print(f\"{p['id']}|{p['unit_amount']}|{p.get('active', True)}\") | |
| 136 | + | " | |
| 137 | + | } | |
| 138 | + | ||
| 139 | + | # Create a price with lookup_key. If transfer_lookup_key is 1, archives whichever | |
| 140 | + | # price currently holds the key. | |
| 141 | + | create_price() { | |
| 142 | + | local product_id=$1 | |
| 143 | + | local unit_amount_cents=$2 | |
| 144 | + | local interval=$3 # month | year | |
| 145 | + | local lookup=$4 | |
| 146 | + | local transfer=$5 # 0 | 1 | |
| 147 | + | ||
| 148 | + | if (( DRY_RUN )); then | |
| 149 | + | echo "price_DRYRUN_${lookup}" | |
| 150 | + | return | |
| 151 | + | fi | |
| 152 | + | ||
| 153 | + | local args=( | |
| 154 | + | -d "currency=usd" | |
| 155 | + | -d "product=${product_id}" | |
| 156 | + | -d "unit_amount=${unit_amount_cents}" | |
| 157 | + | -d "recurring[interval]=${interval}" | |
| 158 | + | -d "lookup_key=${lookup}" | |
| 159 | + | ) | |
| 160 | + | if (( transfer )); then | |
| 161 | + | args+=(-d "transfer_lookup_key=true") | |
| 162 | + | fi | |
| 163 | + | ||
| 164 | + | local resp | |
| 165 | + | resp=$(curl -sS "${AUTH[@]}" "${API}/prices" "${args[@]}") | |
| 166 | + | local price_id | |
| 167 | + | price_id=$(echo "$resp" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('id') or ''); sys.exit(0 if d.get('id') else 1)" || true) | |
| 168 | + | if [[ -z "$price_id" ]]; then | |
| 169 | + | echo "FAILED to create price ${lookup}: $resp" >&2 | |
| 170 | + | exit 1 | |
| 171 | + | fi | |
| 172 | + | echo "$price_id" | |
| 173 | + | } | |
| 174 | + | ||
| 175 | + | archive_price() { | |
| 176 | + | local price_id=$1 | |
| 177 | + | if (( DRY_RUN )); then | |
| 178 | + | echo "(dry-run) would archive ${price_id}" >&2 | |
| 179 | + | return | |
| 180 | + | fi | |
| 181 | + | curl -sS "${AUTH[@]}" "${API}/prices/${price_id}" -d "active=false" >/dev/null | |
| 182 | + | echo "archived ${price_id}" >&2 | |
| 183 | + | } | |
| 184 | + | ||
| 185 | + | # Ensure a price with the given lookup_key, amount, and interval exists. Echoes the price ID. | |
| 186 | + | ensure_price() { | |
| 187 | + | local product_id=$1 | |
| 188 | + | local unit_amount_cents=$2 | |
| 189 | + | local interval=$3 | |
| 190 | + | local lookup=$4 | |
| 191 | + | ||
| 192 | + | local found | |
| 193 | + | found=$(find_price_by_lookup "$lookup") | |
| 194 | + | if [[ -n "$found" ]]; then | |
| 195 | + | local existing_id existing_amount existing_active | |
| 196 | + | IFS='|' read -r existing_id existing_amount existing_active <<<"$found" | |
| 197 | + | if [[ "$existing_amount" == "$unit_amount_cents" && "$existing_active" == "True" ]]; then | |
| 198 | + | echo "$existing_id" | |
| 199 | + | return | |
| 200 | + | fi | |
| 201 | + | # Wrong amount or inactive: transfer the key onto a fresh price and archive the old one. | |
| 202 | + | echo "lookup_key ${lookup}: existing ${existing_id} amount=${existing_amount}, want ${unit_amount_cents}; rotating" >&2 | |
| 203 | + | local new_id | |
| 204 | + | new_id=$(create_price "$product_id" "$unit_amount_cents" "$interval" "$lookup" 1) | |
| 205 | + | archive_price "$existing_id" | |
| 206 | + | echo "$new_id" | |
| 207 | + | return | |
| 208 | + | fi | |
| 209 | + | ||
| 210 | + | create_price "$product_id" "$unit_amount_cents" "$interval" "$lookup" 0 | |
| 211 | + | } | |
| 212 | + | ||
| 213 | + | # uppercase a tier slug for env var name | |
| 214 | + | upper_slug() { | |
| 215 | + | echo "$1" | tr '[:lower:]' '[:upper:]' | |
| 216 | + | } | |
| 217 | + | ||
| 218 | + | # env var name for (tier, rate, interval). | |
| 219 | + | env_var_name() { | |
| 220 | + | local tier_slug=$1 | |
| 221 | + | local rate=$2 # standard | founder | |
| 222 | + | local interval=$3 # monthly | annual | |
| 223 | + | local tier_uc | |
| 224 | + | tier_uc=$(upper_slug "$tier_slug") | |
| 225 | + | local prefix="CREATOR_TIER_${tier_uc}" | |
| 226 | + | case "${rate}_${interval}" in | |
| 227 | + | standard_monthly) echo "${prefix}_PRICE_ID" ;; | |
| 228 | + | standard_annual) echo "${prefix}_ANNUAL_PRICE_ID" ;; | |
| 229 | + | founder_monthly) echo "${prefix}_FOUNDER_PRICE_ID" ;; | |
| 230 | + | founder_annual) echo "${prefix}_FOUNDER_ANNUAL_PRICE_ID" ;; | |
| 231 | + | esac | |
| 232 | + | } | |
| 233 | + | ||
| 234 | + | main() { | |
| 235 | + | local TIERS=(basic small_files big_files everything) | |
| 236 | + | local env_lines=() | |
| 237 | + | local wanted_lookup_keys=() | |
| 238 | + | ||
| 239 | + | for tier in "${TIERS[@]}"; do | |
| 240 | + | local std_monthly_cents=$(( STANDARD_MONTHLY[$tier] * 100 )) | |
| 241 | + | local founder_monthly_cents=$(( std_monthly_cents / 2 )) | |
| 242 | + | local std_annual_cents | |
| 243 | + | std_annual_cents=$(annual_cents "$std_monthly_cents") | |
| 244 | + | local founder_annual_cents | |
| 245 | + | founder_annual_cents=$(annual_cents "$founder_monthly_cents") | |
| 246 | + | ||
| 247 | + | echo "==> ${tier}: standard \$${STANDARD_MONTHLY[$tier]}/mo, founder \$$(( STANDARD_MONTHLY[$tier] / 2 ))/mo" >&2 | |
| 248 | + | echo " annual cents: standard=${std_annual_cents}, founder=${founder_annual_cents}" >&2 | |
| 249 | + | ||
| 250 | + | local product_id | |
| 251 | + | product_id=$(ensure_product "$tier") | |
| 252 | + | echo " product: ${product_id}" >&2 | |
| 253 | + | ||
| 254 | + | for rate in standard founder; do | |
| 255 | + | for interval in monthly annual; do | |
| 256 | + | local cents stripe_interval | |
| 257 | + | if [[ "$rate" == "standard" && "$interval" == "monthly" ]]; then | |
| 258 | + | cents=$std_monthly_cents | |
| 259 | + | elif [[ "$rate" == "standard" && "$interval" == "annual" ]]; then | |
| 260 | + | cents=$std_annual_cents | |
| 261 | + | elif [[ "$rate" == "founder" && "$interval" == "monthly" ]]; then | |
| 262 | + | cents=$founder_monthly_cents | |
| 263 | + | else | |
| 264 | + | cents=$founder_annual_cents | |
| 265 | + | fi | |
| 266 | + | if [[ "$interval" == "monthly" ]]; then | |
| 267 | + | stripe_interval=month | |
| 268 | + | else | |
| 269 | + | stripe_interval=year | |
| 270 | + | fi | |
| 271 | + | ||
| 272 | + | local lookup="creator_tier_${tier}_${rate}_${interval}" | |
| 273 | + | wanted_lookup_keys+=("$lookup") | |
| 274 | + | local price_id | |
| 275 | + | price_id=$(ensure_price "$product_id" "$cents" "$stripe_interval" "$lookup") | |
| 276 | + | local var | |
| 277 | + | var=$(env_var_name "$tier" "$rate" "$interval") | |
| 278 | + | env_lines+=("${var}=${price_id}") | |
| 279 | + | echo " ${lookup} -> ${price_id} (\$$(awk "BEGIN { printf \"%.2f\", $cents/100 }"))" >&2 | |
| 280 | + | done | |
| 281 | + | done | |
| 282 | + | ||
| 283 | + | if (( ARCHIVE_OLD )); then | |
| 284 | + | echo " archiving stale prices on product ${product_id}..." >&2 | |
| 285 | + | # List all active prices on this product, archive any whose lookup_key isn't in the wanted set | |
| 286 | + | # (or whose lookup_key is null, which means it was created manually before lookup_keys existed). | |
| 287 | + | local resp | |
| 288 | + | resp=$(stripe_get "prices" "product=${product_id}&active=true&limit=100") | |
| 289 | + | # Build a python literal of the wanted keys for this tier | |
| 290 | + | local tier_wanted_py="[" | |
| 291 | + | for k in "${wanted_lookup_keys[@]}"; do | |
| 292 | + | if [[ "$k" == "creator_tier_${tier}_"* ]]; then | |
| 293 | + | tier_wanted_py+="'$k'," | |
| 294 | + | fi | |
| 295 | + | done | |
| 296 | + | tier_wanted_py+="]" | |
| 297 | + | local stale_ids | |
| 298 | + | stale_ids=$(echo "$resp" | python3 -c " | |
| 299 | + | import json, sys | |
| 300 | + | d = json.load(sys.stdin) | |
| 301 | + | wanted = set(${tier_wanted_py}) | |
| 302 | + | for p in d.get('data', []): | |
| 303 | + | if p.get('lookup_key') not in wanted: | |
| 304 | + | print(p['id']) | |
| 305 | + | ") | |
| 306 | + | for sid in $stale_ids; do | |
| 307 | + | archive_price "$sid" | |
| 308 | + | done | |
| 309 | + | fi | |
| 310 | + | done | |
| 311 | + | ||
| 312 | + | echo | |
| 313 | + | echo "# Paste into the server environment (and restart):" | |
| 314 | + | printf '%s\n' "${env_lines[@]}" | sort | |
| 315 | + | } | |
| 316 | + | ||
| 317 | + | main "$@" |
| @@ -165,7 +165,7 @@ Stripe Connect Standard for creator payouts. Creators connect their Stripe accou | |||
| 165 | 165 | ||
| 166 | 166 | - Checkout sessions for one-time purchases and subscriptions | |
| 167 | 167 | - Webhook handlers for payment confirmation, subscription lifecycle, disputes | |
| 168 | - | - Creator tier subscriptions (Basic $10, Small Files $20, Big Files $30, Everything $60) | |
| 168 | + | - Creator tier subscriptions (Basic $16, Small Files $24, Big Files $36, Everything $60) | |
| 169 | 169 | - Fan+ consumer subscriptions ($8/mo) | |
| 170 | 170 | - Promo codes (percentage/fixed discount, free access) | |
| 171 | 171 |
| @@ -893,7 +893,7 @@ The unit economics are actually sound — Hetzner storage + Cloudflare CDN make | |||
| 893 | 893 | ||
| 894 | 894 | | ID | Risk | Evidence | Plan | | |
| 895 | 895 | |----|------|----------|------| | |
| 896 | - | | BF-H1 | Multi-account tier-gaming: `try_increment_storage` gates per-user only; no cross-account dedup against payment method, IP, or email domain. A creator with 10GB of small files could split across two Basic accounts at $10/mo each instead of one Small Files at $20/mo. | `src/db/creator_tiers.rs:218,568` | Defer. Founder cohort is hand-picked; at scale add Stripe customer-id cross-check or payment-method fingerprinting. | | |
| 896 | + | | BF-H1 | Multi-account tier-gaming: `try_increment_storage` gates per-user only; no cross-account dedup against payment method, IP, or email domain. A creator with 10GB of small files could split across two Basic accounts at $16/mo each instead of one Small Files at $24/mo. | `src/db/creator_tiers.rs:218,568` | Defer. Founder cohort is hand-picked; at scale add Stripe customer-id cross-check or payment-method fingerprinting. | | |
| 897 | 897 | | BF-H2 | MetaDefender Cloud has no monthly spend cap in code. Currently free-tier (4k req/day) and gated to suspicious files only, so cost = $0 today. If MNW upgrades to a paid key, an uploads-flood from a hostile account would have no spend ceiling. | `src/scanning/metadefender.rs` | Defer. Add daily-budget alert + cap before any paid-key upgrade. Note in `tech/content-scanning.md`. | | |
| 898 | 898 | | BF-H3 | Founder rate "locked for life" is a one-way ratchet. Cost-favorable changes apply retroactively; cost-unfavorable changes cannot. | `site-docs/public/about/guarantees.md`, `site-docs/public/about/pricing.md:14` | Defer. The legal language is already correct ("locked at the rate when you joined"); business risk is structural and intentional. | | |
| 899 | 899 | | BF-H4 | Earn-back credit program: any creator who pays more than they earn gets credited. Inverts unit economics on small creators — a $5 Basic creator earning $0 gets a year free. Combined with "no ads ever" guarantee + founder rate lock, the long tail of creators is structurally subsidized by the top end. | `site-docs/public/about/economics.md`, `roadmap.md:54` | Defer. Strategic decision. Cap the credit to a maximum dollar amount or pair with a minimum-engagement floor before the program goes live (deadline 2027-01-01). | |
| @@ -356,7 +356,7 @@ A thin local binary that handles file reading and calls the API directly. But th | |||
| 356 | 356 | │ Username: max │ | |
| 357 | 357 | │ Display name: [Max J ] │ | |
| 358 | 358 | │ Email: max@example.com (verified) │ | |
| 359 | - | │ Tier: Small Files ($20/mo) │ | |
| 359 | + | │ Tier: Small Files ($24/mo) │ | |
| 360 | 360 | │ Storage: 142MB / 10GB ██░░░░░░░░ 1.4% │ | |
| 361 | 361 | │ │ | |
| 362 | 362 | │ Security │ |
| @@ -489,19 +489,19 @@ | |||
| 489 | 489 | ||
| 490 | 490 | <div class="pricing"> | |
| 491 | 491 | <div class="tier"> | |
| 492 | - | <span class="tier-price">$10</span> | |
| 492 | + | <span class="tier-price">$16</span> | |
| 493 | 493 | <span class="tier-period">/ month</span> | |
| 494 | 494 | <span class="tier-name">Basic</span> | |
| 495 | 495 | <div class="tier-desc">Text, blogs, newsletters, community forums.</div> | |
| 496 | 496 | </div> | |
| 497 | 497 | <div class="tier"> | |
| 498 | - | <span class="tier-price">$20</span> | |
| 498 | + | <span class="tier-price">$24</span> | |
| 499 | 499 | <span class="tier-period">/ month</span> | |
| 500 | 500 | <span class="tier-name">Small Files</span> | |
| 501 | 501 | <div class="tier-desc">Audio, sample packs, plugins, software, presets.</div> | |
| 502 | 502 | </div> | |
| 503 | 503 | <div class="tier"> | |
| 504 | - | <span class="tier-price">$30</span> | |
| 504 | + | <span class="tier-price">$36</span> | |
| 505 | 505 | <span class="tier-period">/ month</span> | |
| 506 | 506 | <span class="tier-name">Big Files</span> | |
| 507 | 507 | <div class="tier-desc">Video, courses, tutorials, large archives.</div> | |
| @@ -628,7 +628,7 @@ | |||
| 628 | 628 | </table> | |
| 629 | 629 | ||
| 630 | 630 | <div class="highlight-box"> | |
| 631 | - | <p>A creator earning $10,000/month on Gumroad loses $1,000 to the platform every month. On Makenot.work, the same creator pays $10–$60 flat — keeping an extra <strong>$12,000 per year</strong>. Month-to-month cancellation. Full data export. No lock-in.</p> | |
| 631 | + | <p>A creator earning $10,000/month on Gumroad loses $1,000 to the platform every month. On Makenot.work, the same creator pays $16–$60 flat — keeping an extra <strong>$12,000 per year</strong>. Month-to-month cancellation. Full data export. No lock-in.</p> | |
| 632 | 632 | </div> | |
| 633 | 633 | ||
| 634 | 634 | <div class="footer"> |
| @@ -43,7 +43,7 @@ CCX13 = 2 dedicated vCPU / 8 GB RAM / 80 GB NVMe + 10 GB volume, ~20 TB included | |||
| 43 | 43 | ||
| 44 | 44 | ## Economic Analysis | |
| 45 | 45 | ||
| 46 | - | All prices are list rates as of 2026-05; verify before budgeting. EUR/USD assumed ~1.08. Tier mix assumed roughly: 50% Basic ($10), 25% Small Files ($20), 20% Big Files ($30), 5% Everything ($60) → blended ARPU ~$19/mo. Tier storage caps (50/250/500/500 GB) are headroom, not actual usage; assume actual fill ~20% of cap at any given time. | |
| 46 | + | All prices are list rates as of 2026-05; verify before budgeting. EUR/USD assumed ~1.08. Tier mix assumed roughly: 50% Basic ($16), 25% Small Files ($24), 20% Big Files ($36), 5% Everything ($60) → blended ARPU ~$24/mo. Tier storage caps (50/250/500/500 GB) are headroom, not actual usage; assume actual fill ~20% of cap at any given time. | |
| 47 | 47 | ||
| 48 | 48 | ### Compute (Hetzner) | |
| 49 | 49 |
| @@ -264,7 +264,7 @@ Per-machine activations. UNIQUE(license_key_id, machine_id) prevents double-acti | |||
| 264 | 264 | ## Creator Tiers | |
| 265 | 265 | ||
| 266 | 266 | ### creator_subscriptions | |
| 267 | - | Platform subscription for creators (Basic $10, Small Files $20, Big Files $30, Everything $60). One row per creator. | |
| 267 | + | Platform subscription for creators (Basic $16, Small Files $24, Big Files $36, Everything $60). One row per creator. | |
| 268 | 268 | ||
| 269 | 269 | - **FK:** user_id → users CASCADE (UNIQUE) | |
| 270 | 270 | - **Key columns:** tier, status, stripe_subscription_id UNIQUE, grace_enforced_at |
| @@ -8,13 +8,13 @@ What you keep on Makenot.work versus other platforms at $500, $2,000, and $10,00 | |||
| 8 | 8 | ||
| 9 | 9 | All numbers assume US Stripe rates (2.9% + $0.30) and an **average fan transaction of $10**. Per-transaction cost depends on sale count, not just gross revenue; see [How We Work § The Math](./how-we-work.md#the-math) for the full breakdown. Patreon's row uses their "Pro" tier (8%); their Lite (5%) and Premium (12%) tiers shift the column up and down respectively. | |
| 10 | 10 | ||
| 11 | - | The Makenot.work range reflects the lowest tier ($10, Basic) at the high end and the highest tier ($60, Everything) at the low end. | |
| 11 | + | The Makenot.work range reflects the lowest tier ($16, Basic) at the high end and the highest tier ($60, Everything) at the low end. | |
| 12 | 12 | ||
| 13 | 13 | ### At $500/month revenue (50 sales × $10) | |
| 14 | 14 | ||
| 15 | 15 | | Platform | Platform fee | Processing | You keep | | |
| 16 | 16 | |----------|---:|---:|---:| | |
| 17 | - | | **Makenot.work** | 0% + $10-60 sub | ~$29.50 | **$410-460** | | |
| 17 | + | | **Makenot.work** | 0% + $16-60 sub | ~$29.50 | **$410-454** | | |
| 18 | 18 | | Bandcamp | 15% = $75 | ~$29.50 | $395 | | |
| 19 | 19 | | Gumroad | 10% = $50 | included | $450 | | |
| 20 | 20 | | itch.io (default) | 10% = $50 | ~$29.50 | $420 | | |
| @@ -24,7 +24,7 @@ The Makenot.work range reflects the lowest tier ($10, Basic) at the high end and | |||
| 24 | 24 | ||
| 25 | 25 | | Platform | Platform fee | Processing | You keep | | |
| 26 | 26 | |----------|---:|---:|---:| | |
| 27 | - | | **Makenot.work** | 0% + $10-60 sub | ~$118 | **$1,822-1,872** | | |
| 27 | + | | **Makenot.work** | 0% + $16-60 sub | ~$118 | **$1,822-1,866** | | |
| 28 | 28 | | Bandcamp | 15% = $300 | ~$118 | $1,582 | | |
| 29 | 29 | | Gumroad | 10% = $200 | included | $1,800 | | |
| 30 | 30 | | itch.io (default) | 10% = $200 | ~$118 | $1,682 | | |
| @@ -34,13 +34,13 @@ The Makenot.work range reflects the lowest tier ($10, Basic) at the high end and | |||
| 34 | 34 | ||
| 35 | 35 | | Platform | Platform fee | Processing | You keep | | |
| 36 | 36 | |----------|---:|---:|---:| | |
| 37 | - | | **Makenot.work** | 0% + $10-60 sub | ~$590 | **$9,350-9,400** | | |
| 37 | + | | **Makenot.work** | 0% + $16-60 sub | ~$590 | **$9,350-9,394** | | |
| 38 | 38 | | Bandcamp | 15% = $1,500 | ~$590 | $7,910 | | |
| 39 | 39 | | Gumroad | 10% = $1,000 | included | $9,000 | | |
| 40 | 40 | | itch.io (default) | 10% = $1,000 | ~$590 | $8,410 | | |
| 41 | 41 | | Patreon (Pro) | 8% = $800 | ~$590 | $8,610 | | |
| 42 | 42 | ||
| 43 | - | The flat-fee model becomes more favorable as revenue grows. At $10,000/month you save **$350-1,490/month** versus percentage-cut platforms: about $350-400 versus Gumroad at the low end, up to $1,440-1,490 versus Bandcamp at the high end. itch.io and Patreon sit between those two endpoints. | |
| 43 | + | The flat-fee model becomes more favorable as revenue grows. At $10,000/month you save **$350-1,484/month** versus percentage-cut platforms: about $350-394 versus Gumroad at the low end, up to $1,440-1,484 versus Bandcamp at the high end. itch.io and Patreon sit between those two endpoints. | |
| 44 | 44 | ||
| 45 | 45 | --- | |
| 46 | 46 | ||
| @@ -83,14 +83,14 @@ Discovery is driven entirely by fan intent: search, filters, tags, feeds, sortin | |||
| 83 | 83 | ||
| 84 | 84 | | | Makenot.work | Bandcamp | Gumroad | itch.io | Patreon | | |
| 85 | 85 | |---|---|---|---|---|---| | |
| 86 | - | | **Model** | Flat monthly ($10-60) | % of revenue | % of revenue | % of revenue (optional) | % of revenue | | |
| 86 | + | | **Model** | Flat monthly ($16-60) | % of revenue | % of revenue | % of revenue (optional) | % of revenue | | |
| 87 | 87 | | **Platform cut** | 0% | 15% | 10% | 0-10% (creator sets) | 5-12% | | |
| 88 | 88 | | **Processing** | ~3% (Stripe) | ~3% (Stripe) | included in 10% | ~3% | ~3% | | |
| 89 | - | | **Break-even vs 15%** | ~$67-400/mo revenue | N/A | N/A | N/A | N/A | | |
| 90 | - | | **Break-even vs 10%** | ~$100-600/mo revenue | N/A | N/A | N/A | N/A | | |
| 91 | - | | **Break-even vs 8%** | ~$125-750/mo revenue | N/A | N/A | N/A | N/A | | |
| 89 | + | | **Break-even vs 15%** | ~$107-400/mo revenue | N/A | N/A | N/A | N/A | | |
| 90 | + | | **Break-even vs 10%** | ~$160-600/mo revenue | N/A | N/A | N/A | N/A | | |
| 91 | + | | **Break-even vs 8%** | ~$200-750/mo revenue | N/A | N/A | N/A | N/A | | |
| 92 | 92 | ||
| 93 | - | Break-even is `subscription / platform-percentage`. Below that revenue, the percentage-cut platform costs you less; above it, the flat fee wins and the gap widens with every dollar earned. The ranges above span the Basic tier ($10) at the low end to Everything ($60) at the high end. | |
| 93 | + | Break-even is `subscription / platform-percentage`. Below that revenue, the percentage-cut platform costs you less; above it, the flat fee wins and the gap widens with every dollar earned. The ranges above span the Basic tier ($16) at the low end to Everything ($60) at the high end. | |
| 94 | 94 | ||
| 95 | 95 | --- | |
| 96 | 96 | ||
| @@ -113,7 +113,7 @@ These are design decisions, not missing features. See [What We Guarantee](./guar | |||
| 113 | 113 | Be honest about what you need: | |
| 114 | 114 | ||
| 115 | 115 | - **You need algorithmic amplification.** If you have no existing audience and need a platform to surface your work via recommendations, Bandcamp's editorial picks or YouTube's algorithm will serve you better today. | |
| 116 | - | - **You earn under $67/month.** A 10-15% cut costs less than our $10 minimum. itch.io's optional revenue share (including 0%) is hard to beat at small scale. | |
| 116 | + | - **You earn under $107/month.** A 10-15% cut costs less than our $16 minimum. itch.io's optional revenue share (including 0%) is hard to beat at small scale. | |
| 117 | 117 | - **You need community features.** If comments, polls, and DMs with fans are core to your model, Patreon has those. We have forums. | |
| 118 | 118 | - **You sell physical products.** We don't handle shipping, inventory, or physical fulfillment. | |
| 119 | 119 |
| @@ -12,7 +12,7 @@ Promises you can verify in the code. If we break any, you can see it and leave. | |||
| 12 | 12 | - No transaction fees, payout fees, or skimming. | |
| 13 | 13 | - This is the model, not a promotional rate. | |
| 14 | 14 | ||
| 15 | - | Your $10-60/month covers platform access. Fan revenue is untouched. | |
| 15 | + | Your $16-60/month covers platform access. Fan revenue is untouched. | |
| 16 | 16 | ||
| 17 | 17 | --- | |
| 18 | 18 |
| @@ -6,7 +6,7 @@ Flat fee. All your revenue passes through to you. | |||
| 6 | 6 | ||
| 7 | 7 | ## For Creators | |
| 8 | 8 | ||
| 9 | - | 1. **Sign up** and choose a pricing tier ($10-$60/month based on content type) | |
| 9 | + | 1. **Sign up** and choose a pricing tier ($16-$60/month based on content type) | |
| 10 | 10 | 2. **Upload content**: text, audio, video, software, or digital files | |
| 11 | 11 | 3. **Organize** using hierarchical tags and projects | |
| 12 | 12 | 4. **Set pricing**: free, pay-what-you-want, fixed price, or membership | |
| @@ -40,7 +40,7 @@ We never touch creator revenue. Payments go directly to creator-controlled payme | |||
| 40 | 40 | ||
| 41 | 41 | ## The Model | |
| 42 | 42 | ||
| 43 | - | You pay a monthly tier fee based on content type ($10-60). We take 0% of your fan revenue. The only deduction is the payment processing fee (~3%). No ads, no percentage cuts, no hidden fees. | |
| 43 | + | You pay a monthly tier fee based on content type ($16-60). We take 0% of your fan revenue. The only deduction is the payment processing fee (~3%). No ads, no percentage cuts, no hidden fees. | |
| 44 | 44 | ||
| 45 | 45 | ### The Math | |
| 46 | 46 | ||
| @@ -48,15 +48,15 @@ Stripe's US standard processing fee is `2.9% + $0.30 per transaction` (see [stri | |||
| 48 | 48 | ||
| 49 | 49 | At $1,000/month in fan revenue (≈100 transactions × $10): | |
| 50 | 50 | - 10% platform cut = $100 to the platform | |
| 51 | - | - Flat fee model = $10-60 tier fee, plus Stripe: `100 × $0.30 + 2.9% × $1,000 = $30 + $29 = $59` processing | |
| 51 | + | - Flat fee model = $16-60 tier fee, plus Stripe: `100 × $0.30 + 2.9% × $1,000 = $30 + $29 = $59` processing | |
| 52 | 52 | ||
| 53 | 53 | At $10,000/month (≈1,000 transactions × $10): | |
| 54 | 54 | - 10% platform cut = $1,000 to the platform | |
| 55 | - | - Flat fee model = same $10-60 tier fee, plus Stripe: `1,000 × $0.30 + 2.9% × $10,000 = $300 + $290 = $590` processing | |
| 55 | + | - Flat fee model = same $16-60 tier fee, plus Stripe: `1,000 × $0.30 + 2.9% × $10,000 = $300 + $290 = $590` processing | |
| 56 | 56 | ||
| 57 | 57 | At $50,000/month (≈5,000 transactions × $10): | |
| 58 | 58 | - 10% platform cut = $5,000 to the platform | |
| 59 | - | - Flat fee model = same $10-60 tier fee, plus Stripe: `5,000 × $0.30 + 2.9% × $50,000 = $1,500 + $1,450 = $2,950` processing | |
| 59 | + | - Flat fee model = same $16-60 tier fee, plus Stripe: `5,000 × $0.30 + 2.9% × $50,000 = $1,500 + $1,450 = $2,950` processing | |
| 60 | 60 | ||
| 61 | 61 | The gap widens as you grow. A percentage-cut platform is most expensive exactly when you're doing the best. Higher average transaction sizes shift more of Stripe's cost into the 2.9% line and away from the per-transaction $0.30; lower average sizes do the opposite. | |
| 62 | 62 | ||
| @@ -66,9 +66,9 @@ The gap widens as you grow. A percentage-cut platform is most expensive exactly | |||
| 66 | 66 | ||
| 67 | 67 | | Tier | Monthly | For | Per-file limit | Total storage | | |
| 68 | 68 | |------|---------|-----|---------------|---------------| | |
| 69 | - | | **Basic** | $10 | Text, blogs, newsletters | 10MB | 50GB | | |
| 70 | - | | **Small Files** | $20 | Audio, software, plugins, sample packs | 500MB | 250GB | | |
| 71 | - | | **Big Files** | $30 | Video, games, large software | 20GB | 500GB | | |
| 69 | + | | **Basic** | $16 | Text, blogs, newsletters | 10MB | 50GB | | |
| 70 | + | | **Small Files** | $24 | Audio, software, plugins, sample packs | 500MB | 250GB | | |
| 71 | + | | **Big Files** | $36 | Video, games, large software | 20GB | 500GB | | |
| 72 | 72 | | **Everything** | $60 | All features, current and future | 20GB | 500GB | | |
| 73 | 73 | ||
| 74 | 74 | Every tier includes 0% platform fee on fan payments, custom profile, project organization, data export, memberships, RSS, promo codes, and 2FA/passkeys. Use the [pricing calculator](/pricing) to compare what you'd keep versus other platforms. |
| @@ -22,9 +22,9 @@ While the window is still open, your founder eligibility depends on having an ac | |||
| 22 | 22 | ||
| 23 | 23 | | Tier | Monthly | Annual (10% off) | What's Included | | |
| 24 | 24 | |---|---|---|---| | |
| 25 | - | | **Basic** | ${{ tiers.founding.basic }}/mo | $54/yr | Text, blogs, newsletters, posts, RSS, memberships, analytics | | |
| 26 | - | | **Small Files** | ${{ tiers.founding.small_files }}/mo | $108/yr | Everything in Basic, plus audio hosting, podcast RSS, binary downloads, license keys, promo codes | | |
| 27 | - | | **Big Files** | ${{ tiers.founding.big_files }}/mo | $162/yr | Everything in Small Files, plus video uploads, in-browser video player, large binaries up to 20GB | | |
| 25 | + | | **Basic** | ${{ tiers.founding.basic }}/mo | $86/yr | Text, blogs, newsletters, posts, RSS, memberships, analytics | | |
| 26 | + | | **Small Files** | ${{ tiers.founding.small_files }}/mo | $130/yr | Everything in Basic, plus audio hosting, podcast RSS, binary downloads, license keys, promo codes | | |
| 27 | + | | **Big Files** | ${{ tiers.founding.big_files }}/mo | $194/yr | Everything in Small Files, plus video uploads, in-browser video player, large binaries up to 20GB | | |
| 28 | 28 | | **Everything** | ${{ tiers.founding.everything }}/mo | $324/yr | All current and future features, including streaming infrastructure when it ships | | |
| 29 | 29 | ||
| 30 | 30 | Annual is 10% off the monthly total. Most of that is the Stripe per-transaction fee we don't pay when we charge once a year instead of twelve times. We pass it back rather than keep it. | |
| @@ -39,9 +39,9 @@ The standard rate applies to new signups after the founder window closes. The va | |||
| 39 | 39 | ||
| 40 | 40 | | Tier | Monthly | Annual (10% off) | | |
| 41 | 41 | |---|---|---| | |
| 42 | - | | **Basic** | ${{ tiers.standard.basic }}/mo | $108/yr | | |
| 43 | - | | **Small Files** | ${{ tiers.standard.small_files }}/mo | $216/yr | | |
| 44 | - | | **Big Files** | ${{ tiers.standard.big_files }}/mo | $324/yr | | |
| 42 | + | | **Basic** | ${{ tiers.standard.basic }}/mo | $173/yr | | |
| 43 | + | | **Small Files** | ${{ tiers.standard.small_files }}/mo | $259/yr | | |
| 44 | + | | **Big Files** | ${{ tiers.standard.big_files }}/mo | $389/yr | | |
| 45 | 45 | | **Everything** | ${{ tiers.standard.everything }}/mo | $648/yr | | |
| 46 | 46 | ||
| 47 | 47 | --- |
| @@ -14,7 +14,7 @@ When a platform takes venture capital, the pressure compounds. Investors need re | |||
| 14 | 14 | ||
| 15 | 15 | ## The Alternative | |
| 16 | 16 | ||
| 17 | - | We charge a flat monthly fee based on what you need to host: $10 for text, $20 for audio and software, $30 for video and large files, $60 for all features, current and future. We take 0% of your revenue. The only deduction from fan payments is the payment processor's fee (~3%), which goes to the processor, not us. | |
| 17 | + | We charge a flat monthly fee based on what you need to host: $16 for text, $24 for audio and software, $36 for video and large files, $60 for all features, current and future. We take 0% of your revenue. The only deduction from fan payments is the payment processor's fee (~3%), which goes to the processor, not us. | |
| 18 | 18 | ||
| 19 | 19 | Your tier fee funds the platform. No incentive to take a cut of your sales, show ads to your fans, or lock you in. | |
| 20 | 20 |
| @@ -16,7 +16,7 @@ Your purchases are permanent and downloadable. No DRM, no streaming-only restric | |||
| 16 | 16 | ||
| 17 | 17 | 1. You pay for content or join a creator's membership tier | |
| 18 | 18 | 2. Payment goes directly to the creator's account minus ~3% processing | |
| 19 | - | 3. We make money from creator tier fees ($10-60/month), not from your purchases | |
| 19 | + | 3. We make money from creator tier fees ($16-60/month), not from your purchases | |
| 20 | 20 | ||
| 21 | 21 | ### Guest Checkout (No Account Required) | |
| 22 | 22 |
| @@ -8,9 +8,9 @@ We are running a founder window. **Every creator who joins right now pays half t | |||
| 8 | 8 | ||
| 9 | 9 | | Tier | Founder monthly | Founder annual (10% off) | Eventual sticker | | |
| 10 | 10 | |------|-----------------|--------------------------|------------------| | |
| 11 | - | | **Basic** | **${{ tiers.founding.basic }}/mo** | $54/yr | ${{ tiers.standard.basic }}/mo | | |
| 12 | - | | **Small Files** | **${{ tiers.founding.small_files }}/mo** | $108/yr | ${{ tiers.standard.small_files }}/mo | | |
| 13 | - | | **Big Files** | **${{ tiers.founding.big_files }}/mo** | $162/yr | ${{ tiers.standard.big_files }}/mo | | |
| 11 | + | | **Basic** | **${{ tiers.founding.basic }}/mo** | $86/yr | ${{ tiers.standard.basic }}/mo | | |
| 12 | + | | **Small Files** | **${{ tiers.founding.small_files }}/mo** | $130/yr | ${{ tiers.standard.small_files }}/mo | | |
| 13 | + | | **Big Files** | **${{ tiers.founding.big_files }}/mo** | $194/yr | ${{ tiers.standard.big_files }}/mo | | |
| 14 | 14 | | **Everything** | **${{ tiers.founding.everything }}/mo** | $324/yr | ${{ tiers.standard.everything }}/mo | | |
| 15 | 15 | ||
| 16 | 16 | The window closes when we reach 1,000 creators or when we exit beta, whichever comes first. After that, new signups pay the sticker price. | |
| @@ -155,7 +155,7 @@ A newsletter writer with 150 fan members at $5/month: | |||
| 155 | 155 | ||
| 156 | 156 | On a percentage-cut platform at 10%, you'd pay $75.00 in platform fees instead of ${{ tiers.standard.basic | int }}.00. At 20%, $150.00. | |
| 157 | 157 | ||
| 158 | - | **Break-even:** Your tier fee pays for itself at three $5 sales (or two $10 sales). | |
| 158 | + | **Break-even:** Your tier fee pays for itself at four $5 sales (or two $10 sales). | |
| 159 | 159 | ||
| 160 | 160 | ### Small Files (${{ tiers.standard.small_files | int }}/month tier) | |
| 161 | 161 |
| @@ -0,0 +1,191 @@ | |||
| 1 | + | <!DOCTYPE html> | |
| 2 | + | <html lang="en"> | |
| 3 | + | <head> | |
| 4 | + | <meta charset="UTF-8"> | |
| 5 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| 6 | + | <title>Content — Makenot.work</title> | |
| 7 | + | <link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,400;0,700;1,400&family=Lato:wght@400;700&family=Young+Serif&display=swap" rel="stylesheet"> | |
| 8 | + | <link rel="stylesheet" href="docs.css"> | |
| 9 | + | </head> | |
| 10 | + | <body class="padded-page"> | |
| 11 | + | <header class="site-header"><a href="./index.html">makenot<span class="dot">.</span>work</a></header> | |
| 12 | + | <article class="doc-container"> | |
| 13 | + | <nav class="doc-nav"><a href="./index.html">Docs</a> / Guide</nav> | |
| 14 | + | <h1>Content<span class="dot">.</span></h1> | |
| 15 | + | <p>Creating, uploading, and managing content on the platform.</p> | |
| 16 | + | <h2 id="choosing-what-to-create">Choosing What to Create</h2> | |
| 17 | + | <p>What are you making, and how should fans experience it?</p> | |
| 18 | + | <table> | |
| 19 | + | <thead> | |
| 20 | + | <tr> | |
| 21 | + | <th>If you’re making…</th> | |
| 22 | + | <th>Use this</th> | |
| 23 | + | <th>Why</th> | |
| 24 | + | </tr> | |
| 25 | + | </thead> | |
| 26 | + | <tbody> | |
| 27 | + | <tr> | |
| 28 | + | <td>An album or EP</td> | |
| 29 | + | <td>Audio items in a project</td> | |
| 30 | + | <td>In-browser player, cover art, track ordering</td> | |
| 31 | + | </tr> | |
| 32 | + | <tr> | |
| 33 | + | <td>A podcast</td> | |
| 34 | + | <td>Audio items with chapters</td> | |
| 35 | + | <td>RSS-compatible, timestamp navigation</td> | |
| 36 | + | </tr> | |
| 37 | + | <tr> | |
| 38 | + | <td>A novel or essay collection</td> | |
| 39 | + | <td>Text items in a project</td> | |
| 40 | + | <td>Markdown editor, clean reading view</td> | |
| 41 | + | </tr> | |
| 42 | + | <tr> | |
| 43 | + | <td>A newsletter</td> | |
| 44 | + | <td>Blog posts</td> | |
| 45 | + | <td>Free, included in RSS, separate from paid items</td> | |
| 46 | + | </tr> | |
| 47 | + | <tr> | |
| 48 | + | <td>Software or plugins</td> | |
| 49 | + | <td>Digital items with versioning</td> | |
| 50 | + | <td>Upload new versions, license key support</td> | |
| 51 | + | </tr> | |
| 52 | + | <tr> | |
| 53 | + | <td>Sample packs or presets</td> | |
| 54 | + | <td>Digital items</td> | |
| 55 | + | <td>Any file format, download tracking</td> | |
| 56 | + | </tr> | |
| 57 | + | <tr> | |
| 58 | + | <td>A course</td> | |
| 59 | + | <td>Mixed item types in a project</td> | |
| 60 | + | <td>Combine text lessons, audio, and downloads</td> | |
| 61 | + | </tr> | |
| 62 | + | </tbody> | |
| 63 | + | </table> | |
| 64 | + | <p>The type determines which player/viewer fans get and which features | |
| 65 | + | are available (chapters, versioning, license keys).</p> | |
| 66 | + | <h2 id="items">Items</h2> | |
| 67 | + | <p>Eleven item types are available (Audio, Text, Digital, Video, Image, | |
| 68 | + | Plugin, Preset, Sample, Course, Template, Bundle). See <a | |
| 69 | + | href="./items.html">Items</a> for the full type matrix with | |
| 70 | + | player/viewer support, chapters, and versioning.</p> | |
| 71 | + | <p>Choose the type when creating the item. It cannot be changed | |
| 72 | + | afterward.</p> | |
| 73 | + | <h3 id="creating-an-item">Creating an Item</h3> | |
| 74 | + | <ol type="1"> | |
| 75 | + | <li>Navigate to your project</li> | |
| 76 | + | <li>Click <strong>New Item</strong></li> | |
| 77 | + | <li>Set a <strong>title</strong> and <strong>item type</strong></li> | |
| 78 | + | <li>Optionally set a price (defaults to free)</li> | |
| 79 | + | </ol> | |
| 80 | + | <h3 id="editing-an-item">Editing an Item</h3> | |
| 81 | + | <p>From the item settings, you can update:</p> | |
| 82 | + | <ul> | |
| 83 | + | <li><strong>Title</strong>: Display name</li> | |
| 84 | + | <li><strong>Description</strong>: Shown on the item page (supports | |
| 85 | + | markdown)</li> | |
| 86 | + | <li><strong>Price</strong>: Free, fixed amount, or pay-what-you-want | |
| 87 | + | (see <a href="./03-selling.html#pricing-models">Pricing</a>)</li> | |
| 88 | + | <li><strong>Tags</strong>: Hierarchical tags for discovery</li> | |
| 89 | + | <li><strong>Cover image</strong>: Displayed on the item card and in | |
| 90 | + | social previews</li> | |
| 91 | + | </ul> | |
| 92 | + | <h3 id="publishing">Publishing</h3> | |
| 93 | + | <p>Items start as drafts. To publish:</p> | |
| 94 | + | <ol type="1"> | |
| 95 | + | <li>Edit the item and switch on <strong>Public</strong></li> | |
| 96 | + | <li>Make sure the parent project is also public</li> | |
| 97 | + | </ol> | |
| 98 | + | <p>Published items appear on your profile, in search results, and in RSS | |
| 99 | + | feeds.</p> | |
| 100 | + | <h3 id="scheduling">Scheduling</h3> | |
| 101 | + | <p>Set a future publish date to schedule content releases. The item | |
| 102 | + | becomes visible automatically at the scheduled time.</p> | |
| 103 | + | <h3 id="bulk-operations">Bulk Operations</h3> | |
| 104 | + | <p>From the project dashboard, you can publish, unpublish, or delete | |
| 105 | + | multiple items at once.</p> | |
| 106 | + | <h3 id="duplicating-an-item">Duplicating an Item</h3> | |
| 107 | + | <p>Duplicate an item to create a copy with the same settings and | |
| 108 | + | metadata. Content (files, text) is not duplicated, only metadata.</p> | |
| 109 | + | <h3 id="deleting-an-item">Deleting an Item</h3> | |
| 110 | + | <p>Deleting an item removes it permanently. Fans lose access, and active | |
| 111 | + | download codes and license keys are invalidated.</p> | |
| 112 | + | <h2 id="content-types">Content Types</h2> | |
| 113 | + | <h3 id="audio">Audio</h3> | |
| 114 | + | <p>Upload in MP3, WAV, FLAC, OGG, AAC, or AIFF format. Each audio item | |
| 115 | + | gets an in-browser player, cover image, chapter markers, and | |
| 116 | + | original-file downloads after purchase.</p> | |
| 117 | + | <p>Per-file size limits depend on your <a href="./pricing.html">pricing | |
| 118 | + | tier</a> (10MB for Basic, 500MB for Small Files, 20GB for Big Files and | |
| 119 | + | Everything).</p> | |
| 120 | + | <p>Metadata (title, artist, track number, genre, cover art) is | |
| 121 | + | auto-extracted from uploaded files. See <a | |
| 122 | + | href="./metadata.html">Metadata & SEO</a>.</p> | |
| 123 | + | <h3 id="text">Text</h3> | |
| 124 | + | <p>Write directly in the editor using markdown. Live preview, automatic | |
| 125 | + | word count and reading time, full markdown support (headers, lists, code | |
| 126 | + | blocks, links, images, tables). Fans read it without ads, | |
| 127 | + | recommendations, or sidebars.</p> | |
| 128 | + | <h3 id="digital-downloads">Digital Downloads</h3> | |
| 129 | + | <p>Upload any file type (ZIP, DMG, EXE, PDF, images, fonts). Digital | |
| 130 | + | items support versioned releases with changelogs, per-version download | |
| 131 | + | tracking, and auto-generated license keys for software products.</p> | |
| 132 | + | <h3 id="blog-posts">Blog Posts</h3> | |
| 133 | + | <p>Every project includes a blog using the same markdown editor as text | |
| 134 | + | items. Posts have draft/publish workflow, appear in the project’s RSS | |
| 135 | + | feed and data exports, and live in their own tab separate from items. | |
| 136 | + | Blog posts are always free. Use them for updates, announcements, liner | |
| 137 | + | notes, or changelogs.</p> | |
| 138 | + | <h2 id="versions--chapters">Versions & Chapters</h2> | |
| 139 | + | <p>Digital and audio items support <strong>versioned releases</strong> | |
| 140 | + | with changelogs and download tracking. Audio items also support | |
| 141 | + | <strong>chapters</strong> (timestamp markers for in-track navigation). | |
| 142 | + | See <a href="./items.html">Items</a> for full details on both | |
| 143 | + | features.</p> | |
| 144 | + | <h2 id="organizing-your-content">Organizing Your Content</h2> | |
| 145 | + | <h3 id="three-layers">Three Layers</h3> | |
| 146 | + | <ol type="1"> | |
| 147 | + | <li><strong>Profile</strong> (<code>/u/you</code>): Your public page, | |
| 148 | + | shows all your projects</li> | |
| 149 | + | <li><strong>Projects</strong> (<code>/p/project-name</code>): Albums, | |
| 150 | + | series, collections</li> | |
| 151 | + | <li><strong>Items</strong> (<code>/i/uuid</code>): Individual tracks, | |
| 152 | + | files, posts</li> | |
| 153 | + | </ol> | |
| 154 | + | <h3 id="tags-vs-projects">Tags vs Projects</h3> | |
| 155 | + | <table> | |
| 156 | + | <thead> | |
| 157 | + | <tr> | |
| 158 | + | <th>Use Tags For</th> | |
| 159 | + | <th>Use Projects For</th> | |
| 160 | + | </tr> | |
| 161 | + | </thead> | |
| 162 | + | <tbody> | |
| 163 | + | <tr> | |
| 164 | + | <td>Genre, mood, style</td> | |
| 165 | + | <td>Albums, series</td> | |
| 166 | + | </tr> | |
| 167 | + | <tr> | |
| 168 | + | <td>Cross-cutting attributes</td> | |
| 169 | + | <td>Sequential content</td> | |
| 170 | + | </tr> | |
| 171 | + | <tr> | |
| 172 | + | <td>Search and filtering</td> | |
| 173 | + | <td>Direct navigation</td> | |
| 174 | + | </tr> | |
| 175 | + | <tr> | |
| 176 | + | <td>Multiple per item</td> | |
| 177 | + | <td>One per item</td> | |
| 178 | + | </tr> | |
| 179 | + | </tbody> | |
| 180 | + | </table> | |
| 181 | + | <p>An item belongs to one project but can have many tags. See <a | |
| 182 | + | href="./tags.html">Tagging System</a> for the full specification.</p> | |
| 183 | + | <h3 id="featured-content">Featured Content</h3> | |
| 184 | + | <p>Pin items or projects to your profile page. Rearrange pinned content | |
| 185 | + | by dragging.</p> | |
| 186 | + | <h3 id="hide">Hide</h3> | |
| 187 | + | <p>Hide old content without deleting. Hidden items don’t appear in | |
| 188 | + | search, but direct links still work. Unhide anytime.</p> | |
| 189 | + | </article> | |
| 190 | + | </body> | |
| 191 | + | </html> |
| @@ -1,112 +0,0 @@ | |||
| 1 | - | <!DOCTYPE html> | |
| 2 | - | <html lang="en"> | |
| 3 | - | <head> | |
| 4 | - | <meta charset="UTF-8"> | |
| 5 | - | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| 6 | - | <title>Projects — Makenot.work</title> | |
| 7 | - | <link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,400;0,700;1,400&family=Lato:wght@400;700&family=Young+Serif&display=swap" rel="stylesheet"> | |
| 8 | - | <link rel="stylesheet" href="docs.css"> | |
| 9 | - | </head> | |
| 10 | - | <body class="padded-page"> | |
| 11 | - | <header class="site-header"><a href="./index.html">makenot<span class="dot">.</span>work</a></header> | |
| 12 | - | <article class="doc-container"> | |
| 13 | - | <nav class="doc-nav"><a href="./index.html">Docs</a> / Guide</nav> | |
| 14 | - | <h1>Projects <span class="dot">.</span></h1> | |
| 15 | - | <p>Projects group your items under a single page with its own URL, | |
| 16 | - | settings, and feed.</p> | |
| 17 | - | <hr /> | |
| 18 | - | <h2 id="creating-a-project">Creating a Project</h2> | |
| 19 | - | <p>From your Dashboard, click <strong>New Project</strong>. You’ll | |
| 20 | - | need:</p> | |
| 21 | - | <ul> | |
| 22 | - | <li><strong>Slug</strong>: URL-safe name (e.g., <code>my-album</code>). | |
| 23 | - | This becomes <code>/p/my-album</code>. Cannot be changed after | |
| 24 | - | creation.</li> | |
| 25 | - | <li><strong>Title</strong>: Display name shown on the project page.</li> | |
| 26 | - | </ul> | |
| 27 | - | <h2 id="project-settings">Project Settings</h2> | |
| 28 | - | <p>Edit your project to configure:</p> | |
| 29 | - | <ul> | |
| 30 | - | <li><strong>Description</strong>: Text shown on the project page</li> | |
| 31 | - | <li><strong>Category</strong>: Helps fans discover your work. Choose | |
| 32 | - | from 12 built-in categories (Music, Band, Podcast, Blog, Software, Art, | |
| 33 | - | etc.) or create your own</li> | |
| 34 | - | <li><strong>Visibility</strong>: Draft (only you can see it) or Public | |
| 35 | - | (visible to everyone)</li> | |
| 36 | - | </ul> | |
| 37 | - | <h2 id="categories">Categories</h2> | |
| 38 | - | <p>Categories are used for discovery and filtering. Each project can | |
| 39 | - | have one category. Built-in options include:</p> | |
| 40 | - | <table> | |
| 41 | - | <thead> | |
| 42 | - | <tr> | |
| 43 | - | <th>Category</th> | |
| 44 | - | <th>Typical Use</th> | |
| 45 | - | </tr> | |
| 46 | - | </thead> | |
| 47 | - | <tbody> | |
| 48 | - | <tr> | |
| 49 | - | <td>Music</td> | |
| 50 | - | <td>Albums, singles, EPs</td> | |
| 51 | - | </tr> | |
| 52 | - | <tr> | |
| 53 | - | <td>Band</td> | |
| 54 | - | <td>Band or artist pages</td> | |
| 55 | - | </tr> | |
| 56 | - | <tr> | |
| 57 | - | <td>Podcast</td> | |
| 58 | - | <td>Podcast feeds</td> | |
| 59 | - | </tr> | |
| 60 | - | <tr> | |
| 61 | - | <td>Blog</td> | |
| 62 | - | <td>Writing and newsletters</td> | |
| 63 | - | </tr> | |
| 64 | - | <tr> | |
| 65 | - | <td>Software</td> | |
| 66 | - | <td>Apps, plugins, tools</td> | |
| 67 | - | </tr> | |
| 68 | - | <tr> | |
| 69 | - | <td>Art</td> | |
| 70 | - | <td>Visual art, photography</td> | |
| 71 | - | </tr> | |
| 72 | - | <tr> | |
| 73 | - | <td>Education</td> | |
| 74 | - | <td>Courses, tutorials</td> | |
| 75 | - | </tr> | |
| 76 | - | <tr> | |
| 77 | - | <td>Games</td> | |
| 78 | - | <td>Game projects</td> | |
| 79 | - | </tr> | |
| 80 | - | </tbody> | |
| 81 | - | </table> | |
| 82 | - | <h2 id="visibility">Visibility</h2> | |
| 83 | - | <p>Projects start as <strong>drafts</strong>. Draft projects and their | |
| 84 | - | items are invisible to everyone except you.</p> | |
| 85 | - | <p>To publish, set visibility to <code>public</code>. All published | |
| 86 | - | items within the project become discoverable.</p> | |
| 87 | - | <h2 id="organizing-items">Organizing Items</h2> | |
| 88 | - | <p>Items are ordered within a project. You can reorder them from the | |
| 89 | - | project dashboard. Each item belongs to exactly one project.</p> | |
| 90 | - | <h2 id="blog">Blog</h2> | |
| 91 | - | <p>Every project gets a blog. Blog posts use markdown, support drafts, | |
| 92 | - | and are included in the project’s RSS feed. See <a | |
| 93 | - | href="./04-content.html">Content Types</a> for details.</p> | |
| 94 | - | <h2 id="rss-feeds">RSS Feeds</h2> | |
| 95 | - | <p>Each project automatically generates an RSS feed containing published | |
| 96 | - | items and blog posts. Fans can subscribe using any feed reader.</p> | |
| 97 | - | <h2 id="deleting-a-project">Deleting a Project</h2> | |
| 98 | - | <p>Deleting a project removes it and all its items permanently. This | |
| 99 | - | cannot be undone. Active subscriptions should be canceled first.</p> | |
| 100 | - | <hr /> | |
| 101 | - | <h2 id="see-also">See Also</h2> | |
| 102 | - | <ul> | |
| 103 | - | <li><a href="./03-items.html">Items</a> — Creating content within | |
| 104 | - | projects</li> | |
| 105 | - | <li><a href="./04-content.html">Content Types</a> — Audio, text, | |
| 106 | - | digital, and blog</li> | |
| 107 | - | <li><a href="./09-analytics.html">Analytics & Data</a> — | |
| 108 | - | Project-level stats</li> | |
| 109 | - | </ul> | |
| 110 | - | </article> | |
| 111 | - | </body> | |
| 112 | - | </html> |
| @@ -1,108 +0,0 @@ | |||
| 1 | - | <!DOCTYPE html> | |
| 2 | - | <html lang="en"> | |
| 3 | - | <head> | |
| 4 | - | <meta charset="UTF-8"> | |
| 5 | - | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| 6 | - | <title>Items — Makenot.work</title> | |
| 7 | - | <link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,400;0,700;1,400&family=Lato:wght@400;700&family=Young+Serif&display=swap" rel="stylesheet"> | |
| 8 | - | <link rel="stylesheet" href="docs.css"> | |
| 9 | - | </head> | |
| 10 | - | <body class="padded-page"> | |
| 11 | - | <header class="site-header"><a href="./index.html">makenot<span class="dot">.</span>work</a></header> | |
| 12 | - | <article class="doc-container"> | |
| 13 | - | <nav class="doc-nav"><a href="./index.html">Docs</a> / Guide</nav> | |
| 14 | - | <h1>Items <span class="dot">.</span></h1> | |
| 15 | - | <p>Items are individual pieces of content — a song, an article, a | |
| 16 | - | software release, a file download.</p> | |
| 17 | - | <hr /> | |
| 18 | - | <h2 id="item-types">Item Types</h2> | |
| 19 | - | <table> | |
| 20 | - | <thead> | |
| 21 | - | <tr> | |
| 22 | - | <th>Type</th> | |
| 23 | - | <th>Content</th> | |
| 24 | - | <th>Player/Viewer</th> | |
| 25 | - | <th>Chapters</th> | |
| 26 | - | <th>Versions</th> | |
| 27 | - | </tr> | |
| 28 | - | </thead> | |
| 29 | - | <tbody> | |
| 30 | - | <tr> | |
| 31 | - | <td><strong>Audio</strong></td> | |
| 32 | - | <td>MP3, WAV, FLAC, OGG</td> | |
| 33 | - | <td>In-browser streaming player</td> | |
| 34 | - | <td>Yes</td> | |
| 35 | - | <td>Yes</td> | |
| 36 | - | </tr> | |
| 37 | - | <tr> | |
| 38 | - | <td><strong>Text</strong></td> | |
| 39 | - | <td>Markdown</td> | |
| 40 | - | <td>Clean reading view</td> | |
| 41 | - | <td>No</td> | |
| 42 | - | <td>No</td> | |
| 43 | - | </tr> | |
| 44 | - | <tr> | |
| 45 | - | <td><strong>Digital</strong></td> | |
| 46 | - | <td>Any file (ZIP, DMG, EXE, etc.)</td> | |
| 47 | - | <td>Download link</td> | |
| 48 | - | <td>No</td> | |
| 49 | - | <td>Yes</td> | |
| 50 | - | </tr> | |
| 51 | - | </tbody> | |
| 52 | - | </table> | |
| 53 | - | <p>Choose the type when creating the item. It cannot be changed | |
| 54 | - | afterward.</p> | |
| 55 | - | <h2 id="creating-an-item">Creating an Item</h2> | |
| 56 | - | <ol type="1"> | |
| 57 | - | <li>Navigate to your project</li> | |
| 58 | - | <li>Click <strong>New Item</strong></li> | |
| 59 | - | <li>Set a <strong>title</strong> and <strong>item type</strong></li> | |
| 60 | - | <li>Optionally set a price (defaults to free)</li> | |
| 61 | - | </ol> | |
| 62 | - | <h2 id="editing-an-item">Editing an Item</h2> | |
| 63 | - | <p>From the item settings, you can update:</p> | |
| 64 | - | <ul> | |
| 65 | - | <li><strong>Title</strong>: Display name</li> | |
| 66 | - | <li><strong>Description</strong>: Shown on the item page</li> | |
| 67 | - | <li><strong>Price</strong>: Free, fixed amount, or pay-what-you-want | |
| 68 | - | (see <a href="./07-pricing.html">Pricing</a>)</li> | |
| 69 | - | <li><strong>Tags</strong>: Hierarchical tags for discovery</li> | |
| 70 | - | <li><strong>Cover image</strong>: Displayed on the item card</li> | |
| 71 | - | </ul> | |
| 72 | - | <h2 id="publishing">Publishing</h2> | |
| 73 | - | <p>Items start as drafts. To publish:</p> | |
| 74 | - | <ol type="1"> | |
| 75 | - | <li>Edit the item and set <strong>is_public</strong> to true</li> | |
| 76 | - | <li>Make sure the parent project is also public</li> | |
| 77 | - | </ol> | |
| 78 | - | <p>Published items appear on your profile, in search results, and in RSS | |
| 79 | - | feeds.</p> | |
| 80 | - | <h2 id="scheduling">Scheduling</h2> | |
| 81 | - | <p>Set a future publish date to schedule content releases. The item | |
| 82 | - | becomes visible automatically at the scheduled time.</p> | |
| 83 | - | <h2 id="bulk-operations">Bulk Operations</h2> | |
| 84 | - | <p>From the project dashboard, you can perform bulk operations on items: | |
| 85 | - | publish, unpublish, or delete multiple items at once.</p> | |
| 86 | - | <h2 id="duplicating-an-item">Duplicating an Item</h2> | |
| 87 | - | <p>Duplicate an item to create a copy with the same settings and | |
| 88 | - | metadata. Useful for creating similar items quickly. Content (files, | |
| 89 | - | text) is not duplicated — only metadata.</p> | |
| 90 | - | <h2 id="deleting-an-item">Deleting an Item</h2> | |
| 91 | - | <p>Deleting an item removes it permanently. Fans who purchased it will | |
| 92 | - | lose access. Active download codes and license keys for the item are | |
| 93 | - | invalidated.</p> | |
| 94 | - | <hr /> | |
| 95 | - | <h2 id="see-also">See Also</h2> | |
| 96 | - | <ul> | |
| 97 | - | <li><a href="./04-content.html">Content Types</a> — Uploading and | |
| 98 | - | managing content</li> | |
| 99 | - | <li><a href="./05-versions.html">Versions</a> — Release versioned | |
| 100 | - | files</li> | |
| 101 | - | <li><a href="./06-chapters.html">Chapters</a> — Audio chapter | |
| 102 | - | markers</li> | |
| 103 | - | <li><a href="./07-pricing.html">Pricing & Monetization</a> — Free, | |
| 104 | - | fixed, and PWYW</li> | |
| 105 | - | </ul> | |
| 106 | - | </article> | |
| 107 | - | </body> | |
| 108 | - | </html> |
| @@ -0,0 +1,123 @@ | |||
| 1 | + | <!DOCTYPE html> | |
| 2 | + | <html lang="en"> | |
| 3 | + | <head> | |
| 4 | + | <meta charset="UTF-8"> | |
| 5 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| 6 | + | <title>Selling & Pricing — Makenot.work</title> | |
| 7 | + | <link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,400;0,700;1,400&family=Lato:wght@400;700&family=Young+Serif&display=swap" rel="stylesheet"> | |
| 8 | + | <link rel="stylesheet" href="docs.css"> | |
| 9 | + | </head> | |
| 10 | + | <body class="padded-page"> | |
| 11 | + | <header class="site-header"><a href="./index.html">makenot<span class="dot">.</span>work</a></header> | |
| 12 | + | <article class="doc-container"> | |
| 13 | + | <nav class="doc-nav"><a href="./index.html">Docs</a> / Guide</nav> | |
| 14 | + | <h1>Selling & Pricing<span class="dot">.</span></h1> | |
| 15 | + | <p>Set prices, manage purchases, and get paid.</p> | |
| 16 | + | <h2 id="pricing-models">Pricing Models</h2> | |
| 17 | + | <p>Three models per item: <strong>free</strong>, <strong>fixed | |
| 18 | + | price</strong>, and <strong>pay-what-you-want</strong> (with optional | |
| 19 | + | minimum). Set prices when creating or editing an item. See <a | |
| 20 | + | href="./pricing.html">Pricing</a> for guidance on choosing a model.</p> | |
| 21 | + | <h2 id="membership-tiers">Membership Tiers</h2> | |
| 22 | + | <p>Offer recurring monthly memberships per project:</p> | |
| 23 | + | <ul> | |
| 24 | + | <li>Create multiple tiers with different prices</li> | |
| 25 | + | <li>Toggle tiers active/inactive without deleting them</li> | |
| 26 | + | <li>Fans join through the payment checkout</li> | |
| 27 | + | <li>The payment processor handles billing, renewals, and | |
| 28 | + | cancellations</li> | |
| 29 | + | </ul> | |
| 30 | + | <p>Membership status changes (active, past due, canceled, renewed) sync | |
| 31 | + | via webhooks and update your dashboard automatically.</p> | |
| 32 | + | <h2 id="license-keys">License Keys</h2> | |
| 33 | + | <p>For software products, license keys are generated automatically on | |
| 34 | + | purchase:</p> | |
| 35 | + | <ul> | |
| 36 | + | <li><strong>Configurable activation limits</strong>: Set how many | |
| 37 | + | machines can activate a key</li> | |
| 38 | + | <li><strong>Machine tracking</strong>: See which machines have | |
| 39 | + | activated</li> | |
| 40 | + | <li><strong>Public validation endpoint</strong>: Your software can | |
| 41 | + | verify keys against the server</li> | |
| 42 | + | <li><strong>Revocable</strong>: Deactivate keys if needed</li> | |
| 43 | + | </ul> | |
| 44 | + | <p>License keys appear in the fan’s library after purchase.</p> | |
| 45 | + | <h2 id="promo-codes">Promo Codes</h2> | |
| 46 | + | <p>Create promotional codes for discounts, free trials, and free | |
| 47 | + | access:</p> | |
| 48 | + | <ul> | |
| 49 | + | <li><strong>Percentage or fixed amount</strong> off the price</li> | |
| 50 | + | <li><strong>Free trial</strong> periods for memberships</li> | |
| 51 | + | <li><strong>Free access</strong> grants for individual items</li> | |
| 52 | + | <li><strong>Scope</strong>: Apply to a specific item, project, or all | |
| 53 | + | your items</li> | |
| 54 | + | <li><strong>Usage limits</strong>: Cap how many times a code can be | |
| 55 | + | used</li> | |
| 56 | + | <li><strong>Expiration dates</strong>: Codes stop working after a date | |
| 57 | + | you set</li> | |
| 58 | + | <li><strong>Auto-apply via URL</strong>: Share a link with | |
| 59 | + | <code>?discount=CODE</code> to pre-fill the code</li> | |
| 60 | + | </ul> | |
| 61 | + | <h2 id="download-codes">Download Codes</h2> | |
| 62 | + | <p>Generate single-use codes for free access:</p> | |
| 63 | + | <ul> | |
| 64 | + | <li><strong>Batch generation</strong>: Create many codes at once</li> | |
| 65 | + | <li><strong>Optional max uses</strong>: Limit how many times each code | |
| 66 | + | works</li> | |
| 67 | + | <li><strong>Optional expiration</strong>: Codes expire after a date</li> | |
| 68 | + | <li><strong>Useful for</strong>: Press copies, review access, | |
| 69 | + | promotional giveaways</li> | |
| 70 | + | </ul> | |
| 71 | + | <h2 id="guest-checkout">Guest Checkout</h2> | |
| 72 | + | <p>Fans can purchase without creating an account:</p> | |
| 73 | + | <ol type="1"> | |
| 74 | + | <li>Fan clicks “Buy Now” on your item page, embed, or direct purchase | |
| 75 | + | link</li> | |
| 76 | + | <li>Stripe checkout collects their email and payment</li> | |
| 77 | + | <li>Fan receives a download link via email immediately</li> | |
| 78 | + | <li>They can create an account later to manage all purchases in one | |
| 79 | + | place</li> | |
| 80 | + | </ol> | |
| 81 | + | <p>Fans who buy first and create accounts later have all purchases | |
| 82 | + | automatically attached. Guest checkout is the default for logged-out | |
| 83 | + | visitors.</p> | |
| 84 | + | <h2 id="direct-purchase-links">Direct Purchase Links</h2> | |
| 85 | + | <p>Every item has a dedicated purchase page at | |
| 86 | + | <code>/buy/{item_id}</code>: a clean page with cover art, title, price, | |
| 87 | + | and a “Buy Now” button. Use it for link-in-bio, social media posts, | |
| 88 | + | email newsletters, and QR codes on physical media. Fans purchase in one | |
| 89 | + | step.</p> | |
| 90 | + | <h2 id="payment-flow">Payment Flow</h2> | |
| 91 | + | <p>All payments go through the payment processor:</p> | |
| 92 | + | <pre><code>Fan pays → Payment processor → Creator's connected account</code></pre> | |
| 93 | + | <p>We take 0% platform fee. Only the payment processing fee (~3% + $0.30 | |
| 94 | + | per transaction) applies. See <a | |
| 95 | + | href="./tiers.html#understanding-stripes-per-transaction-fee">Pricing | |
| 96 | + | Tiers</a> for how this affects small transactions.</p> | |
| 97 | + | <h2 id="refunds">Refunds</h2> | |
| 98 | + | <p>You set your own refund policy. You process refunds directly through | |
| 99 | + | your <a href="https://dashboard.stripe.com">Stripe dashboard</a>. See <a | |
| 100 | + | href="./payouts.html#refunds">Payouts</a> for details.</p> | |
| 101 | + | <h2 id="notifications">Notifications</h2> | |
| 102 | + | <p>Email notifications for sales and account events, each individually | |
| 103 | + | toggleable in account settings: sales, new followers, tips, new releases | |
| 104 | + | from followed creators, and new device logins.</p> | |
| 105 | + | <h2 id="data-export">Data Export</h2> | |
| 106 | + | <p>Export all your data at any time. No limits on frequency. See <a | |
| 107 | + | href="./export.html">Data Export</a> for formats and details.</p> | |
| 108 | + | <h2 id="see-also">See Also</h2> | |
| 109 | + | <ul> | |
| 110 | + | <li><a href="./pricing.html">Pricing</a>: Detailed pricing model | |
| 111 | + | guidance</li> | |
| 112 | + | <li><a href="./payouts.html">Receiving Payouts</a>: How and when you get | |
| 113 | + | paid</li> | |
| 114 | + | <li><a href="./analytics.html">Analytics & Dashboard</a>: Revenue | |
| 115 | + | tracking and stats</li> | |
| 116 | + | <li><a href="./best-practices.html">Best Practices</a>: Pricing strategy | |
| 117 | + | and audience building</li> | |
| 118 | + | <li><a href="./fan-guide.html">Fan Guide</a>: The fan perspective on | |
| 119 | + | purchasing</li> | |
| 120 | + | </ul> | |
| 121 | + | </article> | |
| 122 | + | </body> | |
| 123 | + | </html> |
| @@ -1,81 +0,0 @@ | |||
| 1 | - | <!DOCTYPE html> | |
| 2 | - | <html lang="en"> | |
| 3 | - | <head> | |
| 4 | - | <meta charset="UTF-8"> | |
| 5 | - | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| 6 | - | <title>Content Types — Makenot.work</title> | |
| 7 | - | <link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,400;0,700;1,400&family=Lato:wght@400;700&family=Young+Serif&display=swap" rel="stylesheet"> | |
| 8 | - | <link rel="stylesheet" href="docs.css"> | |
| 9 | - | </head> | |
| 10 | - | <body class="padded-page"> | |
| 11 | - | <header class="site-header"><a href="./index.html">makenot<span class="dot">.</span>work</a></header> | |
| 12 | - | <article class="doc-container"> | |
| 13 | - | <nav class="doc-nav"><a href="./index.html">Docs</a> / Guide</nav> | |
| 14 | - | <h1>Content Types <span class="dot">.</span></h1> | |
| 15 | - | <p>What you can upload and how it’s delivered to fans.</p> | |
| 16 | - | <hr /> | |
| 17 | - | <h2 id="audio">Audio</h2> | |
| 18 | - | <p>Upload audio files in MP3, WAV, FLAC, or OGG format. Each audio item | |
| 19 | - | gets:</p> | |
| 20 | - | <ul> | |
| 21 | - | <li><strong>In-browser player</strong>: Stream without downloading. | |
| 22 | - | Custom player with playback controls.</li> | |
| 23 | - | <li><strong>Cover image</strong>: Album art displayed in the player and | |
| 24 | - | on the item card.</li> | |
| 25 | - | <li><strong>Chapters</strong>: Timestamp markers for navigating within | |
| 26 | - | the track. See <a href="./06-chapters.html">Chapters</a>.</li> | |
| 27 | - | <li><strong>Downloads</strong>: Fans can download the original file | |
| 28 | - | after purchase.</li> | |
| 29 | - | </ul> | |
| 30 | - | <p>Upload your audio file from the item’s content tab. Large files are | |
| 31 | - | supported — there are no per-file size limits.</p> | |
| 32 | - | <h2 id="text">Text</h2> | |
| 33 | - | <p>Write directly in the markdown editor. Features include:</p> | |
| 34 | - | <ul> | |
| 35 | - | <li><strong>Live preview</strong>: See rendered output as you type</li> | |
| 36 | - | <li><strong>Word count</strong>: Automatically calculated</li> | |
| 37 | - | <li><strong>Reading time</strong>: Estimated based on word count</li> | |
| 38 | - | <li><strong>Full markdown support</strong>: Headers, lists, code blocks, | |
| 39 | - | links, images, tables</li> | |
| 40 | - | </ul> | |
| 41 | - | <p>Text content is stored and rendered on the platform. Fans read it in | |
| 42 | - | a clean, distraction-free view.</p> | |
| 43 | - | <h2 id="digital-downloads">Digital Downloads</h2> | |
| 44 | - | <p>Upload any file type. Digital items support:</p> | |
| 45 | - | <ul> | |
| 46 | - | <li><strong>Any format</strong>: ZIP, DMG, EXE, PDF, images, fonts — | |
| 47 | - | whatever you make</li> | |
| 48 | - | <li><strong>Versioned releases</strong>: Upload new versions with | |
| 49 | - | changelogs. See <a href="./05-versions.html">Versions</a>.</li> | |
| 50 | - | <li><strong>Download tracking</strong>: See how many times each version | |
| 51 | - | has been downloaded</li> | |
| 52 | - | <li><strong>License keys</strong>: Auto-generated keys for software | |
| 53 | - | products. See <a href="./07-pricing.html">Pricing</a>.</li> | |
| 54 | - | </ul> | |
| 55 | - | <h2 id="blog-posts">Blog Posts</h2> | |
| 56 | - | <p>Every project includes a blog. Blog posts use the same markdown | |
| 57 | - | editor as text items, plus:</p> | |
| 58 | - | <ul> | |
| 59 | - | <li><strong>Draft/publish workflow</strong>: Write drafts, publish when | |
| 60 | - | ready</li> | |
| 61 | - | <li><strong>Included in RSS</strong>: Published posts appear in the | |
| 62 | - | project’s RSS feed</li> | |
| 63 | - | <li><strong>Included in data exports</strong>: Blog posts export | |
| 64 | - | alongside all other project data</li> | |
| 65 | - | <li><strong>Separate from items</strong>: Blog posts don’t appear in | |
| 66 | - | your item list — they have their own tab</li> | |
| 67 | - | </ul> | |
| 68 | - | <p>Blog posts are always free. Use them for updates, announcements, | |
| 69 | - | liner notes, or changelogs.</p> | |
| 70 | - | <hr /> | |
| 71 | - | <h2 id="see-also">See Also</h2> | |
| 72 | - | <ul> | |
| 73 | - | <li><a href="./06-chapters.html">Chapters</a> — Audio timestamp | |
| 74 | - | markers</li> | |
| 75 | - | <li><a href="./05-versions.html">Versions</a> — Versioned file | |
| 76 | - | releases</li> | |
| 77 | - | <li><a href="./03-items.html">Items</a> — Item types and settings</li> | |
| 78 | - | </ul> | |
| 79 | - | </article> | |
| 80 | - | </body> | |
| 81 | - | </html> |
| @@ -1,80 +0,0 @@ | |||
| 1 | - | <!DOCTYPE html> | |
| 2 | - | <html lang="en"> | |
| 3 | - | <head> | |
| 4 | - | <meta charset="UTF-8"> | |
| 5 | - | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| 6 | - | <title>Versions — Makenot.work</title> | |
| 7 | - | <link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,400;0,700;1,400&family=Lato:wght@400;700&family=Young+Serif&display=swap" rel="stylesheet"> | |
| 8 | - | <link rel="stylesheet" href="docs.css"> | |
| 9 | - | </head> | |
| 10 | - | <body class="padded-page"> | |
| 11 | - | <header class="site-header"><a href="./index.html">makenot<span class="dot">.</span>work</a></header> | |
| 12 | - | <article class="doc-container"> | |
| 13 | - | <nav class="doc-nav"><a href="./index.html">Docs</a> / Guide</nav> | |
| 14 | - | <h1>Versions <span class="dot">.</span></h1> | |
| 15 | - | <p>Track releases of digital and audio items with version numbers and | |
| 16 | - | changelogs.</p> | |
| 17 | - | <hr /> | |
| 18 | - | <h2 id="creating-a-version">Creating a Version</h2> | |
| 19 | - | <p>From the item dashboard, add a new version:</p> | |
| 20 | - | <ul> | |
| 21 | - | <li><strong>Version number</strong> (required): Any string up to 50 | |
| 22 | - | characters (e.g., <code>1.0.0</code>, <code>v2</code>, | |
| 23 | - | <code>2024-03-01</code>)</li> | |
| 24 | - | <li><strong>Changelog</strong> (optional): Up to 10,000 characters | |
| 25 | - | describing what changed</li> | |
| 26 | - | <li><strong>File</strong>: Optionally attach a new file to this | |
| 27 | - | version</li> | |
| 28 | - | </ul> | |
| 29 | - | <h2 id="how-is_current-works">How is_current Works</h2> | |
| 30 | - | <p>Only one version per item can be marked as “current.” When you create | |
| 31 | - | a new version:</p> | |
| 32 | - | <ol type="1"> | |
| 33 | - | <li>All existing versions are marked | |
| 34 | - | <code>is_current = false</code></li> | |
| 35 | - | <li>The new version is marked <code>is_current = true</code></li> | |
| 36 | - | </ol> | |
| 37 | - | <p>This happens atomically — there’s no moment where zero or multiple | |
| 38 | - | versions are current.</p> | |
| 39 | - | <p>Fans downloading the item get the current version by default.</p> | |
| 40 | - | <h2 id="changelogs">Changelogs</h2> | |
| 41 | - | <p>Use changelogs to tell fans what changed. Changelogs are plain text, | |
| 42 | - | up to 10,000 characters. Keep them concise — fans want to know what’s | |
| 43 | - | new, not read a novel.</p> | |
| 44 | - | <h2 id="download-tracking">Download Tracking</h2> | |
| 45 | - | <p>Each version tracks its download count independently. This helps you | |
| 46 | - | see which versions fans are using.</p> | |
| 47 | - | <h2 id="listing-versions">Listing Versions</h2> | |
| 48 | - | <p>The public version list is ordered newest-first (by creation date). | |
| 49 | - | Only published items expose their version list — draft items return a | |
| 50 | - | 404.</p> | |
| 51 | - | <h2 id="validation">Validation</h2> | |
| 52 | - | <table> | |
| 53 | - | <thead> | |
| 54 | - | <tr> | |
| 55 | - | <th>Field</th> | |
| 56 | - | <th>Rule</th> | |
| 57 | - | </tr> | |
| 58 | - | </thead> | |
| 59 | - | <tbody> | |
| 60 | - | <tr> | |
| 61 | - | <td>Version number</td> | |
| 62 | - | <td>1-50 characters, required</td> | |
| 63 | - | </tr> | |
| 64 | - | <tr> | |
| 65 | - | <td>Changelog</td> | |
| 66 | - | <td>0-10,000 characters, optional</td> | |
| 67 | - | </tr> | |
| 68 | - | </tbody> | |
| 69 | - | </table> | |
| 70 | - | <hr /> | |
| 71 | - | <h2 id="see-also">See Also</h2> | |
| 72 | - | <ul> | |
| 73 | - | <li><a href="./03-items.html">Items</a> — Item types and settings</li> | |
| 74 | - | <li><a href="./04-content.html">Content Types</a> — Upload formats</li> | |
| 75 | - | <li><a href="./09-analytics.html">Analytics & Data</a> — Download | |
| 76 | - | tracking and exports</li> | |
| 77 | - | </ul> | |
| 78 | - | </article> | |
| 79 | - | </body> | |
| 80 | - | </html> |