Skip to content

Repository files navigation

Notepad

A minimal, self-hosted online notepad. Open a URL, start typing — your text is saved automatically and synced to any tab pointing at the same URL.

Demo Note: The data of the demo will be wiped on an ad-hoc basis

Bun server · Vite + TypeScript frontend · SQLite storage · ships as a single static binary in a small Docker image.

The ktor-BE branch runs the same features on Ktor/Kotlin. Feature parity, same wire protocol, same session cookie contract — only the backend implementation differs.


Features

Editing & sync

  • URL is the identity — visit /anything and you have a note.
  • Live sync over WebSocket, debounced per keystroke, multi-tab safe.
  • Auto-reconnect with exponential back-off; unsent edits are buffered and flushed.
  • Cmd/Ctrl-S forces an immediate flush.
  • 20 MB max content size per note.
  • Empty notes are not persisted; deleting all content removes the row.

Presentation

  • Light / Dark theme (Solarized-dark variant).
  • Font family (15+ mono / sans / serif), font size (12–48 px), line wrapping, line numbers.
  • All view settings saved per note in localStorage (LRU-capped at 200).

Sharing

  • Password protect / change / remove per note.
  • Read-only share link, one-click copy.
  • View as raw text or rendered Markdown (with highlight.js syntax highlighting).

Admin page (/admin)

  • Opt-in via NOTEPAD_ADMIN_PW env var. Disabled by default.
  • Login-gated table of all notes, sortable by size / updated time.
  • Per-row actions (Gmail-style hover): view content, open in new tab, set/remove password, delete.
  • Bulk-select + bulk-delete.
  • Rate-limited login; admin session auto-expires after 8 h.

Hardening

  • Signed session cookies (SameSite=Strict, HttpOnly, Secure in prod).
  • WebSocket bound to your own note key — cross-note writes blocked.
  • Rate limits on unlock, admin login, and writes.
  • Refuses to start if SESSION_SIGN_KEY is unset, too short, or equals the known-leaked default from earlier in the repo history.

How to self-host

1. Requirements

  • Docker (or Podman) — nothing else on the host.

2. Environment variables

Env var Required Purpose
SESSION_SIGN_KEY Yes Random hex ≥ 32 chars for signing session cookies. Generate: openssl rand -hex 32. Refuses to start without.
NOTEPAD_ADMIN_PW No (unset → admin disabled) Plain-text password for the /admin page. Leave unset to hide/disable the admin feature.
DB_PATH No (/data/note.db in Docker) SQLite file path.
PORT No (8080) TCP port to listen on.
NODE_ENV No (production in Docker) Set to production to enable the Secure cookie flag (requires HTTPS).
STATIC_ROOT No (auto-detected) Override the frontend build directory. Defaults to frontend/dist next to the source or the executable.

3. Run with Docker

docker run -d --name notepad \
  -p 8080:8080 \
  -v $HOME/notepad-data:/data \
  -e SESSION_SIGN_KEY=$(openssl rand -hex 32) \
  -e NOTEPAD_ADMIN_PW=change-me \
  notepad:latest

Notepad at http://localhost:8080, admin at http://localhost:8080/admin.

4. Or with docker-compose

services:
  notepad:
    image: notepad:latest
    restart: unless-stopped
    ports: ["8080:8080"]
    volumes:
      - ./notepad-data:/data
    environment:
      SESSION_SIGN_KEY: ${SESSION_SIGN_KEY:?run: openssl rand -hex 32}
      NOTEPAD_ADMIN_PW: ${NOTEPAD_ADMIN_PW:-}

5. Build your own image

docker build -t notepad:local .

6. Run locally without Docker

cd frontend && bun install && bun run build && cd ..
SESSION_SIGN_KEY=$(openssl rand -hex 32) bun server/index.ts

Or bun run dev for hot reload.


License

MIT — see LICENSE.

About

a simple notepad app for self-hosting

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages