A browser based webmail client for smol mail, a minimalist end-to-end encrypted mail protocol
Find a file
2026-10-09 13:45:43 +03:00
locales/en-US feat: base UI strings on carrier's shared Fluent source 2026-10-08 23:43:59 +03:00
nix chore: bump version to 0.2.0 2026-10-08 23:44:04 +03:00
scripts feat: base UI strings on carrier's shared Fluent source 2026-10-08 23:43:59 +03:00
test feat: adopt smolmail protocol 1.1 with accept tokens and leave-mail-on-server 2026-09-27 15:18:07 +03:00
web feat: base UI strings on carrier's shared Fluent source 2026-10-08 23:43:59 +03:00
.gitignore chore: untrack AGENTS.md, add license and AI declaration 2026-10-09 13:45:43 +03:00
AI-DECLARATION.md chore: untrack AGENTS.md, add license and AI declaration 2026-10-09 13:45:43 +03:00
bridge.py fix: send Cache-Control so a stale Nix mtime can't pin visitors to old JS 2026-09-26 20:42:48 +03:00
devbox.json feat: base UI strings on carrier's shared Fluent source 2026-10-08 23:43:59 +03:00
devbox.lock
flake.lock feat: package the bridge as a nix flake with a NixOS deploy module 2026-09-26 19:37:48 +03:00
flake.nix fix: use stdenv.hostPlatform.system, not the removed pkgs.system 2026-10-06 09:59:12 +03:00
LICENSE chore: untrack AGENTS.md, add license and AI declaration 2026-10-09 13:45:43 +03:00
README.md chore: untrack AGENTS.md, add license and AI declaration 2026-10-09 13:45:43 +03:00

gsmol

License: Apache-2.0 Built with Devbox AI-DECLARATION: copilot Nix Flake

Smol Mail in a browser tab. All the crypto, keys and mail handling run client-side in JavaScript; a small local bridge just relays bytes to a smolmaild server over WebSocket.

browser (all crypto, all keys)  ⇄  bridge.py (dumb byte pipe)  ⇄  smolmaild (TCP :1961)

The bridge holds no keys and never parses a byte of traffic. The trust boundary is the machine running the browser.

Run

devbox run serve

Open http://127.0.0.1:8096. Onboarding walks you through creating or restoring an identity (the seed is shown once — write it down), pinning your server's public key, and claiming an address. Then fetch.

Non-default server port: uv run bridge.py --allow-port <port>.

Test

devbox run test

Byte-for-byte checks against the reference vectors, protocol cases, and a live end-to-end exchange with the reference client through the bridge — the exact byte path the browser takes. Only clicking through the UI is left to a manual pass.

Deploy

nix build .#default   # -> ./result/bin/gsmol-bridge

The bridge binds to 127.0.0.1 and has no TLS of its own — for anything beyond localhost, put nginx or caddy in front. A NixOS module is included (nixosModules.default → services.gsmol-bridge) with the same options.