verdande

verdande

Self-hosted tasks, notes and projects, shared with the people you share the work with. One binary, SQLite inside it.

Built to be deployed as a Rune in Yggdrasil Panel — upload the manifest, fill in two fields, press start. It also runs anywhere Docker does.

Add a task
file the VAT return next friday at 10am p1 #Accounts @tax
→ file the VAT return Fri 10:00 P1 Accounts tax

The same line works in Danish — betal moms på fredag kl 10 p1 #Firma @regnskab — and the two can be mixed mid-sentence.

What it looks like

The Today view: a sidebar of projects, filters and labels beside a list of tasks due today, each with its priority ring, time and labels.
Today. Dark is the default; there is a light theme too.
The Today view in the light theme: a sidebar of projects, filters and labels beside a list of tasks due today.
Today. Dark is the default; there is a light theme too.
A project in board view: one column per section, with task cards showing due dates, labels and repetition.
Board view — one column per section.
Notes: a list of notes on the left, one open on the right with headings, bullet lists, a quotation and a shell command in a code block.
Notes. Rich text on top, Markdown underneath.
Upcoming as a single week: seven columns of days, each holding the tasks due that day.
A week at a time — so a task can be dragged across a month boundary.
A task open in the detail drawer, with its description, priority, due date, labels, sub-tasks and an attached file.
A task, opened.
The settings page showing five themes as swatches and, below them, four looks written in the typeface each one selects.
Five themes and four looks: how bright, and how it reads.
The instance-wide history page: who did what, in which project, filtered by person and event.
What has been done on the server, across every project.
Waiting on others: tasks that have been handed to somebody else, grouped under the person who has them.
Waiting on others — grouped by who has it.
A note with the source view open: the same note as Markdown, with headings, a list, a quotation, a wiki link and a fenced code block.
The same note as Markdown. What is on disk is what you see.
The integrations settings page: connecting Gmail with an OAuth client, and below it the calendar feed address.
Integrations: your mailbox, your calendar feed, your address.

What it does

Doing the work

Reads what you type

Dates, times, priorities, projects, labels and repetition, parsed out of one line — in Danish and English, mixed freely.

Nothing to remember

Start typing anywhere and you are writing a task, with the letter you pressed already in the field. ⌘K goes anywhere else.

Search that reads Danish

Type gron and find grøn. Unicode does not consider ø an accented o, so a search that leans on that alone is broken for the people this was built for.

Repeats, and says so in words

Recurring tasks are RRULE underneath and "every other Tuesday" on the screen. Reminders are absolute or relative, and go out to the devices you have allowed them on.

Notes, beside the work

Rich text to write in, Markdown on disk — and a source view to see it. Images are pasted or dragged in. #project and [[another note]] are links, and a task shows what has been written about it. Archive what is done with it; the bin is for mistakes.

Waiting on others

What you have handed to somebody else, on its own page, grouped under the person who has it. The thing a shared list stops being able to tell you the moment it is shared.

Connected to what you already use

Shared, properly

Owner, editor and viewer roles. People outside your instance join by invite link. Changes appear live.

A real CalDAV server

Two-way. Tick something off in Apple Reminders and it is ticked off here. Not a read-only feed pretending.

A calendar of its own

A month or a week of what is due, and a secret ICS address to subscribe to from Apple Calendar, Google or Thunderbird. A Google calendar can be laid over the top, read-only.

The Google half is written to Google's documentation and has not yet been run against Google. The feed and CalDAV have.

Your mail, as an inbox

Star a mail in Gmail, or flag one over IMAP in iCloud or Fastmail, and it becomes a task. Forward one to your own address instead and the subject is parsed like anything else you type. One way: unstarring it later does nothing to the task you made.

Claude, connected

A built-in MCP server. Ask what is due this week, or have a task added, in conversation.

AI only if you ask for it

Off by default, your own key, and your choice of Anthropic, OpenAI, Google or something local. Nothing leaves the server until you have filled that in, and everything works without it.

Yours, and checkable

More than one way in

Passkeys, or a password hashed with Argon2id and a second factor with recovery codes. Every device you are signed in on is listed, and any of them can be signed out from here.

Keys stay behind

Mail tokens, mailbox passwords, second-factor secrets and AI keys are encrypted in the database, and the key lives in a file beside it — not inside it. So a backup you download, or one that ends up somewhere it should not, does not open your mail.

Nobody signs themselves up

The first account is the administrator, and after that people arrive by invitation. An address on the internet is not an open door.

Who did what

Every change is written down — who moved it, who closed it, who let somebody in. Delete the account and the trail stays: it is the instance's record, not the person's.

Yours to leave

Import from Todoist, export back to it, take everything as JSON, or hand the notes a zip of Markdown and get the same zip back out. The round trip is tested, not promised.

It counts itself, out loud

Once a day an instance says it exists — a random id, the version, and nothing else. No tasks, no names, no addresses. It is on to begin with, the settings page prints the exact payload, and one switch stops it.

Lately

A landing page can say a project is alive; a list of what landed says it better. This is not a changelog — every release has notes, and they are on the releases page.

Running it

As a Rune in Yggdrasil Panel

This is what it was built for. Runes → Carve a rune, upload rune/verdande.yaml, create a server from it, set the public address and your mail server, and start it. No port forwarding — give it a subdomain and the panel routes it through your Cloudflare Tunnel.

Or with Docker, anywhere

Open the address afterwards and create the first account. That one is the administrator.

docker run -d --name verdande \
  -p 8080:8080 \
  -v verdande-data:/data \
  -e VERDANDE_BASE_URL=https://todo.example.dk \
  gitea.nolimit.dk/kw/verdande:latest

What it will not do

At your own risk

verdande is MIT licensed and provided as is, without warranty of any kind. That sentence is in every MIT licence and it is usually skipped, so here it is in the open: if you run this, you run it at your own risk, and nobody is on the hook if it loses your work.

It is one person's project, at version 0.x, and 0.x means the shape can still change. You host it, so the data and the backups are yours. It writes a backup every night and keeps fourteen — and a backup nobody has ever restored is not yet a backup. Restore one before you need to.

Security is worked on rather than claimed. There have been two full reviews of the code, every finding is written down and closed, and what is protected and what is not is spelled out in SECURITY.md — including the parts that are a deliberate trade-off. Nobody outside the project has audited it. The last review found two ways to reach something you should not and closed both; a third review will find more, which is the point of having one.

It is built to sit behind something — a tunnel, a reverse proxy, a VPN — put there by somebody who knows what they exposed. Found a hole? Mail it rather than opening an issue; the address is in SECURITY.md and you get an answer within a week.