Commit Graph
5 Commits
Author SHA1 Message Date
nvrl a42f9074a2 links: a rename or a move no longer breaks them
A document links to another by its path, `[the plan](/n/work/plan)`, or
now by its title, `[[Plan]]` or `[[Plan|the plan]]`. What each document
links to is kept in a new `links` table, rebuilt whenever its text is
written: from the browser, over the mount, or by an import. A title is
looked for in the linking document's space first, then in every other.

Renaming or moving a document, or a folder above it, rewrites the links
to it in every document that has one, in the same transaction: the path
to the new one, a title to the new name, with the label left as it was.
Each rewritten document keeps a revision of what it said before. A link
to something in the trash keeps its row, so it follows the thing when it
is restored somewhere else. A document created, or renamed, under a title
that a link was waiting for is found by that link from then on.

The reader draws `[[titles]]` as links, and a title no document has yet
as a dimmed one that offers to write that document. `gf` follows either
from the editor, and `[[` there completes titles from the search. `gb`
and `:backlinks` list the documents that link to the open one, with the
line each does it on; the line under the title counts them. A share page
shows these links as plain text, as it does every /n/ link.

The documents written before this are indexed once, when the server
starts and finds the table empty.
2026-10-20 20:20:40 +02:00
nvrl fc593e6452 markdown: math set by KaTeX, fetched only when a page has some
$x^2$ inline, $$…$$ for display, and a ```math block, the way GitHub
writes them, in documents, shared pages and .md files alike. KaTeX loads
on first use; until then the math shows as its source. Only the woff2
fonts are bundled.
2026-10-20 10:25:26 +02:00
nvrl 8a37ca5dfe redesign 2026-10-17 13:44:05 +02:00
nvrl 49b2056215 feat: spaces, folder import, boards and mail; rename to narl-workspace
The diary grows into a workspace: a flat list of dated entries becomes a
tree of spaces, and the app is renamed to match what it now is.

Spaces and nodes
  One recursive `nodes` table replaces `entries`: a space is a root node,
  and folders and documents nest under it without limit. Entries keep
  their ids through the migration, so share tokens, media links and the
  drafts in localStorage all still resolve.

Folder import
  A folder or a zip is uploaded as a document tree. Markdown becomes
  documents titled from their first heading, everything else becomes
  media, and relative links between the imported files are rewritten to
  the paths they landed at, so a set of cross-linked notes stays
  navigable after the upload.

Boards
  A kanban board per space, with the space as the board: lists, cards,
  due dates and an optional link to a document. `diary` has none.

Mail
  SMTP notifications through an outbox. A mail is enqueued under a key
  naming the occurrence it belongs to, so a restart cannot resend and a
  relay that refuses is retried with a widening backoff. Four kinds: the
  diary reminder, cards due and overdue, a weekly digest, and logins
  from a browser that has not been seen before or a burst of failures.
  All of it is dormant until WORKSPACE_SMTP_URL is set.

Rename
  Everything user-visible says workspace; everything that already exists
  outside this repo keeps its name, because renaming it would break a
  running deployment for tidiness alone: the database file, the docker
  volume, the session cookie, the Proton device, the keyring entry and
  the localStorage keys. Configuration reads WORKSPACE_* first and falls
  back to DIARY_*, so the deployed .env keeps working untouched.
2026-09-18 14:53:22 +02:00
nvrl 4002a35305 Terminal-themed markdown diary
Single-user diary served as one Rust binary with the Svelte frontend
embedded.

- axum 0.8 + SQLite (sqlx), migrations run at startup
- stateless HMAC session cookie; credentials from .env, compared in
  constant time
- FTS5 full-text search, user input rewritten into quoted prefix terms
- media uploads linked to entries by scanning bodies for /api/media/<id>,
  which scopes share-token media access and entry deletion
- unguessable share links (192-bit token) serving a public read-only page
- vim keybindings via CodeMirror plus a modal browse layer and : command
  line; disabled on touch devices
2026-09-05 05:39:25 +02:00