Basking: a place to dump thoughts, jot notes and keep a journal
Plain markdown files, tags by typing #hashtags, a page per day, search, pin and trash with undo, autosave with conflict warnings, API tokens, zip export, and the Lightwell dashboard. Includes install.sh, CI and release workflows. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
b548faa258
23 files changed
+4026
No files matched your search
@@ -0,0 +1,156 @@
|
||||
# Basking
|
||||
|
||||
A place to dump thoughts, jot notes and keep a journal. Named for the basking shark, which swims
|
||||
along with its mouth open and takes in whatever drifts by. One small binary, no database, no
|
||||
dependencies.
|
||||
|
||||
Your notes are plain markdown files in a folder you own. Basking is just a fast, comfortable way to
|
||||
write them and find them again, from a browser on your phone or your desk.
|
||||
|
||||
## What it does
|
||||
|
||||
- **Dump first, sort later.** The box at the top of Notes is always ready. Type, press Ctrl+Enter,
|
||||
keep typing. An unsaved draft survives a closed tab.
|
||||
- **Tags by typing.** Write `#errands` or `#projects/basking` anywhere in a note and it becomes a tag.
|
||||
The sidebar lists them. Numbers such as `#12` and anything inside code are left alone.
|
||||
- **A page for each day.** Today opens the day's journal page, with an Insert time button to stamp
|
||||
`20:15 ` where you are typing. Move between days, or read back over the Journal.
|
||||
- **Search** across everything as you type: every word must match, and `#tag` words filter by tag.
|
||||
- **Markdown**, rendered safely: headings, lists, checkboxes you can tick in place, quotes, code,
|
||||
links and bold and italic.
|
||||
- **Pin** what matters. **Delete** goes to a trash first, with an Undo, and nothing is lost until you
|
||||
empty it.
|
||||
- **Autosave** while you edit, and a warning (not a silent overwrite) if the same note was changed on
|
||||
another device.
|
||||
- **Send notes from anywhere.** Make an API token and post text from a script, a phone shortcut or the
|
||||
`basking add` command.
|
||||
- **Take it with you.** Download everything as a zip of `.md` files, or just copy the folder.
|
||||
|
||||
## Installing on Linux (systemd)
|
||||
|
||||
```sh
|
||||
curl -fsSL https://git.veillax.com/Veillax/basking/raw/branch/main/deploy/install.sh | sudo sh
|
||||
```
|
||||
|
||||
This downloads the latest release (checking its SHA-256), installs `/usr/local/bin/basking`, creates
|
||||
a `basking` user, `/etc/basking/` (settings) and `/var/lib/basking/` (your notes), and writes the
|
||||
systemd service and `/etc/basking/basking.env`. It then tells you what to do next:
|
||||
|
||||
```sh
|
||||
sudoedit /etc/basking/basking.env # optional: the address and where notes are kept
|
||||
sudo systemctl start basking
|
||||
journalctl -u basking -f # the first start prints your password here, once
|
||||
```
|
||||
|
||||
Run it again to upgrade; your settings and notes are kept and a running service is restarted.
|
||||
|
||||
Options: `--start` (start the service straight away), `--version v0.1.0`, `--listen 0.0.0.0:8490`,
|
||||
`--source` (build from the repository with Go instead), and `--uninstall` (add `--purge` to delete
|
||||
settings and notes). Download the script and read it first if you prefer: it is
|
||||
[`deploy/install.sh`](deploy/install.sh).
|
||||
|
||||
## Running it by hand
|
||||
|
||||
```sh
|
||||
# download a release, or: go build ./cmd/basking
|
||||
./basking serve
|
||||
```
|
||||
|
||||
On first run it writes `basking.json` and prints a password **once** in the log. Open
|
||||
http://127.0.0.1:8490 and sign in. Notes go in `./data/notes/`.
|
||||
|
||||
By default it only listens on `127.0.0.1`. To reach it from your phone, put it behind an HTTPS
|
||||
reverse proxy, or expose it through [Hammerhead](https://git.veillax.com/Veillax/hammerhead), and set
|
||||
`"cookie_secure": true` and `"trust_proxy": true` in `basking.json`. Don't put it on the open
|
||||
internet over plain HTTP: it holds your private thoughts.
|
||||
|
||||
Docker: see [`Dockerfile`](Dockerfile) and [`deploy/docker-compose.yml`](deploy/docker-compose.yml).
|
||||
|
||||
### Commands
|
||||
|
||||
```
|
||||
basking serve [-config basking.json] [-listen addr] [-data dir]
|
||||
basking password [-config ...] set a new password (BASKING_PASSWORD or stdin); restart afterwards
|
||||
basking token [-config ...] NAME make an API token (printed once)
|
||||
basking add [TEXT...] send a note to a running Basking (needs BASKING_URL and BASKING_TOKEN)
|
||||
```
|
||||
|
||||
## Settings
|
||||
|
||||
`basking.json` holds `listen` (default `127.0.0.1:8490`), `data_dir` (default `data`), the password
|
||||
hash, API token hashes, a signing secret, and `cookie_secure` and `trust_proxy` for use behind a
|
||||
proxy. The environment variables `BASKING_CONFIG`, `BASKING_LISTEN` and `BASKING_DATA` override the
|
||||
file location, address and notes folder.
|
||||
|
||||
## Where your notes are
|
||||
|
||||
```
|
||||
data/
|
||||
notes/20261031-143205-a1b2c3.md one file per note
|
||||
notes/daily-2026-10-31.md the journal page for a day
|
||||
trash/ deleted notes, until the trash is emptied
|
||||
```
|
||||
|
||||
A note file looks like this, so you can edit it with anything:
|
||||
|
||||
```
|
||||
---
|
||||
created: 2026-10-31T14:32:05.123Z
|
||||
updated: 2026-10-31T14:35:00.456Z
|
||||
pinned: true
|
||||
---
|
||||
|
||||
Call the dentist #errands
|
||||
```
|
||||
|
||||
A plain `.md` file you drop into `notes/` is picked up too, with its file time as its date (name it
|
||||
with lower-case letters, numbers and dashes). Restart Basking to see files added by hand.
|
||||
|
||||
## API
|
||||
|
||||
Sign in from a browser, or send `Authorization: Bearer bsk_...`.
|
||||
|
||||
```sh
|
||||
curl -H "Authorization: Bearer $TOKEN" -H "Content-Type: text/plain" \
|
||||
-d "Call the dentist #errands" http://127.0.0.1:8490/api/notes
|
||||
```
|
||||
|
||||
`GET /api/notes?q=&tag=&view=all|pinned|daily|trash&offset=&limit=`, `POST /api/notes` (JSON
|
||||
`{"body": "..."}` or plain text), `GET|PUT|DELETE /api/notes/{id}`, `POST /api/notes/{id}/restore`,
|
||||
`DELETE /api/trash`, `POST /api/daily` (`{"date": "2026-10-31"}`), `GET /api/summary`,
|
||||
`GET /api/export`.
|
||||
|
||||
## Security notes
|
||||
|
||||
- The password is stored as a PBKDF2-SHA256 hash and API tokens as SHA-256 hashes. `basking.json` is
|
||||
written `0600`. Failed sign-ins are rate-limited per address.
|
||||
- Sessions are `HttpOnly`, `SameSite=Strict` cookies that last 30 days, signed with a secret from the
|
||||
settings file. They are not kept on the server, so a restart does not sign you out, and signing out
|
||||
only clears this browser's cookie. Changing the password signs out every browser.
|
||||
- Every browser change needs a header a page on another site can't send. The page has a strict
|
||||
Content-Security-Policy and notes are never rendered as HTML.
|
||||
- Notes are **not encrypted** on disk. Anyone who can read the folder can read your notes.
|
||||
|
||||
## Honest limits
|
||||
|
||||
- One person, one password. There are no accounts, sharing or real-time collaboration.
|
||||
- No attachments or images, and no offline mode: it needs the server to be reachable.
|
||||
- Searching holds every note in memory, which is comfortable for tens of thousands of notes and not
|
||||
built for millions.
|
||||
- Notes are only reloaded from disk when Basking starts.
|
||||
|
||||
## Design
|
||||
|
||||
The dashboard follows the Lightwell design language, the same one Hammerhead and Megalodon use. See
|
||||
[docs/design.md](docs/design.md). `node scripts/lint-design.mjs` checks the rules a machine can check.
|
||||
|
||||
## Development
|
||||
|
||||
```sh
|
||||
go test ./...
|
||||
go run ./cmd/basking serve
|
||||
```
|
||||
|
||||
Releases are built by the Gitea workflow when a `v*` tag is pushed.
|
||||
|
||||
Licensed under the AGPL-3.0 (see [LICENSE](LICENSE)).
|
||||
Reference in new issue
Block a user