fractal-threads-through-qui.../exploration.html

73 lines
578 KiB
HTML
Raw Normal View History

2026-05-02 17:47:17 +00:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fractal threads through quiet hum — exploration</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #0a0a0f; color: #3a3a4a; font-family: ui-monospace, monospace; overflow: hidden; }
#grid { padding: 20px; font-size: 12px; line-height: 1.4; white-space: pre; }
.c { display: inline-block; transition: all 0.3s; }
.c.active { color: #fde68a; text-shadow: 0 0 6px rgba(253,230,138,0.5); }
.c.strong { color: #34d399; text-shadow: 0 0 10px rgba(52,211,153,0.6); font-weight: bold; }
.c.dead { color: #1a1a2a; }
#info { position: fixed; bottom: 10px; left: 20px; color: #3a3a4a; font-size: 11px; }
#controls { position: fixed; top: 10px; right: 20px; color: #666; font-size: 11px; }
#controls span { cursor: pointer; margin-left: 12px; color: #fde68a; }
</style>
</head>
<body>
<div id="grid"></div>
<div id="info">neurameba · physarum exploration</div>
<div id="controls"><span id="play-btn">play</span><span id="reset-btn">reset</span></div>
<script>
const text = "# Email Bridge\n\nConnect your email to motd. Receive bookmarked content in your inbox. Anyone can email `username@motd.social` and it becomes a public post.\n\n---\n\n## Connect Your Email\n\nIn the motd terminal:\n\n```\n> /connect email\n\n Enter your email address: you@gmail.com\n\n Verification email sent to you@gmail.com\n Click the link in the email to confirm.\n Tip: add noreply@motd.social to your contacts so notifications don't go to spam.\n```\n\nCheck your inbox. Click the link. Done.\n\nThe link expires after 10 minutes. Type `/connect email` again for a fresh one.\n\n## Disconnect\n\n```\n> /disconnect email\n\n✓ Email disconnected.\n```\n\n---\n\n## Emailing a motd User\n\nAnyone can send an email to `username@motd.social`. The email body becomes a public post in the motd feed with the `[email]` tag.\n\n### Rules\n\n- Only the plain text body is used (HTML is stripped)\n- First 189 characters show in the feed; full post via `/goto`\n- Email signatures are stripped (`--`, `Sent from my iPhone`, etc.)\n- Reply chains (quoted text with `>`) are removed\n- Subject line is ignored\n- Attachments are ignored\n- Maximum 500 characters stored per post\n\n### How it looks\n\nFrom a connected motd user:\n```\n@bob · 5m\n@mika hey saw your project, really clean work\n [email]\n```\n\nFrom an unknown sender:\n```\nemail:john@gmail.com · 5m\n@mika hey saw your project, really clean work\n [email]\n```\n\n### Rate limits\n\nUnknown email senders: 5 emails per hour per address.\n\n---\n\n## Receiving Notifications\n\nWhen your email is connected, you receive emails for:\n\n- New posts from users you bookmarked\n- New posts matching tags you bookmarked\n- Replies to your posts\n- Posts that @mention you\n\n**Not emailed:**\n- The entire feed\n- Posts from killed/filtered users\n- Posts from users with high filter scores\n\n### Email format\n\n```\nFrom: motd.social <noreply@motd.social>\nSubject: @alice on motd.social\n\n@alice · just now\njust shipped the wasm compiler [rust] [wasm]\n\n—\nmotd.social\nReply to this email to post on motd.\n```\n\nPlain text only. Terminal aesthetic even in the inbox.\n\n### Replying to notifications\n\nReply to a notification email and your reply becomes a threaded reply on motd. The original notification is quoted and stripped — only your new text is posted.\n\n---\n\n## Notification Settings\n\nIn `/settings`, connected users see:\n\n```\nEmail notifications: on\n Notify on: bookmarked users/tags, mentions/replies\n```\n\nToggle each notification type on or off. Email and Telegram notifications are independent.\n\n---\n\n## Long Posts (Read More)\n\nPosts longer than 189 characters show an excerpt in the feed:\n\n```\n@bob · 5m\n@mika hey saw your project, really clean work. I was\nwondering if you considered a different approach to the\nparsing step because...\n [read more · 847 chars]\n [email]\n```\n\nClick `[read more]` or type `/goto [post_id]` to see the full text. This applies to all posts, not just email.\n\n---\n\n## Server Setup\n\n### Outbound (sending notifications)\n\nOutbound email uses the Brevo transactional API. No local mail server needed.\n\n- API endpoint: `POST https://api.brevo.com/v3/smtp/email`\n- Authenticated via `BREVO_API_KEY` in `.env`\n- Sender: `motd.social <noreply@motd.social>`\n- Free tier: 300 emails/day\n\nDNS records (on INWX for motd.social):\n- SPF: `v=spf1 include:sendinblue.com ~all`\n- DKIM: CNAME `brevo1._domainkey` (via Brevo dashboard)\n- DMARC: `v=DMARC1; p=none; rua=mailto:rua@dmarc.brevo.com`\n\n### Inbound (receiving email as posts)\n\nInbound email is handled by Maddy (mail server already running on the VPS for anomata.eu). Maddy receives email for `motd.social`, then forwards it via SMTP to the motd Node.js app.\n\nFlow: sender → MX → Maddy (port 25) → localhost:2525 → motd SMTP listener → post created\n\nDNS: MX record `motd.socia
const passes = [{"t":0,"r":113,"c":1,"a":"hold","s":0.2667572985537656,"ps":9,"e":100.78405838843013,"pr":1.1},{"t":0,"r":85,"c":0,"a":"died","s":0,"ps":8,"e":100,"pr":1},{"t":0,"r":6,"c":8,"a":"hold","s":0.1540735366727577,"ps":9,"e":99.88258829338206,"pr":1.1},{"t":0,"r":51,"c":2,"a":"hold","s":0.24454692450032353,"ps":9,"e":100.60637539600259,"pr":1.1},{"t":0,"r":171,"c":1,"a":"extend","s":0.4947562664325159,"ps":9,"e":71.82563509202208,"pr":1.1},{"t":1,"r":113,"c":1,"a":"hold","s":0.2702561137249388,"ps":9,"e":101.59610729822964,"pr":1.1},{"t":1,"r":6,"c":8,"a":"hold","s":0.17309819401487375,"ps":8,"e":100.06737384550105,"pr":1.05},{"t":1,"r":51,"c":2,"a":"hold","s":0.25470677439111017,"ps":8,"e":101.44402959113147,"pr":1.05},{"t":1,"r":171,"c":1,"a":"extend","s":0.4770065912634015,"ps":8,"e":52.1091814754905,"pr":1.05},{"t":1,"r":171,"c":0,"a":"extend","s":0.4517735035342632,"ps":5,"e":23.5526221473985,"pr":1.2000000000000002},{"t":2,"r":113,"c":1,"a":"retracted","s":0.2702561137249388,"ps":8,"e":102.55815620802915,"pr":1.05},{"t":2,"r":6,"c":8,"a":"retracted","s":0.1540735366727577,"ps":7,"e":100.24996213888312,"pr":1},{"t":2,"r":51,"c":2,"a":"retracted","s":0.23541883211193895,"ps":7,"e":102.27738024802699,"pr":1},{"t":2,"r":171,"c":1,"a":"extend","s":0.46590912063263046,"ps":7,"e":38.350518108386076,"pr":1},{"t":2,"r":171,"c":0,"a":"extend","s":0.4395504847921445,"ps":4,"e":18.528318218014956,"pr":1.1500000000000001},{"t":2,"r":172,"c":1,"a":"extend","s":0.399447440079967,"ps":5,"e":17.344660107094967,"pr":1.1500000000000001},{"t":2,"r":172,"c":0,"a":"extend","s":0.4363777496437488,"ps":5,"e":8.984502042224543,"pr":1.3000000000000003},{"t":3,"r":171,"c":1,"a":"extend","s":0.5131657667380081,"ps":6,"e":29.0890909696031,"pr":0.95},{"t":3,"r":171,"c":0,"a":"extend","s":0.42761290987484196,"ps":4,"e":14.944455047909582,"pr":1.1},{"t":3,"r":172,"c":1,"a":"hold","s":0.3311290953298609,"ps":4,"e":19.393692869733854,"pr":1.1},{"t":3,"r":172,"c":0,"a":"extend","s":0.5962990474428849,"ps":6,"e":8.998426095237335,"pr":1.4000000000000004},{"t":3,"r":173,"c":1,"a":"extend","s":0.5726358735617054,"ps":5,"e":7.885158924074039,"pr":1.2500000000000002},{"t":3,"r":172,"c":2,"a":"hold","s":0.3366465916038395,"ps":5,"e":9.376598493014273,"pr":1.2500000000000002},{"t":4,"r":171,"c":1,"a":"extend","s":0.5856163630020083,"ps":6,"e":23.011815311533415,"pr":0.95},{"t":4,"r":171,"c":0,"a":"extend","s":0.4160218589278037,"ps":4,"e":12.370840943532407,"pr":1.05},{"t":4,"r":172,"c":1,"a":"hold","s":0.3819378244688502,"ps":4,"e":21.849195465484655,"pr":1.05},{"t":4,"r":172,"c":0,"a":"extend","s":0.45642968916635995,"ps":6,"e":8.224904525997749,"pr":1.4000000000000004},{"t":4,"r":173,"c":1,"a":"extend","s":0.4988838399037133,"ps":4,"e":7.893360750312621,"pr":1.2000000000000002},{"t":4,"r":172,"c":2,"a":"hold","s":0.19732791573979452,"ps":5,"e":10.205221818932628,"pr":1.2500000000000002},{"t":4,"r":173,"c":0,"a":"hold","s":0.3277012518706234,"ps":5,"e":5.250963839568147,"pr":1.3500000000000003},{"t":5,"r":171,"c":1,"a":"extend","s":0.5623117617836346,"ps":5,"e":18.732216584061742,"pr":0.8999999999999999},{"t":5,"r":171,"c":0,"a":"extend","s":0.4047449997625246,"ps":4,"e":10.506160659142822,"pr":1},{"t":5,"r":172,"c":1,"a":"retracted","s":0.37278397929362256,"ps":4,"e":24.231467299833636,"pr":1},{"t":5,"r":172,"c":0,"a":"extend","s":0.44310436000276265,"ps":5,"e":7.713817584213895,"pr":1.3500000000000003},{"t":5,"r":173,"c":1,"a":"extend","s":0.5358204359321739,"ps":4,"e":8.105946966439008,"pr":1.1500000000000001},{"t":5,"r":172,"c":2,"a":"retracted","s":0.19494345410709432,"ps":4,"e":11.164769451789383,"pr":1.2000000000000002},{"t":5,"r":173,"c":0,"a":"hold","s":0.3551836847156674,"ps":4,"e":7.492433317293486,"pr":1.3000000000000003},{"t":5,"r":171,"c":2,"a":"hold","s":0.22277409734082204,"ps":5,"e":10.894399340812326,"pr":1.05},{"t":5,"r":174,"c":1,"a":"extend","s":0.6643855221780915,"ps":5,"e":5.563567149291099,"pr":1.3000000000000003},{"t":6,"r":171,"c":1,"a":"hold","s":0.3760037887345223,"ps":5,"e":20.990246893937922,"pr":0.899999999999999
const lines = text.split('\n');
const gridEl = document.getElementById('grid');
const charEls = [];
for (let r = 0; r < lines.length; r++) {
const row = [];
for (let c = 0; c < lines[r].length; c++) {
const s = document.createElement('span');
s.className = 'c';
s.textContent = lines[r][c];
row.push(s);
gridEl.appendChild(s);
}
charEls.push(row);
gridEl.appendChild(document.createTextNode('\n'));
}
let tick = -1, playing = false, iv;
function apply(t) {
for (const r of charEls) for (const e of r) e.className = 'c';
const active = new Map();
for (const p of passes) {
if (p.t > t) break;
const k = p.r+','+p.c;
if (p.a === 'died' || p.a === 'retracted') active.set(k, 'dead');
else if (p.ps > 16) active.set(k, 'strong');
else active.set(k, 'active');
}
for (const [k, cls] of active) {
const [r, c] = k.split(',').map(Number);
if (charEls[r]?.[c]) charEls[r][c].className = 'c ' + cls;
}
document.getElementById('info').textContent = 'tick ' + t + ' · ' + [...active.values()].filter(v=>v!=='dead').length + ' alive';
}
function play() {
if (playing) return;
playing = true;
document.getElementById('play-btn').textContent = 'pause';
const max = passes.length > 0 ? passes[passes.length-1].t : 0;
iv = setInterval(() => { tick++; if (tick > max) { pause(); return; } apply(tick); }, 900);
}
function pause() { playing = false; clearInterval(iv); document.getElementById('play-btn').textContent = 'play'; }
function reset() { pause(); tick = -1; for (const r of charEls) for (const e of r) e.className = 'c'; document.getElementById('info').textContent = 'neurameba'; }
document.getElementById('play-btn').addEventListener('click', () => playing ? pause() : play());
document.getElementById('reset-btn').addEventListener('click', reset);
setTimeout(play, 1000);
</script>
</body>
</html>