board / site / index.html
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>board — serverless p2p e2e whiteboard</title>
<style>
  :root {
    --bg: #0d1117; --panel: #161b22; --panel-2: #1c2129; --border: #262c36;
    --text: #e6edf3; --muted: #8b949e; --accent: #3fb68b; --accent-2: #2ea043;
  }
  * { margin: 0; padding: 0; box-sizing: border-box; }
  body {
    background: var(--bg); color: var(--text);
    font: 16px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    padding: 40px 20px 80px;
  }
  main { max-width: 780px; margin: 0 auto; }
  h1 { font-size: 34px; letter-spacing: 1px; }
  h1 .lock { font-size: 24px; }
  .tag { color: var(--muted); margin: 6px 0 30px; font-size: 17px; }
  h2 { margin: 44px 0 12px; font-size: 22px; color: var(--accent); }
  h3 { margin: 24px 0 8px; font-size: 17px; }
  p, li { color: #c9d3dd; }
  ul { padding-left: 22px; margin: 10px 0; }
  li { margin: 5px 0; }
  a { color: var(--accent); }
  pre {
    background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
    padding: 14px 16px; overflow-x: auto; margin: 12px 0;
    font: 13.5px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace;
  }
  code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 14px;
    background: var(--panel-2); border-radius: 5px; padding: 1px 6px; }
  pre code { background: none; padding: 0; }
  .card {
    background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
    padding: 18px 20px; margin: 14px 0;
  }
  .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; }
  .muted { color: var(--muted); font-size: 14px; }
  .btn {
    display: inline-block; background: var(--accent-2); color: #fff; text-decoration: none;
    font-weight: 600; border-radius: 10px; padding: 12px 22px; margin: 8px 12px 8px 0;
  }
  .btn.ghost { background: var(--panel-2); border: 1px solid var(--border); }
  footer { margin-top: 60px; color: var(--muted); font-size: 13px; }
  .langs {
    position: fixed; top: 12px; right: 14px; color: var(--muted); font-size: 13px;
    letter-spacing: .06em; user-select: none;
  }
  .langs button {
    font: inherit; color: inherit; background: none; border: 0; padding: 3px 4px;
    cursor: pointer; opacity: .55;
  }
  .langs button.on { color: var(--accent); opacity: 1; }
</style>
</head>
<body>
<nav class="langs" id="langs"></nav>

