notes — Personal Sticky-Notes System

Personal kanban / sticky-notes system that lives on Eric's Mac as floating frameless windows, syncs to a server, and shows on his iPhone Home Screen via a Scriptable widget. Replaces ad-hoc use of Apple Stickies and Apple Notes for short-lived task and idea capture.

Scope is firm: personal-only, forever. Not a product, never to be shared, no multi-user features.

Status

Where everything lives — canonical map

What Path
Source code ~/Projects/notes/
Repo entry point for Claude ~/Projects/notes/CLAUDE.md
Stack source of truth ~/Projects/notes/docs/TECHNOLOGY-STACK.md
In-app cheatsheet ~/Projects/notes/desktop/help.html (also reachable via tray menu → Help)
Packaged app /Applications/notes.app
Build output ~/Projects/notes/dist/notes-darwin-arm64/
User config (server URL + token) ~/Library/Application Support/notes/config.json
Window positions ~/Library/Application Support/notes/positions.json
Local SQLite (dev only) ~/Projects/notes/data/notes.db
Production SQLite droplet: /opt/ai-clients/data/notes/notes.db
Production env (AUTH_TOKEN) droplet: /opt/ai-clients/clients/notes/config.env
Production nginx site droplet: /opt/ai-clients/nginx/conf.d/notes.conf
Production compose service droplet: /opt/ai-clients/docker-compose.yml (service: notes)
Project hub (this file) ~/.claude-royal/project-notes/notes/README.md
Original build plan ~/.claude-royal/plans/does-apple-still-have-iterative-fog.md
Infrastructure memory ~/.claude-royal/projects/-Users-edowns-Desktop/memory/infrastructure_servers.md
Dashboard registration ~/.claude/skills/projects-dashboard/projects.json (id: "notes")

Components

Piece Path / URL Notes
Server (Hono + better-sqlite3) ~/Projects/notes/server/ → container on droplet Listens on :5681 inside the docker network
Mac desktop app (Electron) ~/Projects/notes/desktop/ Tray app, one frameless BrowserWindow per note. Run with npm run desktop from the project.
iOS widget (Scriptable) ~/Projects/notes/widget/notes-widget.js See widget/README.md for install steps
Backend image docker-compose service notes in /opt/ai-clients/ Built from ~/Projects/notes/Dockerfile
Data (SQLite) droplet: /opt/ai-clients/data/notes/notes.db Volume-mounted into the container
Auth secret droplet: /opt/ai-clients/clients/notes/config.env AUTH_TOKEN — also stored in 1Password

Integrations

Integration Status Where it lives
Production URL https://notes.workflows.heyroyal.co Reuses *.workflows.heyroyal.co wildcard cert + DNS
Hosting AI Clients droplet 159.89.182.182 See infrastructure_servers.md memory
DNS Cloudflare (heyroyal.co) Wildcard A record for *.workflows.heyroyal.co
TLS Let's Encrypt (certbot) /etc/letsencrypt/live/workflows.heyroyal.co/
Reverse proxy nginx-in-docker Conf at /opt/ai-clients/nginx/conf.d/notes.conf
Auth secret 1Password TBD — see "Open items"
Sites registry ~/.claude/skills/sites-dashboard/sites.json TBD — entry not added yet
Backups Volume /opt/ai-clients/data/notes/ TBD — no rotation cron yet

Daily use

/Applications/notes.app — packaged Electron app. Launch via Spotlight ("notes") or Finder. No dock icon (LSUIElement=1); lives in the menubar.

Hotkeys (registered globally — work from any app)

In-window UX

Tray menu (click menubar icon)

New note · New in column · Refresh now · Tidy notes · Show all · Hide all · All on top · Launch at login · Settings… · Quit notes

Rebuild the .app

cd ~/Projects/notes
npm run package                   # → dist/notes-darwin-arm64/notes.app
rm -rf /Applications/notes.app
cp -R dist/notes-darwin-arm64/notes.app /Applications/

Local dev (against localhost server)

cd ~/Projects/notes
node --env-file=.env server/index.js   # backend on :5681 against ./data/notes.db
npm run desktop                         # Electron app pointed at the URL in ~/Library/Application Support/notes/config.json

⚠️ The dev launch (npm run desktop) and the packaged /Applications/notes.app share the same userData directory, so don't run both at once or they'll fight over the same note windows.

For the desktop app, switch between local and production by editing ~/Library/Application Support/notes/config.json:

{ "baseUrl": "https://notes.workflows.heyroyal.co", "tokenPlain": "<token>" }

(tokenPlain is the dev-friendly fallback. Production will use Electron safeStorage once the user goes through the in-app Settings flow.)

Deploy

From the local repo:

rsync -az --delete -e "ssh -p 22" \
  --include="package.json" --include="package-lock.json" --include="Dockerfile" \
  --include="server/" --include="server/**" --exclude="*" \
  ~/Projects/notes/ root@159.89.182.182:/opt/ai-clients/notes/

ssh -p 22 root@159.89.182.182 \
  "cd /opt/ai-clients && docker compose up -d --build notes && \
   docker compose exec nginx nginx -s reload"

API surface

Method Path Notes
GET /healthz No auth
GET /api/board All columns + all notes
GET /api/snapshot Compact projection used by the iOS widget
POST /api/columns / PATCH /api/columns/:id / DELETE /api/columns/:id
POST /api/notes / PATCH /api/notes/:id / DELETE /api/notes/:id
POST /api/reorder Bulk position update used by the (retired) browser drag handler

All /api/* requires Authorization: Bearer <token>.

Open items