feat: browser client for smol mail

This commit is contained in:
randogoth 2026-09-26 15:59:28 +03:00
commit 9798d38040
19 changed files with 3331 additions and 0 deletions

92
web/index.html Normal file
View file

@ -0,0 +1,92 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>smol mail</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>smol mail</h1>
<div id="account" class="account"></div>
<nav class="actions">
<button id="fetch">fetch</button>
<button id="write">write</button>
<button id="settings-open">settings</button>
</nav>
</header>
<main id="setup" class="setup" hidden>
<h2>welcome</h2>
<p>Identity is one 32-byte seed. Back it up: it is the only secret, and losing it means losing the address.</p>
<div class="row">
<button id="create-identity">create a new identity</button>
<span>or restore from a saved seed:</span>
<input id="restore-seed" placeholder="64 hex characters" spellcheck="false">
<button id="restore-identity">restore</button>
</div>
</main>
<main id="app" hidden>
<nav id="folders" class="folders">
<button data-folder="inbox" class="active">inbox</button>
<button data-folder="sent">sent</button>
<button data-folder="contacts">contacts</button>
</nav>
<section id="list" class="list"></section>
<article id="view" class="view"><p class="placeholder">select a message</p></article>
</main>
<dialog id="compose">
<form id="compose-form" method="dialog">
<label>to <input name="to" required spellcheck="false" placeholder="alice@example.org or smol://…"></label>
<label>subject <input name="subject" spellcheck="false"></label>
<textarea name="body" rows="12"></textarea>
<footer>
<span id="compose-error" class="error"></span>
<button value="cancel">cancel</button>
<button id="send" value="send">send</button>
</footer>
</form>
</dialog>
<dialog id="settings">
<h2>settings</h2>
<section>
<h3>identity</h3>
<div id="identity-card"></div>
<button id="rotate">rotate identity</button>
</section>
<section>
<h3>account</h3>
<form id="register-form">
<input name="address" placeholder="alice@example.org[:1961]" spellcheck="false" required>
<input name="token" placeholder="invite token (if the server requires one)">
<button>register</button>
</form>
<p class="hint">registration requires a pinned server key (SPEC.md §4). Pin one first.</p>
</section>
<section>
<h3>server keys</h3>
<form id="pin-form">
<input name="host" placeholder="example.org" spellcheck="false" required>
<input name="key" placeholder="base32 public key" spellcheck="false" required>
<button>pin</button>
</form>
<ul id="pins" class="kv"></ul>
</section>
<section>
<h3>contacts</h3>
<form id="import-form">
<input name="uri" placeholder="smol://alice@example.org/mfrggzdf…" spellcheck="false" required>
<button>import</button>
</form>
</section>
<footer><button id="settings-close">close</button></footer>
</dialog>
<div id="status" class="status"></div>
<script type="module" src="js/app.js"></script>
</body>
</html>