Case · Web app · TypeScript

scratch-notes: "Draft", an offline Markdown note editor

A demo concept of an offline Markdown note editor on SolidJS: data in IndexedDB, no server and no accounts. A live preview, an own full-text search (BM25, RU/EN stemming, keyboard-layout correction), edit history with a line diff, per-note password encryption (PBKDF2 with 600,000 iterations + AES-256-GCM, WebCrypto), .md and .zip import and export with an own ZIP writer.

  • SolidJS
  • TypeScript
  • Vite
  • IndexedDB
  • WebCrypto
  • PWA
  • fast-check
  • vitest
  • axe
  • Cloudflare Pages
  • GitHub Actions

01 · How it looks

Screenshots

Screenshot of the project "scratch-notes: "Draft", an offline Markdown note editor" at 1280 pixels wide
Desktop, 1280 px
Screenshot of the project "scratch-notes: "Draft", an offline Markdown note editor" on a phone screen, 390 pixels wide
Phone, 390 px

02 · About

What it is and why

The task: an offline note editor that needs no server and lets you encrypt a single note with a password, stating honestly what that protects against and what it does not.

The solution: SolidJS + TypeScript, data in IndexedDB, every write goes through a sequential queue. The Markdown parser and sanitizer come from md-safe together with the XSS vector corpus.

Limitations

No sync or collaboration; two tabs on one note are last-write-wins.

Search over the text of encrypted notes works only while they are open.

Encryption does not protect against malicious extensions, keyloggers, a weak password or losing it (there is no reset), and metadata stays open.

A demo concept, not a password-manager replacement.

What is inside

  • Note encryption: PBKDF2-HMAC-SHA-256 with 600,000 iterations, a 16-byte salt, AES-256-GCM, a fresh IV on every save, the note id in AAD; the text and history snapshots are encrypted
  • An own in-memory full-text index: RU/EN tokenization, simple stemming, BM25 with field weights, prefix, "phrases", #tags, wrong-layout correction
  • Edit history: up to 50 snapshots per note, merging of frequent edits, a line diff, rollback
  • An own ZIP writer (store, CRC-32) and reader (store and deflate) with limits against bombs; .md, .zip import and export, a JSON backup
  • 777 tests, including the XSS corpus from md-safe; hotkeys by e.code on any layout; axe 0
  • Deployed on Cloudflare Pages, a service worker with a versioned cache, CSP without inline code

03 · How to run

Run it locally

git clone <repository on request> scratch-notes
cd scratch-notes
npm ci
npm run dev

04 · Code

The repository is private

The source is in a private repository. Message me on Telegram and I will open access.

Request the code