Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Zenshare

An anonymous static HTML sharing service built on Cloudflare Workers and D1.

Features

  • Upload a single .html file up to 512KB with an alias and optional metadata.
  • Shares are accessible at /s/<alias>.
  • Alias availability is checked before upload and enforced with a unique D1 index.
  • Default expiration is 7 days; choose 1-30 days. Expired records are removed by a daily UTC 20:00 cron job and lazily on read.
  • D1 keeps up to 2000 shares. When full, creation returns a "storage full" response.
  • Backdoor convention: entering zenshare/<name> as the alias stores <name> as a permanent share and the same availability check applies.
  • Optional password protection: files are encrypted in the browser with PBKDF2 and AES-256-GCM; the server never stores passwords.
  • Reader pages render content in a sandboxed iframe with meta info, HTML download, PDF export, and a share button.
  • Responsive layout, light/dark theme, and Chinese/English UI.

Project Layout

src/index.js          Worker routes, API, cron cleanup
public/               Upload and reader page assets
migrations/           D1 migration
scripts/smoke-test.mjs Local smoke test (encryption + API round trip)
wrangler.toml         Worker / D1 / cron configuration

Local Development

npm install
npm run db:local
npm run dev

The local server runs at http://127.0.0.1:8787.

Run the smoke test:

npm run smoke

The smoke test creates a password-protected share and verifies upload, read, decryption, wrong-password rejection, and alias duplicate detection.

Database

The D1 binding is defined in wrangler.toml. Do not publish credentials or database identifiers in public documentation.

Create the schema in the remote D1 database:

wrangler login
npm run db:remote

The Worker also runs idempotent CREATE TABLE IF NOT EXISTS statements on first access, so a missing migration will not break the service.

Deploy

npm run deploy

The Worker name, routes, and cron trigger are defined in wrangler.toml.

API

Check Alias

GET /api/alias-check?alias=demo

Returns availability, the normalized alias, and whether the backdoor prefix was used.

Create Share

POST /api/share
Content-Type: application/json
{
  "alias": "demo",
  "title": "Report title",
  "description": "Description",
  "author": "Author",
  "tags": ["report", "demo"],
  "expires_days": 7,
  "password_protected": true,
  "content": "base64(ciphertext or plaintext)",
  "salt": "base64(16 bytes)",
  "iv": "base64(12 bytes)"
}

expires_days defaults to 7 and must be between 1 and 30. When password_protected is true, salt and iv are required.

Security Notes

  • Password-protected shares are zero-knowledge: the key is derived in the reader's browser and the server only stores ciphertext, salt, and IV.
  • Unprotected shares are stored as plaintext.
  • Reader pages render uploaded HTML inside an iframe without allow-same-origin, so uploaded scripts cannot access the Zenshare origin.
  • Permanent shares are not editable or deletable through the UI; remove them directly in D1 if needed.

License

MIT. See LICENSE.

Open Source

github.com/fakeoder/zenshare

About

share static html reports from here.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages