lwid / docs
Home GitHub

How lwid works

An encrypted, zero-knowledge platform for sharing small web apps.

Security model

End-to-end encryption

Every file is encrypted with AES-256-GCM in your browser before it leaves your machine. The server only ever receives and stores opaque ciphertext blobs.

Zero-knowledge server

The server never sees your content, your keys, or your filenames. It stores content-addressed blobs identified by their IPFS CIDv1 hash — nothing more.

Keys live in the URL fragment

The decryption key is encoded in the #fragment part of the URL. Browsers never send the fragment to the server — it stays entirely client-side.

Architecture

  You (browser / CLI)                           Server
  ┌──────────────────────┐                ┌──────────────────┐
  │                      │                │                  │
  │  1. Generate keys    │                │  Stores only:    │
  │     - AES-256-GCM    │   encrypted    │  - CID → blob    │
  │     - Ed25519 seed   │──── blobs ────▶│  - project → CID │
  │                      │                │                  │
  │  2. Encrypt files    │                │  Never sees:     │
  │  3. Compute CID      │                │  - plaintext     │
  │  4. Upload blobs     │                │  - keys          │
  │  5. Build manifest   │                │  - filenames     │
  │  6. Sign & upload    │                │                  │
  │                      │                └──────────────────┘
  └──────────────────────┘

  URL: /p/{project-id-OA4cCJ3}#{read-key}:{write-key}
       └─── sent to server ──┘└───── never sent ────┘
Encryption & keys

When you create a project, two keys are generated client-side:

  • Read key (32 bytes) — AES-256-GCM symmetric key used to encrypt and decrypt all file content.
  • Write key (32 bytes) — Ed25519 seed used to derive a signing keypair. The server stores only the public key and verifies signatures on manifest updates.

Both keys are encoded as base64url (no padding) and placed in the URL fragment: #readkey:writekey. A view-only URL omits the write key: #readkey.

Content-addressed storage

Each encrypted blob is hashed with SHA2-256 and stored under its IPFS CIDv1 (multicodec raw, multibase base32lower). This means:

  • Identical content is stored once (deduplication).
  • Integrity is verifiable by recomputing the hash.
  • The server cannot tamper with content without detection.
Manifests & versioning

A manifest is a JSON document listing all files in a version: path, CID, and size for each entry. The manifest itself is encrypted, uploaded as a blob, and its CID becomes the project's root.

Each manifest points to its predecessor via a parent CID, forming a linked version chain. Updating the root requires a valid Ed25519 signature from the write key.

Service Worker sandbox

In the browser, files are decrypted in the main thread and passed to a Service Worker via postMessage. The SW intercepts fetch requests under /sandbox/ and serves the decrypted files from memory, so the project renders in a sandboxed <iframe> without any plaintext hitting the network.

Usage

Web UI

  1. Go to lookwhatidid.xyz.
  2. Drop your project folder (must contain an index.html).
  3. Click Create & Share.
  4. You'll be redirected to your project's URL with both keys in the fragment.
  5. Share the view-only link (read key only) or the edit link (both keys).

CLI

Install the lwid CLI:

curl -fsSL https://raw.githubusercontent.com/Marlinski/lwid/main/install.sh | sh

First push (new project)

cd my-project/
lwid push --server https://lookwhatidid.xyz --dir .

This generates keys, creates the project, encrypts and uploads all files, and prints the shareable URL. A .lwid.json config file is saved in the directory.

Important: Add .lwid.json to your .gitignore immediately — it contains your encryption and signing keys.

Update an existing project

lwid push

Reads config from .lwid.json in the current directory.

Pull a project

lwid pull --dir .

Project info

lwid info

Prints project ID, server URL, edit URL, and view-only URL.

AI agent integration

Any coding agent that supports skill files can publish to lwid automatically. Point your agent at the skill URL:

https://lookwhatidid.xyz/SKILL.md

The skill instructs the agent to install the CLI, run lwid push, and return the shareable URL. No manual steps required.

URL scheme

TypeFormatWho can…
View /p/{project-id}#{read-key} Decrypt and view the project
Edit /p/{project-id}#{read-key}:{write-key} View + push new versions

Keys are base64url-encoded (no padding). The fragment (#...) is never sent to the server by the browser.

Constraints

Source code

lwid is open source. The Rust workspace has three crates:

CratePurpose
lwid-commonShared types, AES-256-GCM crypto, Ed25519 auth, CID utilities, blob/project stores
lwid-serverAxum HTTP server, API endpoints, static file serving
lwid-cliCLI binary — push, pull, info commands

View on GitHub