Send yourself messages, cache your notes, and sync them with all your devices
Click me to read why I have developed this app
Background story
So many people I know send themselves (or friends) messages on WhatsApp as a way to quickly write something down. I do the same for many years with a group in which I am the only member. I love it because messages are synced, you can search them, and you don't need to care about any structure - just send anything super quick.
Unfortunately, the WhatsApp approach is not perfect. You always have to find the right chat first and messages can't be easily marked as done or categorized. Also, WhatsApp or other messengers can be quite distracting. Examples are when you open the web client during work because you want to search for a message and are then confronted with new messages from friends, or when you compose a longer message while brainstorming and then receive messages.
WhatsNote focuses on the use case of sending, tagging and checking off messages quickly and distraction-free. In addition, the scratchpads make it easy to collect ideas and organize thoughts.
- Tiny, installable, progressive web app that works offline
- Chat with yourself
- Tag and send a message in one click
- Super quickly filter messages by tag
- Check off, edit, or delete messages
- Hide checked off messages
- Search messages with a fuzzy search
- Quickly organize your thoughts in plain text scratchpads
- Live sync with all your devices
- Just start typing and the chat input focuses automatically
- Ctrl + Space to focus the chat input
- Tab to focus the send button and cycle through the message tags
- Esc to leave the focus of the send buttons and focus the input field again
- Ctrl + z or Ctrl + y to undo/redo
The production release of WhatsNote runs in a single Node.js-based Docker container. You can find the Dockerfile here. You can run the container with the following environment variables:
- PORT (default=8080,
integer
, port at which the server should listen) - LOG_LEVEL (default=warn,
string
, one of trace, debug, info, warn, error, or fatal) - COOKIE_SECURE (default=true,
boolean
, send cookie only on secure connection) - COOKIE_MAX_AGE (default=30 days,
integer
, number of milliseconds until the session cookie expires) - COOKIE_SECRET (required and minimum 32 characters long,
string
, to sign the cookie)
git clone [email protected]:bttger/whats-note.git
cd whats-note
docker build -t bttger/whatsnote:<tag> .
docker run --name whatsnote -d -p 8080:8080 -e COOKIE_SECRET=... whatsnote
The container runs a simple Node.js server without TLS termination. When running it in production, you should always run a TLS termination proxy in front of it to encrypt the communication between client and server. Look into Certbot, Caddy, or other tools that provide simple TLS termination. The following command starts a Caddy proxy which automatically provisions a TLS certificate to encrypt traffic. But keep in mind that you need to open port 80 and 443, and you need to link your public domain name to the IP address of your server.
caddy reverse-proxy --from MY-DOMAIN.xyz --to localhost:8080
This repository also contains a half-baked Helm chart to deploy a single container to a Kubernetes cluster. I solely created it because I already had a cluster running and wanted to quickly deploy it for some friends. Usually Kubernetes is totally overkill for this app.
# Create a values.local.yaml file in the ~/chart/whats-note directory to save the cookie.secret value
# Install the chart:
helm upgrade whatsnote-prod . --install --namespace whatsnote --create-namespace --atomic --timeout 2m -f ./values.local.yaml
This mono repository contains the backend (Fastify API server) and frontend code (Vite+Svelte SPA). The project uses npm workspaces. See their docs for more info about the CLI commands. But don't worry, once the project structure is set up, you don't really need to care about workspaces.
- e2e encryption (I am not a cryptography expert so help is very welcome. Everything should already be in place, we would just need to implement the encryption and decryption of the
data
field of events.) - export and import client data as JSON file
- tabs and tags customization
- abort editing a message
- send photo
- send file
- send audio message
- remind me notifications
- link title previews (would imply privacy issues because of the PWA nature)
- state bar (not sure about this one, maybe show some visual state if there are events unsynced or if it is disconnected)
- UI design overhaul
- markdown input with preview for each token that is not actively edited (like Obsidian and Silver Bullet)
- litestream backups/replication
- fastify request and response validation
- automated tests
In the root directory, run npm ci --workspaces
.
Run npm outdated
or npm update --workspaces --dry-run
to check which updates are available. You can then check the package's changelog and make sure the updates are desired. Remove the --dry-run
flag (and optionally set a workspace) to install updates.
# Set the environment variables before starting the server
COOKIE_SECRET=xxx node backend/src/index.js
# If you start the server through the npm script,
# you won't be able to gracefully shutdown the server
npm run start --workspace backend
npm run dev --workspace frontend
To prevent CORS errors, you must run the API and vite dev server under the same host. This repository contains a simple Caddyfile with a reverse proxy configuration for local development.
docker run --rm --network host --name caddy --volume $PWD/Caddyfile:/etc/caddy/Caddyfile:ro caddy
Now with the backend, frontend, and reverse proxy running, you can start developing.
The following command builds all artifacts and saves them in the ./frontend/dist
directory.
npm run build -w frontend