| 1 |
<div class="tab-docs"><a href="/docs/getting-started">Docs: Getting Started →</a></div> |
| 2 |
|
| 3 |
{% if can_create_projects %} |
| 4 |
<div class="creator-tab-section creator-tab-section--centered"> |
| 5 |
<h2 class="creator-h2">You have creator access</h2> |
| 6 |
<p class="muted mb-5">You can create projects and publish content.</p> |
| 7 |
<button class="btn-primary" |
| 8 |
hx-get="/dashboard/tabs/projects" |
| 9 |
hx-target="#tab-content" |
| 10 |
hx-swap="innerHTML" |
| 11 |
onclick="document.getElementById('tab-projects').click()">Go to Projects</button> |
| 12 |
</div> |
| 13 |
|
| 14 |
<div class="creator-tab-section creator-tab-section--no-top"> |
| 15 |
<h2 class="creator-h2 creator-h2--sm mb-3">Creator Plan</h2> |
| 16 |
{% if let Some(label) = creator_tier_label %} |
| 17 |
<div class="creator-plan-box mb-4"> |
| 18 |
<div class="creator-plan-head"> |
| 19 |
<span class="creator-plan-name">{{ label }}</span> |
| 20 |
{% if let Some(status) = creator_sub_status %} |
| 21 |
{% if status == "active" %} |
| 22 |
<span class="badge active">Active</span> |
| 23 |
{% else if status == "past_due" %} |
| 24 |
<span class="badge pending">Past Due</span> |
| 25 |
{% else %} |
| 26 |
<span class="badge">{{ status }}</span> |
| 27 |
{% endif %} |
| 28 |
{% endif %} |
| 29 |
{% if is_founder_locked %} |
| 30 |
<span class="badge badge--founder-locked" title="Founder pricing is locked in for the life of this account.">Founder · locked for life</span> |
| 31 |
{% else if is_founder && founder_window_open %} |
| 32 |
<span class="badge badge--founder-pending" title="Founder pricing applies while the window is open. Stay subscribed until the window closes to lock it in for life.">Founder · pending lock-in</span> |
| 33 |
{% endif %} |
| 34 |
</div> |
| 35 |
{% if let Some(period_end) = creator_period_end %} |
| 36 |
<p class="muted text-sm">Current period ends {{ period_end }}</p> |
| 37 |
{% endif %} |
| 38 |
<p class="muted text-sm mt-2">{{ storage_total }} of {{ storage_max }} storage used ({{ storage_pct }}%). <a href="/docs/guide/tiers" class="muted">Plan limits →</a></p> |
| 39 |
</div> |
| 40 |
{% else %} |
| 41 |
<p class="muted text-sm mb-4"> |
| 42 |
No active plan. During alpha, all creator features are available without a membership. |
| 43 |
</p> |
| 44 |
{% if founder_window_open || is_founder_locked %} |
| 45 |
<div class="founder-callout mb-4"> |
| 46 |
{% if is_founder_locked %} |
| 47 |
<p class="m-0 text-sm"><strong>Your founder pricing is locked in.</strong> The rates below show the founder rate for each tier: you can subscribe (or upgrade later) at this rate for the life of your account.</p> |
| 48 |
{% else %} |
| 49 |
<p class="m-0 text-sm"><strong>Founder pricing window is open.</strong> Subscribe now to lock in half-price creator memberships for life. Window closes at 1,000 creators or exit-beta, whichever first. <a href="/docs/pricing">How it works →</a></p> |
| 50 |
{% endif %} |
| 51 |
</div> |
| 52 |
{% endif %} |
| 53 |
{% if creator_tiers_configured %} |
| 54 |
{% let show_founder_rate = founder_window_open || is_founder_locked %} |
| 55 |
<div class="creator-tier-grid mb-4"> |
| 56 |
{% for card in tier_cards %} |
| 57 |
<div class="creator-tier-card"> |
| 58 |
<div class="creator-tier-name"><a href="/docs/guide/tiers" class="creator-tier-link">{{ card.label }}</a></div> |
| 59 |
{% if show_founder_rate %} |
| 60 |
<div class="meta mb-2"><strong>${{ card.founder_monthly }}/mo</strong> <span class="strike-dim">${{ card.standard_monthly }}</span></div> |
| 61 |
<div class="meta creator-tier-sub mb-2">or ${{ card.founder_annual }}/yr (10% off)</div> |
| 62 |
{% else %} |
| 63 |
<div class="meta mb-2">${{ card.standard_monthly }}/mo</div> |
| 64 |
<div class="meta creator-tier-sub mb-2">or ${{ card.standard_annual }}/yr (10% off)</div> |
| 65 |
{% endif %} |
| 66 |
<div class="meta creator-tier-storage mb-3">{{ card.storage }}</div> |
| 67 |
<div class="creator-tier-buttons"> |
| 68 |
<form method="post" action="/stripe/creator-tier" class="m-0"> |
| 69 |
{% if let Some(token) = csrf_token %}<input type="hidden" name="_csrf" value="{{ token }}">{% endif %} |
| 70 |
<input type="hidden" name="tier" value="{{ card.key }}"> |
| 71 |
<input type="hidden" name="interval" value="monthly"> |
| 72 |
<button type="submit" class="btn-primary creator-tier-btn" data-loading-text="Redirecting to Stripe...">Monthly</button> |
| 73 |
</form> |
| 74 |
<form method="post" action="/stripe/creator-tier" class="m-0"> |
| 75 |
{% if let Some(token) = csrf_token %}<input type="hidden" name="_csrf" value="{{ token }}">{% endif %} |
| 76 |
<input type="hidden" name="tier" value="{{ card.key }}"> |
| 77 |
<input type="hidden" name="interval" value="annual"> |
| 78 |
<button type="submit" class="btn-secondary creator-tier-btn" data-loading-text="Redirecting to Stripe...">Annual (save 10%)</button> |
| 79 |
</form> |
| 80 |
</div> |
| 81 |
</div> |
| 82 |
{% endfor %} |
| 83 |
</div> |
| 84 |
<p class="text-center mb-4"><a href="/docs/guide/tiers" class="text-sm">Full tier details →</a></p> |
| 85 |
<p class="text-center text-sm muted mb-4"> |
| 86 |
Upgrades take effect immediately and are prorated. Downgrades take effect at the next billing period; if you're over the new tier's storage cap, new uploads stay blocked until you're under it, but your existing content stays published either way. |
| 87 |
</p> |
| 88 |
{% endif %} |
| 89 |
{% endif %} |
| 90 |
</div> |
| 91 |
|
| 92 |
<div class="section-group-label creator-section-label">Usage</div> |
| 93 |
|
| 94 |
<details class="form-section creator-form-section"> |
| 95 |
<summary><h2 class="creator-h2 creator-h2--sm">Storage ({{ storage_total }} / {{ storage_max }})</h2></summary> |
| 96 |
<div class="storage-box mb-4"> |
| 97 |
<div class="storage-row"> |
| 98 |
<span>{{ storage_total }} of {{ storage_max }} used</span> |
| 99 |
<span class="muted">{{ storage_pct }}%</span> |
| 100 |
</div> |
| 101 |
<div class="storage-track"> |
| 102 |
<div class="storage-fill {% if storage_pct >= 90 %}storage-fill--full{% endif %}" style="width: {{ storage_pct }}%"></div> |
| 103 |
</div> |
| 104 |
<div class="storage-breakdown"> |
| 105 |
<span class="muted">Audio: {{ storage_audio }}</span> |
| 106 |
<span class="muted">Covers: {{ storage_covers }}</span> |
| 107 |
<span class="muted">Downloads: {{ storage_downloads }}</span> |
| 108 |
<span class="muted">Clips: {{ storage_insertions }}</span> |
| 109 |
<span class="muted">Video: {{ storage_video }}</span> |
| 110 |
<span class="muted">Media: {{ storage_media }}</span> |
| 111 |
</div> |
| 112 |
</div> |
| 113 |
</details> |
| 114 |
|
| 115 |
<div class="section-group-label creator-section-label">Outreach</div> |
| 116 |
|
| 117 |
<details class="form-section creator-form-section"> |
| 118 |
<summary><h2 class="creator-h2 creator-h2--sm">Broadcast to Followers</h2></summary> |
| 119 |
<div class="broadcast-head mb-4"> |
| 120 |
<p class="text-sm muted m-0 broadcast-desc"> |
| 121 |
Send a plain-text announcement to everyone who follows you or your projects. |
| 122 |
Limited to one broadcast per 24 hours. |
| 123 |
{% if follower_count > 0 %} |
| 124 |
<strong>{{ follower_count }}</strong> follower{% if follower_count != 1 %}s{% endif %} will receive this email. |
| 125 |
{% else %} |
| 126 |
You don't have any followers yet. |
| 127 |
{% endif %} |
| 128 |
</p> |
| 129 |
{% if follower_count > 0 %} |
| 130 |
<button class="btn-secondary text-sm broadcast-export nowrap" |
| 131 |
onclick="this.textContent='Exporting...'; this.disabled=true; var btn=this; fetch('/api/export/followers', {method:'POST', headers: csrfHeaders()}).then(function(r){return r.blob()}).then(function(b){var a=document.createElement('a'); a.href=URL.createObjectURL(b); a.download='followers.csv'; a.click(); btn.textContent='Export CSV'; btn.disabled=false;}).catch(function(){btn.textContent='Export CSV'; btn.disabled=false; showToast('Export failed')});">Export CSV</button> |
| 132 |
{% endif %} |
| 133 |
</div> |
| 134 |
<form hx-post="/api/broadcast" hx-target="#broadcast-result" hx-swap="innerHTML" |
| 135 |
hx-confirm="Send this broadcast to {{ follower_count }} follower{% if follower_count != 1 %}s{% endif %}?"> |
| 136 |
<div class="form-group"> |
| 137 |
<label for="broadcast-subject">Subject</label> |
| 138 |
<input type="text" id="broadcast-subject" name="subject" required maxlength="200" |
| 139 |
placeholder="Subject line for your announcement"> |
| 140 |
</div> |
| 141 |
<div class="form-group"> |
| 142 |
<label for="broadcast-body">Message</label> |
| 143 |
<textarea id="broadcast-body" name="body" rows="6" required maxlength="5000" |
| 144 |
placeholder="Your announcement..."></textarea> |
| 145 |
</div> |
| 146 |
<div id="broadcast-result"></div> |
| 147 |
<button type="submit" class="btn-primary">Send Broadcast</button> |
| 148 |
</form> |
| 149 |
</details> |
| 150 |
|
| 151 |
{% if invites_enabled %} |
| 152 |
<details class="form-section creator-form-section"> |
| 153 |
<summary><h2 class="creator-h2 creator-h2--sm">Invite Codes</h2></summary> |
| 154 |
<p class="muted text-sm mb-4"> |
| 155 |
Invite people to Makenotwork. They skip the pitch but still need admin approval. |
| 156 |
{{ active_invite_count }}/{{ invite_limit }} active. |
| 157 |
</p> |
| 158 |
|
| 159 |
{% if active_invite_count < invite_limit %} |
| 160 |
<div id="invite-result" class="mb-4"></div> |
| 161 |
<button class="btn-primary mb-5" |
| 162 |
hx-post="/api/invites/create" |
| 163 |
hx-target="#invite-result" |
| 164 |
hx-swap="innerHTML">Generate Invite Code</button> |
| 165 |
{% else %} |
| 166 |
<p class="dimmed text-sm mb-5"> |
| 167 |
You have reached the limit of {{ invite_limit }} active codes. Codes free up when redeemed. |
| 168 |
</p> |
| 169 |
{% endif %} |
| 170 |
|
| 171 |
{% if !invite_codes.is_empty() %} |
| 172 |
<div class="scroll-x"> |
| 173 |
<table class="compact-table" aria-label="Invite codes"> |
| 174 |
<thead> |
| 175 |
<tr> |
| 176 |
<th>Code</th> |
| 177 |
<th>Status</th> |
| 178 |
<th>Created</th> |
| 179 |
</tr> |
| 180 |
</thead> |
| 181 |
<tbody> |
| 182 |
{% for code in invite_codes %} |
| 183 |
<tr> |
| 184 |
<td class="mono-sm">{{ code.formatted_code }}</td> |
| 185 |
<td> |
| 186 |
{% if code.redeemed %} |
| 187 |
<span class="badge dimmed">Redeemed</span> |
| 188 |
{% else %} |
| 189 |
<span class="badge active">Available</span> |
| 190 |
{% endif %} |
| 191 |
</td> |
| 192 |
<td class="text-sm">{{ code.created_at }}</td> |
| 193 |
</tr> |
| 194 |
{% endfor %} |
| 195 |
</tbody> |
| 196 |
</table> |
| 197 |
</div> |
| 198 |
{% endif %} |
| 199 |
</details> |
| 200 |
{% endif %} |
| 201 |
|
| 202 |
{% else %} |
| 203 |
|
| 204 |
<div class="creator-tab-section"> |
| 205 |
<h2 class="creator-h2">Become a Creator</h2> |
| 206 |
<p class="creator-intro mb-5"> |
| 207 |
Apply for creator access to start publishing and selling your work. |
| 208 |
Tell us what you make and which tier fits. Most applications are approved within a few days. |
| 209 |
</p> |
| 210 |
</div> |
| 211 |
|
| 212 |
<hr class="creator-divider"> |
| 213 |
|
| 214 |
{% if let Some(entry) = waitlist_entry %} |
| 215 |
<div class="creator-tab-section"> |
| 216 |
<h2 class="creator-h2 mb-4">Application Submitted</h2> |
| 217 |
{% if let Some(pitch_text) = entry.pitch %} |
| 218 |
<div class="creator-pitch-box mb-4"> |
| 219 |
<div class="meta mb-2">Your pitch</div> |
| 220 |
<p>{{ pitch_text }}</p> |
| 221 |
</div> |
| 222 |
{% else %} |
| 223 |
<div class="creator-pitch-box mb-4"> |
| 224 |
<p class="muted">You were invited: no pitch required.</p> |
| 225 |
</div> |
| 226 |
{% endif %} |
| 227 |
<div class="muted text-sm"> |
| 228 |
Applied {{ entry.created_at }} |
| 229 |
{% if entry.status == "pending" %} |
| 230 |
· Status: <strong>Pending review</strong> |
| 231 |
{% else if entry.status == "approved" %} |
| 232 |
· Status: <strong>Approved</strong> |
| 233 |
{% else %} |
| 234 |
· Status: {{ entry.status }} |
| 235 |
{% endif %} |
| 236 |
</div> |
| 237 |
<p class="text-sm mt-4"> |
| 238 |
We review applications individually, usually within a few days. You'll get an email when you're approved. |
| 239 |
</p> |
| 240 |
</div> |
| 241 |
{% else %} |
| 242 |
{% if email_verified %} |
| 243 |
<div class="creator-tab-section"> |
| 244 |
<h2 class="creator-h2 mb-4">Apply for Creator Access</h2> |
| 245 |
<p class="mb-5"> |
| 246 |
Tell us what you make and which tier you need. If you have existing work online, |
| 247 |
link to it: a portfolio, channel, or profile elsewhere helps us review faster. |
| 248 |
</p> |
| 249 |
<form hx-post="/api/waitlist/apply" |
| 250 |
hx-target="closest div" |
| 251 |
hx-swap="innerHTML" |
| 252 |
id="waitlist-form"> |
| 253 |
<div class="form-group"> |
| 254 |
<label for="pitch">What do you make?</label> |
| 255 |
<textarea id="pitch" name="pitch" rows="4" |
| 256 |
minlength="20" maxlength="500" required |
| 257 |
placeholder="Briefly describe your work. A link to your portfolio, channel, or existing storefront is helpful."></textarea> |
| 258 |
<div class="hint">20-500 characters.</div> |
| 259 |
</div> |
| 260 |
<div class="form-group"> |
| 261 |
<label for="preferred-tier">Which tier fits?</label> |
| 262 |
<select id="preferred-tier" name="preferred_tier"> |
| 263 |
<option value="">Not sure yet</option> |
| 264 |
<option value="basic">Basic (${{ tier_cards[0].standard_monthly }}/mo): text, blogs, newsletters</option> |
| 265 |
<option value="small_files">Small Files (${{ tier_cards[1].standard_monthly }}/mo): audio, software, plugins</option> |
| 266 |
<option value="big_files">Big Files (${{ tier_cards[2].standard_monthly }}/mo): video, games, large software</option> |
| 267 |
<option value="everything">Everything (${{ tier_cards[3].standard_monthly }}/mo): all features, current and future</option> |
| 268 |
</select> |
| 269 |
</div> |
| 270 |
<div class="form-group"> |
| 271 |
<label> |
| 272 |
<input type="checkbox" id="free-trial" name="free_trial" value="yes" |
| 273 |
onchange="document.getElementById('trial-details').classList.toggle('hidden', !this.checked);"> |
| 274 |
I'd like to request a free trial |
| 275 |
</label> |
| 276 |
</div> |
| 277 |
<div id="trial-details" class="hidden"> |
| 278 |
<div class="form-group"> |
| 279 |
<label for="trial-length">How long do you need?</label> |
| 280 |
<select id="trial-length" name="trial_length"> |
| 281 |
<option value="2 weeks">2 weeks</option> |
| 282 |
<option value="1 month" selected>1 month</option> |
| 283 |
<option value="2 months">2 months</option> |
| 284 |
<option value="3 months">3 months</option> |
| 285 |
</select> |
| 286 |
</div> |
| 287 |
<div class="form-group"> |
| 288 |
<label for="trial-reason">What do you want to test?</label> |
| 289 |
<textarea id="trial-reason" name="trial_reason" rows="3" maxlength="500" |
| 290 |
placeholder="What feature or workflow are you unsure about? What do you need to try before committing?"></textarea> |
| 291 |
<div class="hint">Longer trials should have a specific reason: a feature you need to evaluate, a workflow you want to test with real content, etc.</div> |
| 292 |
</div> |
| 293 |
</div> |
| 294 |
<div id="apply-result"></div> |
| 295 |
<button type="submit" class="btn-primary">Submit Application</button> |
| 296 |
</form> |
| 297 |
</div> |
| 298 |
{% else %} |
| 299 |
<div class="creator-tab-section creator-tab-section--centered"> |
| 300 |
<h2 class="creator-h2 mb-4">Verify Your Email First</h2> |
| 301 |
<p class="muted mb-5"> |
| 302 |
You need a verified email address to apply for creator access. |
| 303 |
</p> |
| 304 |
<button class="btn-primary" |
| 305 |
hx-post="/api/resend-verification" |
| 306 |
hx-target="#verify-result" |
| 307 |
hx-swap="innerHTML">Resend Verification Email</button> |
| 308 |
<div id="verify-result" class="mt-4"></div> |
| 309 |
</div> |
| 310 |
{% endif %} |
| 311 |
{% endif %} |
| 312 |
{% endif %} |
| 313 |
|