Skip to main content

max / makenotwork

20.4 KB · 734 lines History Blame Raw
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>Multithreaded — Pitch</title>
7 <style>
8 @import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&family=Lato:wght@300;400;700&family=Young+Serif&display=swap');
9
10 :root {
11 --bg: #ede8e1;
12 --bg-warm: #e4ddd3;
13 --bg-deep: #d8cfc3;
14 --text: #3d3530;
15 --text-secondary: #5d524a;
16 --text-muted: #8a7e74;
17 --accent: #6c5ce7;
18 --accent-light: #8577ed;
19 --green: #4caf50;
20 --red: #d62828;
21 --border: #c9c0b4;
22 --border-dark: #a89d91;
23 }
24
25 * { margin: 0; padding: 0; box-sizing: border-box; }
26
27 @page { size: letter; margin: 0; }
28
29 body {
30 font-family: 'Lato', sans-serif;
31 color: var(--text);
32 background: var(--bg);
33 line-height: 1.6;
34 -webkit-print-color-adjust: exact;
35 print-color-adjust: exact;
36 }
37
38 .page {
39 width: 8.5in;
40 min-height: 11in;
41 margin: 0 auto;
42 padding: 0.6in 0.8in;
43 background: var(--bg);
44 page-break-after: always;
45 position: relative;
46 }
47
48 .page:last-child { page-break-after: auto; }
49
50 /* ── Hero ── */
51
52 .hero {
53 text-align: center;
54 padding: 0.3in 0 0.25in;
55 border-bottom: 2px solid var(--border);
56 margin-bottom: 0.28in;
57 }
58
59 .hero h1 {
60 font-family: 'Young Serif', serif;
61 font-size: 44px;
62 font-weight: 400;
63 color: var(--text);
64 margin-bottom: 4px;
65 letter-spacing: -0.5px;
66 }
67
68 .hero h1 .mark { color: var(--accent); }
69
70 .hero .tagline {
71 font-family: 'IBM Plex Mono', monospace;
72 font-size: 14px;
73 color: var(--text-secondary);
74 letter-spacing: 0.3px;
75 }
76
77 .hero .sub {
78 font-size: 12.5px;
79 color: var(--text-muted);
80 margin-top: 8px;
81 }
82
83 /* ── Sections ── */
84
85 h2 {
86 font-family: 'IBM Plex Mono', monospace;
87 font-size: 14px;
88 font-weight: 600;
89 text-transform: uppercase;
90 letter-spacing: 1.5px;
91 color: var(--accent);
92 margin-bottom: 12px;
93 padding-bottom: 5px;
94 border-bottom: 1px solid var(--border);
95 }
96
97 h3 {
98 font-family: 'IBM Plex Mono', monospace;
99 font-size: 12.5px;
100 font-weight: 600;
101 color: var(--text);
102 margin-bottom: 5px;
103 margin-top: 14px;
104 }
105
106 h3:first-child { margin-top: 0; }
107
108 .intro {
109 font-size: 15px;
110 line-height: 1.7;
111 margin-bottom: 0.28in;
112 color: var(--text);
113 }
114
115 .intro strong { color: var(--text); }
116
117 /* ── Stats ── */
118
119 .stats {
120 display: grid;
121 grid-template-columns: repeat(4, 1fr);
122 gap: 12px;
123 margin-bottom: 0.28in;
124 }
125
126 .stat {
127 text-align: center;
128 background: var(--bg-warm);
129 border: 1px solid var(--border);
130 border-radius: 6px;
131 padding: 12px 8px;
132 }
133
134 .stat .num {
135 font-family: 'Young Serif', serif;
136 font-size: 28px;
137 color: var(--accent);
138 display: block;
139 line-height: 1;
140 margin-bottom: 4px;
141 }
142
143 .stat .label {
144 font-family: 'IBM Plex Mono', monospace;
145 font-size: 10px;
146 color: var(--text-muted);
147 text-transform: uppercase;
148 letter-spacing: 0.5px;
149 }
150
151 /* ── Feature grid ── */
152
153 .features {
154 display: grid;
155 grid-template-columns: 1fr 1fr;
156 gap: 14px;
157 margin-bottom: 0.25in;
158 }
159
160 .feature-card {
161 background: var(--bg-warm);
162 border: 1px solid var(--border);
163 border-radius: 6px;
164 padding: 14px 16px;
165 }
166
167 .feature-card h3 {
168 margin: 0 0 6px 0;
169 font-size: 12.5px;
170 color: var(--accent);
171 }
172
173 .feature-card ul { list-style: none; padding: 0; }
174
175 .feature-card li {
176 font-size: 12px;
177 line-height: 1.5;
178 color: var(--text-secondary);
179 padding: 2px 0 2px 14px;
180 position: relative;
181 }
182
183 .feature-card li::before {
184 content: '';
185 position: absolute;
186 left: 0;
187 top: 8px;
188 width: 5px;
189 height: 5px;
190 background: var(--accent);
191 border-radius: 50%;
192 }
193
194 /* ── Feature section (full width, 2-col) ── */
195
196 .feature-section { margin-bottom: 0.22in; }
197
198 .feature-section ul {
199 list-style: none;
200 padding: 0;
201 columns: 2;
202 column-gap: 24px;
203 }
204
205 .feature-section li {
206 font-size: 12px;
207 line-height: 1.5;
208 color: var(--text-secondary);
209 padding: 2.5px 0 2.5px 14px;
210 position: relative;
211 break-inside: avoid;
212 }
213
214 .feature-section li::before {
215 content: '';
216 position: absolute;
217 left: 0;
218 top: 9px;
219 width: 5px;
220 height: 5px;
221 background: var(--accent);
222 border-radius: 50%;
223 }
224
225 /* ── Highlight box ── */
226
227 .highlight-box {
228 background: var(--bg-warm);
229 border-left: 3px solid var(--accent);
230 padding: 14px 18px;
231 margin-bottom: 0.22in;
232 border-radius: 0 6px 6px 0;
233 }
234
235 .highlight-box p {
236 font-size: 13px;
237 line-height: 1.6;
238 color: var(--text-secondary);
239 }
240
241 .highlight-box strong { color: var(--text); }
242
243 /* ── Comparison table ── */
244
245 .comparison {
246 width: 100%;
247 border-collapse: collapse;
248 margin-bottom: 0.22in;
249 font-size: 12px;
250 }
251
252 .comparison th {
253 font-family: 'IBM Plex Mono', monospace;
254 font-size: 11px;
255 font-weight: 600;
256 text-align: left;
257 padding: 8px 10px;
258 background: var(--bg-deep);
259 color: var(--text);
260 border-bottom: 1px solid var(--border-dark);
261 }
262
263 .comparison td {
264 padding: 6px 10px;
265 border-bottom: 1px solid var(--border);
266 color: var(--text-secondary);
267 vertical-align: top;
268 }
269
270 .comparison .check { color: var(--green); font-weight: 700; font-size: 13px; }
271 .comparison .dash { color: var(--text-muted); }
272 .comparison tr:last-child td { border-bottom: none; }
273
274 /* ── Structure diagram ── */
275
276 .structure {
277 display: grid;
278 grid-template-columns: repeat(4, 1fr);
279 gap: 12px;
280 margin-bottom: 0.25in;
281 }
282
283 .structure-level {
284 background: var(--bg-warm);
285 border: 1px solid var(--border);
286 border-radius: 6px;
287 padding: 12px 14px;
288 text-align: center;
289 }
290
291 .structure-level .level-name {
292 font-family: 'IBM Plex Mono', monospace;
293 font-size: 12px;
294 font-weight: 600;
295 color: var(--accent);
296 display: block;
297 margin-bottom: 4px;
298 }
299
300 .structure-level .level-desc {
301 font-size: 11px;
302 color: var(--text-muted);
303 line-height: 1.35;
304 }
305
306 .structure-arrow {
307 display: none;
308 }
309
310 /* ── Two-column ── */
311
312 .two-col {
313 display: grid;
314 grid-template-columns: 1fr 1fr;
315 gap: 14px;
316 margin-bottom: 0.22in;
317 }
318
319 .two-col .col {
320 background: var(--bg-warm);
321 border: 1px solid var(--border);
322 border-radius: 6px;
323 padding: 14px 16px;
324 }
325
326 .two-col .col h3 {
327 margin: 0 0 5px 0;
328 font-size: 12.5px;
329 color: var(--accent);
330 }
331
332 .two-col .col p {
333 font-size: 12px;
334 line-height: 1.5;
335 color: var(--text-secondary);
336 }
337
338 /* ── Moderation grid ── */
339
340 .mod-actions {
341 display: grid;
342 grid-template-columns: repeat(3, 1fr);
343 gap: 10px;
344 margin-bottom: 0.22in;
345 }
346
347 .mod-action {
348 background: var(--bg-warm);
349 border: 1px solid var(--border);
350 border-radius: 6px;
351 padding: 10px 12px;
352 text-align: center;
353 }
354
355 .mod-action .action-name {
356 font-family: 'IBM Plex Mono', monospace;
357 font-size: 11px;
358 font-weight: 600;
359 color: var(--text);
360 display: block;
361 margin-bottom: 3px;
362 }
363
364 .mod-action .action-desc {
365 font-size: 10.5px;
366 color: var(--text-muted);
367 line-height: 1.35;
368 }
369
370 /* ── Footer ── */
371
372 .footer {
373 position: absolute;
374 bottom: 0.5in;
375 left: 0.8in;
376 right: 0.8in;
377 display: flex;
378 justify-content: space-between;
379 align-items: center;
380 padding-top: 12px;
381 border-top: 1px solid var(--border);
382 }
383
384 .footer .left, .footer .right {
385 font-family: 'IBM Plex Mono', monospace;
386 font-size: 10px;
387 color: var(--text-muted);
388 }
389
390 .footer-inline {
391 display: flex;
392 justify-content: space-between;
393 align-items: center;
394 padding-top: 12px;
395 border-top: 1px solid var(--border);
396 margin-top: auto;
397 }
398
399 .footer-inline .left, .footer-inline .right {
400 font-family: 'IBM Plex Mono', monospace;
401 font-size: 10px;
402 color: var(--text-muted);
403 }
404
405 @media print { body { background: white; } .page { box-shadow: none; } }
406 @media screen { body { background: #ccc; padding: 20px 0; } .page { box-shadow: 0 2px 20px rgba(0,0,0,0.15); margin-bottom: 20px; } }
407 </style>
408 </head>
409 <body>
410
411 <!-- ═══════════════════════════════════════════════════════════════════════ -->
412 <!-- PAGE 1 -->
413 <!-- ═══════════════════════════════════════════════════════════════════════ -->
414 <div class="page">
415
416 <div class="hero">
417 <h1>Multithreaded<span class="mark">.</span></h1>
418 <div class="tagline">Forum software for project communities.</div>
419 <div class="sub">Built into Makenot.work. One login, full moderation, no separate accounts to manage.</div>
420 </div>
421
422 <div class="intro">
423 Multithreaded gives every Makenot.work project a discussion space. Your supporters log in with their existing MNW account &mdash; no separate signup, no password to remember, no email verification loop. You get a clean, fast forum with categories, threads, markdown posts, and a full moderation toolkit. We built the mod tools first, not as an afterthought.
424 </div>
425
426 <div class="stats">
427 <div class="stat">
428 <span class="num">1</span>
429 <span class="label">Login for everything</span>
430 </div>
431 <div class="stat">
432 <span class="num">0</span>
433 <span class="label">Separate signups</span>
434 </div>
435 <div class="stat">
436 <span class="num">6</span>
437 <span class="label">Mod actions built in</span>
438 </div>
439 <div class="stat">
440 <span class="num">0</span>
441 <span class="label">Tracking &amp; analytics</span>
442 </div>
443 </div>
444
445 <h2>How Forums Work</h2>
446
447 <div class="structure">
448 <div class="structure-level">
449 <span class="level-name">Community</span>
450 <div class="level-desc">One per MNW project. Name, description, member list.</div>
451 </div>
452 <div class="structure-level">
453 <span class="level-name">Categories</span>
454 <div class="level-desc">Organize by topic. Custom names, slugs, ordering.</div>
455 </div>
456 <div class="structure-level">
457 <span class="level-name">Threads</span>
458 <div class="level-desc">Discussions. Sortable by activity or replies. Pin and lock.</div>
459 </div>
460 <div class="structure-level">
461 <span class="level-name">Posts</span>
462 <div class="level-desc">Markdown replies. Edit within 15 min. Soft delete.</div>
463 </div>
464 </div>
465
466 <h2>What You Get</h2>
467
468 <div class="features">
469 <div class="feature-card">
470 <h3>Threads &amp; Posts</h3>
471 <ul>
472 <li>Markdown with safe rendering (no XSS, no script injection)</li>
473 <li>Edit posts within 15 minutes (mods can edit anytime)</li>
474 <li>Edit thread titles (authors and mods)</li>
475 <li>Soft deletes preserve audit trail</li>
476 <li>Paginated threads (25/page) and posts (50/page)</li>
477 <li>"(edited)" indicator on modified posts</li>
478 </ul>
479 </div>
480 <div class="feature-card">
481 <h3>Categories</h3>
482 <ul>
483 <li>Unlimited categories per community</li>
484 <li>Custom names, URL slugs, and descriptions</li>
485 <li>Drag-to-reorder (transactional swap)</li>
486 <li>Thread counts displayed per category</li>
487 <li>Sort threads by latest activity or reply count</li>
488 </ul>
489 </div>
490 <div class="feature-card">
491 <h3>MNW Integration</h3>
492 <ul>
493 <li>OAuth 2.0 + PKCE login (one click, no new account)</li>
494 <li>User profiles link back to Makenot.work</li>
495 <li>Forum listed on MNW project page</li>
496 <li>Shared identity across all MNW services</li>
497 <li>Account suspension propagates from MNW</li>
498 </ul>
499 </div>
500 <div class="feature-card">
501 <h3>Design</h3>
502 <ul>
503 <li>Makenot.work visual language (warm beige, serif headings)</li>
504 <li>Clean tables with sort controls and pagination</li>
505 <li>Pinned/locked thread badges</li>
506 <li>Responsive layout (mobile hamburger nav)</li>
507 <li>No JavaScript required for core reading experience</li>
508 </ul>
509 </div>
510 </div>
511
512 <h2>Moderation</h2>
513
514 <div class="highlight-box">
515 <p>Moderation tools are built in from day one &mdash; not a plugin you install later. Every community gets a mod dashboard, a searchable mod log, and role-based access. Community owners appoint moderators. Moderators can ban, mute, pin, lock, and delete. Every action is logged with who did it, why, and when.</p>
516 </div>
517
518 <div class="mod-actions">
519 <div class="mod-action">
520 <span class="action-name">Ban</span>
521 <div class="action-desc">1h, 1d, 7d, 30d, or permanent. With reason. Blocks all access.</div>
522 </div>
523 <div class="mod-action">
524 <span class="action-name">Mute</span>
525 <div class="action-desc">Same durations. User can read but not post or reply.</div>
526 </div>
527 <div class="mod-action">
528 <span class="action-name">Pin / Lock</span>
529 <div class="action-desc">Pin threads to category top. Lock to prevent new replies.</div>
530 </div>
531 <div class="mod-action">
532 <span class="action-name">Delete</span>
533 <div class="action-desc">Soft-delete threads and posts. Content hidden, data preserved.</div>
534 </div>
535 <div class="mod-action">
536 <span class="action-name">Mod Log</span>
537 <div class="action-desc">Full audit trail. Paginated. Actor, target, action, reason, time.</div>
538 </div>
539 <div class="mod-action">
540 <span class="action-name">Platform Admin</span>
541 <div class="action-desc">Suspend entire communities or users at the platform level.</div>
542 </div>
543 </div>
544
545 <div class="footer">
546 <div class="left">Multithreaded &mdash; v0.2.0 alpha</div>
547 <div class="right">makenot.work</div>
548 </div>
549
550 </div>
551
552 <!-- ═══════════════════════════════════════════════════════════════════════ -->
553 <!-- PAGE 2 -->
554 <!-- ═══════════════════════════════════════════════════════════════════════ -->
555 <div class="page" style="display: flex; flex-direction: column;">
556
557 <h2>Roles &amp; Permissions</h2>
558
559 <table class="comparison" style="margin-bottom: 0.22in;">
560 <tr>
561 <th style="width:18%">Role</th>
562 <th style="width:42%">Can do</th>
563 <th style="width:40%">Cannot do</th>
564 </tr>
565 <tr>
566 <td><strong>Owner</strong></td>
567 <td>Edit community, create/reorder categories, appoint mods, all mod actions</td>
568 <td>&mdash;</td>
569 </tr>
570 <tr>
571 <td><strong>Moderator</strong></td>
572 <td>Ban, mute, pin, lock, delete posts/threads, view mod log</td>
573 <td>Edit community settings, manage categories</td>
574 </tr>
575 <tr>
576 <td><strong>Member</strong></td>
577 <td>Create threads, post replies, edit own posts (15 min window)</td>
578 <td>Mod actions, community settings</td>
579 </tr>
580 <tr>
581 <td><strong>Banned</strong></td>
582 <td>&mdash;</td>
583 <td>All access (403 on every page)</td>
584 </tr>
585 <tr>
586 <td><strong>Muted</strong></td>
587 <td>Read all content</td>
588 <td>Post, reply, edit</td>
589 </tr>
590 </table>
591
592 <div class="highlight-box" style="margin-bottom: 0.22in;">
593 <p><strong>Fail-closed access model.</strong> If the database cannot verify your permissions, you get blocked. Errors never grant access.</p>
594 </div>
595
596 <h2>Community Settings</h2>
597
598 <div class="feature-section">
599 <ul>
600 <li>Edit community name and description</li>
601 <li>Create new categories with custom name, URL slug, and description</li>
602 <li>Edit existing category names and descriptions</li>
603 <li>Reorder categories (move up / move down)</li>
604 <li>View member list with roles and join dates</li>
605 <li>All setting changes recorded in the mod log</li>
606 </ul>
607 </div>
608
609 <h2>Security</h2>
610
611 <div class="features">
612 <div class="feature-card">
613 <h3>Content Safety</h3>
614 <ul>
615 <li>Markdown rendered server-side (pulldown-cmark)</li>
616 <li>All raw HTML stripped &mdash; no script, iframe, or event handlers</li>
617 <li>URL scheme allowlist: http, https, mailto, ftp only</li>
618 <li>javascript:, data:, and vbscript: links replaced with #</li>
619 <li>CSRF tokens on all write actions</li>
620 </ul>
621 </div>
622 <div class="feature-card">
623 <h3>Infrastructure</h3>
624 <ul>
625 <li>OAuth 2.0 with PKCE (no client secrets in browser)</li>
626 <li>Session cookies: Secure, HttpOnly, SameSite=Lax</li>
627 <li>Rate limiting on all write endpoints</li>
628 </ul>
629 </div>
630 </div>
631
632 <h2>How It Compares</h2>
633
634 <table class="comparison">
635 <tr>
636 <th style="width:28%">Feature</th>
637 <th style="width:18%">Multithreaded</th>
638 <th style="width:18%">Discourse</th>
639 <th style="width:18%">Discord</th>
640 <th style="width:18%">GitHub Discussions</th>
641 </tr>
642 <tr>
643 <td>Shared login with platform</td>
644 <td><span class="check">Yes</span></td>
645 <td><span class="dash">&mdash;</span></td>
646 <td><span class="dash">&mdash;</span></td>
647 <td><span class="check">Yes</span></td>
648 </tr>
649 <tr>
650 <td>No separate account</td>
651 <td><span class="check">Yes</span></td>
652 <td><span class="dash">&mdash;</span></td>
653 <td><span class="dash">&mdash;</span></td>
654 <td><span class="check">Yes</span></td>
655 </tr>
656 <tr>
657 <td>Moderation built in</td>
658 <td><span class="check">Yes</span></td>
659 <td><span class="check">Yes</span></td>
660 <td><span class="check">Yes</span></td>
661 <td>Limited</td>
662 </tr>
663 <tr>
664 <td>Mod log / audit trail</td>
665 <td><span class="check">Yes</span></td>
666 <td><span class="check">Yes</span></td>
667 <td><span class="check">Yes</span></td>
668 <td><span class="dash">&mdash;</span></td>
669 </tr>
670 <tr>
671 <td>Timed bans &amp; mutes</td>
672 <td><span class="check">Yes</span></td>
673 <td><span class="check">Yes</span></td>
674 <td><span class="check">Yes</span></td>
675 <td><span class="dash">&mdash;</span></td>
676 </tr>
677 <tr>
678 <td>Self-hosted option</td>
679 <td><span class="check">Yes</span></td>
680 <td><span class="check">Yes</span></td>
681 <td><span class="dash">&mdash;</span></td>
682 <td><span class="dash">&mdash;</span></td>
683 </tr>
684 <tr>
685 <td>No JavaScript required</td>
686 <td><span class="check">Yes</span></td>
687 <td><span class="dash">&mdash;</span></td>
688 <td><span class="dash">&mdash;</span></td>
689 <td><span class="dash">&mdash;</span></td>
690 </tr>
691 <tr>
692 <td>Searchable &amp; archivable</td>
693 <td><span class="check">Yes</span></td>
694 <td><span class="check">Yes</span></td>
695 <td><span class="dash">&mdash;</span></td>
696 <td><span class="check">Yes</span></td>
697 </tr>
698 <tr>
699 <td>Free for creators</td>
700 <td><span class="check">Yes</span></td>
701 <td>$50+/mo</td>
702 <td>Free (ads)</td>
703 <td><span class="check">Yes</span></td>
704 </tr>
705 <tr>
706 <td>Source-available</td>
707 <td><span class="check">Yes</span></td>
708 <td><span class="check">Yes</span></td>
709 <td><span class="dash">&mdash;</span></td>
710 <td><span class="dash">&mdash;</span></td>
711 </tr>
712 <tr>
713 <td>Zero tracking</td>
714 <td><span class="check">Yes</span></td>
715 <td><span class="dash">&mdash;</span></td>
716 <td><span class="dash">&mdash;</span></td>
717 <td><span class="dash">&mdash;</span></td>
718 </tr>
719 </table>
720
721 <div class="highlight-box">
722 <p><strong>Included with your MNW project.</strong> No additional cost, no setup, no server to manage. Your community forum lives at the same place your project does. Conversations are public and indexable &mdash; not locked behind a Discord server that search engines can't see. Source-available under PolyForm Noncommercial 1.0.0.</p>
723 </div>
724
725 <div class="footer-inline" style="margin-top: 14px;">
726 <div class="left">Multithreaded &mdash; v0.2.0 alpha</div>
727 <div class="right">makenot.work</div>
728 </div>
729
730 </div>
731
732 </body>
733 </html>
734