<main data-lang-block lang="en">
  <h1><span class="lock">▦</span> board</h1>
  <p class="tag">a <strong>serverless p2p end-to-end-encrypted infinite whiteboard</strong> — draw together, no accounts, no server. This page is also the git repo.</p>

  <a class="btn" href="https://board.ardegazu.ro">open the live board</a>
  <a class="btn ghost" href="browse/index.html">browse the code</a>
  <a class="btn ghost" href="#clone">clone the repo</a>

  <h2 id="clone">Clone</h2>
  <p>This site serves the repository over git's dumb-HTTP protocol as plain static files (there is no git server here, or any server at all):</p>
  <pre><code>git clone https://git.ardegazu.ro/board.git</code></pre>

  <h2>What it is</h2>
  <div class="grid">
    <div class="card"><h3>an infinite board</h3>
      <p class="muted">Pen (with Apple Pencil pressure), text, sticky notes, shapes, connectors that follow the shapes they attach to, images pasted from the clipboard, an eraser, and PNG export — on an endless white or black canvas.</p></div>
    <div class="card"><h3>truly peer-to-peer</h3>
      <p class="muted">Boards are capability links; everything is end-to-end encrypted and replicated member⇄member over WebRTC. Changes made while alone reach late joiners through an encrypted offline mailbox the server cannot read.</p></div>
    <div class="card"><h3>private boards</h3>
      <p class="muted">A board's creator can switch it from anyone-with-the-link to a strict allow-list: strangers holding the URL can only knock — name, message, key fingerprint — and any approved member can let them in.</p></div>
    <div class="card"><h3>installable PWA</h3>
      <p class="muted">Home-screen app on iPhone, iPad and macOS with safe-area-aware chrome; the same build runs in any modern browser, served as static files.</p></div>
  </div>

  <h2>The stack</h2>
  <ul>
    <li><strong>The board secret never leaves the browser.</strong> It lives in the URL fragment (<code>#…</code>); HKDF derives every network-visible identifier one-way.</li>
    <li><strong>Replicated, encrypted history.</strong> Every change is an op in an end-to-end-encrypted append-only log (OrbitDB on Helia), folded identically on every member. History lives on members' devices.</li>
    <li><strong>Blind infrastructure.</strong> A libp2p circuit relay bootstraps browsers to direct WebRTC; the offline mailbox stores only ciphertext it cannot read.</li>
    <li><strong>Shared p2p core.</strong> <code>client/src/lib/</code> is the sueta p2p stack (see <a href="https://git.ardegazu.ro/chat/">chat</a>), reused unchanged; the board is <code>client/src/app/</code> on top.</li>
  </ul>

  <footer>MIT licensed · part of <a href="https://git.ardegazu.ro/">git.ardegazu.ro</a> · lives at <a href="https://board.ardegazu.ro">board.ardegazu.ro</a></footer>
</main>

<main data-lang-block lang="ro" hidden>
  <h1><span class="lock">▦</span> board</h1>
  <p class="tag">o <strong>tablă albă infinită p2p, criptată cap-la-cap, fără server</strong> — desenați împreună, fără conturi, fără server. Pagina asta e și repo-ul git.</p>

  <a class="btn" href="https://board.ardegazu.ro">deschide tabla live</a>
  <a class="btn ghost" href="browse/index.html">răsfoiește codul</a>
  <a class="btn ghost" href="#clone-ro">clonează repo-ul</a>

  <h2 id="clone-ro">Clonare</h2>
  <p>Situl servește repository-ul prin protocolul dumb-HTTP al lui git, ca simple fișiere statice (nu există aici niciun server git, de fapt niciun server):</p>
  <pre><code>git clone https://git.ardegazu.ro/board.git</code></pre>

  <h2>Ce este</h2>
  <div class="grid">
    <div class="card"><h3>o tablă infinită</h3>
      <p class="muted">Creion (cu presiune pentru Apple Pencil), text, notițe, forme, conectori care urmăresc formele de care sunt prinși, imagini lipite din clipboard, radieră și export PNG — pe o pânză nesfârșită, albă sau neagră.</p></div>
    <div class="card"><h3>cu adevărat peer-to-peer</h3>
      <p class="muted">Tablele sunt linkuri-capabilitate; totul e criptat cap-la-cap și replicat membru⇄membru prin WebRTC. Modificările făcute de unul singur ajung la cei care intră mai târziu printr-o cutie poștală offline criptată, pe care serverul n-o poate citi.</p></div>
    <div class="card"><h3>table private</h3>
      <p class="muted">Creatorul unei table o poate trece de la oricine-are-linkul la o listă strictă de acces: străinii cu URL-ul pot doar să bată la ușă — nume, mesaj, amprenta cheii — și orice membru aprobat îi poate lăsa înăuntru.</p></div>
    <div class="card"><h3>PWA instalabil</h3>
      <p class="muted">Aplicație pe ecranul de start pe iPhone, iPad și macOS, cu interfață care respectă safe-area; același build rulează în orice browser modern, servit ca fișiere statice.</p></div>
  </div>

  <h2>Stiva</h2>
  <ul>
    <li><strong>Secretul tablei nu pleacă niciodată din browser.</strong> Stă în fragmentul URL-ului (<code>#…</code>); HKDF derivă unidirecțional fiecare identificator vizibil în rețea.</li>
    <li><strong>Istoric replicat, criptat.</strong> Fiecare modificare e un op într-un jurnal append-only criptat cap-la-cap (OrbitDB pe Helia), împăturit identic la fiecare membru. Istoricul trăiește pe dispozitivele membrilor.</li>
    <li><strong>Infrastructură oarbă.</strong> Un releu circuit libp2p pornește browserele spre WebRTC direct; cutia poștală offline stochează doar ciphertext pe care nu-l poate citi.</li>
    <li><strong>Nucleu p2p comun.</strong> <code>client/src/lib/</code> e stiva p2p din sueta (vezi <a href="https://git.ardegazu.ro/chat/">chat</a>), refolosită neschimbată; tabla e <code>client/src/app/</code> deasupra.</li>
  </ul>

  <footer>Licență MIT · parte din <a href="https://git.ardegazu.ro/">git.ardegazu.ro</a> · trăiește la <a href="https://board.ardegazu.ro">board.ardegazu.ro</a></footer>
</main>

<main data-lang-block lang="hu" hidden>
  <h1><span class="lock">▦</span> board</h1>
  <p class="tag"><strong>szerver nélküli, p2p, végponttól végpontig titkosított végtelen rajztábla</strong> — rajzoljatok együtt, fiók nélkül, szerver nélkül. Ez az oldal egyben a git repó is.</p>

  <a class="btn" href="https://board.ardegazu.ro">az élő tábla megnyitása</a>
  <a class="btn ghost" href="browse/index.html">kód böngészése</a>
  <a class="btn ghost" href="#clone-hu">repó klónozása</a>

  <h2 id="clone-hu">Klónozás</h2>
  <p>Az oldal a repót a git dumb-HTTP protokollján át szolgálja ki, sima statikus fájlokként (nincs itt git szerver, sőt semmilyen szerver):</p>
  <pre><code>git clone https://git.ardegazu.ro/board.git</code></pre>

  <h2>Mi ez</h2>
  <div class="grid">
    <div class="card"><h3>végtelen tábla</h3>
      <p class="muted">Toll (Apple Pencil nyomásérzékeléssel), szöveg, cetlik, alakzatok, az alakzataikat követő összekötők, vágólapról beillesztett képek, radír és PNG-export — végtelen fehér vagy fekete vásznon.</p></div>
    <div class="card"><h3>valóban peer-to-peer</h3>
      <p class="muted">A táblák capability-linkek; minden végponttól végpontig titkosított, és tagtól tagig replikálódik WebRTC-n. Az egyedül végzett módosítások egy titkosított offline postaládán át érik el a később érkezőket — a szerver nem tudja elolvasni őket.</p></div>
    <div class="card"><h3>privát táblák</h3>
      <p class="muted">A tábla létrehozója átválthatja bárki-a-linkkel módról szigorú engedélylistára: az URL-t birtokló idegenek csak kopogtathatnak — név, üzenet, kulcs-ujjlenyomat —, és bármelyik jóváhagyott tag beengedheti őket.</p></div>
    <div class="card"><h3>telepíthető PWA</h3>
      <p class="muted">Kezdőképernyős app iPhone-on, iPaden és macOS-en, safe-area-tudatos kerettel; ugyanaz a build bármely modern böngészőben fut, statikus fájlokként kiszolgálva.</p></div>
  </div>

  <h2>A stack</h2>
  <ul>
    <li><strong>A tábla titka soha nem hagyja el a böngészőt.</strong> Az URL fragmentben él (<code>#…</code>); minden hálózaton látható azonosítót HKDF származtat egyirányúan.</li>
    <li><strong>Replikált, titkosított történet.</strong> Minden módosítás egy op egy végponttól végpontig titkosított append-only naplóban (OrbitDB Helián), minden tagnál azonosan összehajtva. A történet a tagok eszközein él.</li>
    <li><strong>Vak infrastruktúra.</strong> Egy libp2p circuit relay indítja a böngészőket a közvetlen WebRTC felé; az offline postaláda csak olvashatatlan ciphertextet tárol.</li>
    <li><strong>Közös p2p mag.</strong> A <code>client/src/lib/</code> a sueta p2p stackje (lásd <a href="https://git.ardegazu.ro/chat/">chat</a>), változatlanul újrahasznosítva; a tábla a <code>client/src/app/</code> fölötte.</li>
  </ul>

  <footer>MIT licenc · a <a href="https://git.ardegazu.ro/">git.ardegazu.ro</a> része · itt él: <a href="https://board.ardegazu.ro">board.ardegazu.ro</a></footer>
</main>

<script>
(function () {
  var LANGS = ["en", "ro", "hu"];
  var KEY = "ardegazu-site:lang";
  var lang = null;
  try { lang = localStorage.getItem(KEY); } catch (e) {}
  if (LANGS.indexOf(lang) < 0) {
    var cands = navigator.languages || [navigator.language];
    for (var i = 0; i < cands.length; i++) {
      var p = (cands[i] || "").slice(0, 2).toLowerCase();
      if (LANGS.indexOf(p) >= 0) { lang = p; break; }
    }
  }
  if (LANGS.indexOf(lang) < 0) lang = "en";

  var nav = document.getElementById("langs");
  function apply(l) {
    lang = l;
    document.documentElement.lang = l;
    try { localStorage.setItem(KEY, l); } catch (e) {}
    var blocks = document.querySelectorAll("[data-lang-block]");
    for (var i = 0; i < blocks.length; i++) blocks[i].hidden = blocks[i].getAttribute("lang") !== l;
    var btns = nav.querySelectorAll("button");
    for (var j = 0; j < btns.length; j++) btns[j].className = btns[j].textContent === l ? "on" : "";
  }
  LANGS.forEach(function (l, i) {
    if (i) nav.appendChild(document.createTextNode(" · "));
    var b = document.createElement("button");
    b.type = "button";
    b.textContent = l;
    b.addEventListener("click", function () { apply(l); });
    nav.appendChild(b);
  });
  apply(lang);
})();
</script>
</body>
</html>

static mirror of HEAD · about · clone: git clone https://git.ardegazu.ro/board.git