# tududi: a self-hosted GTD app with areas, projects and CalDAV sync

> tududi is an MIT-licensed, self-hosted task manager built around areas, projects, notes and recurring tasks, with Telegram capture, OIDC login and CalDAV sync. It ships as a Docker image on port 3002, and the trade-off is that you own the database and the upgrades.

**chrisvel/tududi** — A calm, open system for organizing life and work. Tasks, projects, notes, areas, and smart workflows - self-hosted or hosted.

- Repository: https://github.com/chrisvel/tududi
- Website: https://tududi.com/
- Stars: 3,407 · Forks: 254
- Language: JavaScript
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/chrisvel-tududi

## What tududi solves, and for whom

Most task apps assume a flat list. tududi assumes a hierarchy. The README describes tasks, projects, areas, notes and tags, where a task can belong to a project, a project can belong to an area, and both tasks and notes can carry tags. Areas are the top level: a grouping above projects, which is the part that separates tududi from a plain to-do list. If your work naturally splits into a few long-lived domains and many short-lived projects inside them, that shape is the reason to look here.

The second assumption is ownership. tududi is self-hosted by default, and the README frames the hosted subscription as the hassle-free alternative rather than the primary path. The licence is MIT, so the code is yours to run, fork or modify. The project also targets households and small teams: the README documents roles (admin, user, guest), groups that share a project, area or goal with several people, and members without an email address who sign in through a link. That last detail matters more than it looks. Adding a child or a household member who has no email is a use case most team-oriented tools never handle.

Who it is not for: anyone who wants someone else to run the sync service, or who needs a first-party iOS and Android app. The README lists an installable PWA and says the app stays readable from cache when offline while write operations are queued and synced when connectivity returns. That is a browser-based offline story, not a native client.

## The data model behind tasks, projects and areas

The structure is relational and shallow, which is a deliberate choice. Areas contain projects. Projects contain tasks and notes. Tasks and notes carry tags. Tasks can also carry subtasks, and the README describes progress tracking and navigation between them. Nothing in the documented model nests an area inside an area, so the depth is fixed at three levels. That constraint keeps queries and the UI simple, and it also means deeply nested outlines are out of scope.

Recurring tasks are the most developed part of the model, and the README is specific about it. Supported patterns include daily, weekly, monthly, monthly on specific weekdays, and monthly last day, with custom intervals such as every 2 weeks or every 3 months, and optional end dates. Two behaviours stand out. First, recurrence can be completion-based rather than due-date-based, so the next instance is scheduled from the moment you finish the current one. Second, generated instances keep a parent-child link to the original pattern, and the README says recurrence settings can be edited directly from any generated instance. That is a real design decision: editing a child normally forks a series, and tududi routes the edit back to the parent instead.

Sync is handled through CalDAV. The README describes bidirectional sync with CalDAV servers including Nextcloud and Baikal, access from tasks.org, Apple Reminders, Thunderbird and Evolution, full recurring task support with RRULE, conflict detection and resolution, background automatic synchronization, and HTTP Basic Authentication for CalDAV clients. Treat the RRULE claim as the one to test first: recurrence rules are where CalDAV implementations diverge most, and the README does not describe how conflicts are resolved when both sides change the same task.

## Installing tududi with Docker and creating the first task

The README's quick start is a single docker run against the published image. Three environment variables are required: the initial admin email, its password, and a session secret generated with openssl. Two volumes keep state across container restarts: /app/db for the SQLite database and /app/uploads for uploaded files. The container listens on port 3002.

```bash
docker pull chrisvel/tududi:latest

docker run \
  -e TUDUDI_USER_EMAIL=admin@example.com \
  -e TUDUDI_USER_PASSWORD=your-secure-password \
  -e TUDUDI_SESSION_SECRET=$(openssl rand -hex 64) \
  -v ~/tududi_db:/app/db \
  -v ~/tududi_uploads:/app/uploads \
  -p 3002:3002 \
  -d chrisvel/tududi:latest
```

After the container starts, the README says to navigate to http://localhost:3002 and log in with the credentials you passed. The admin account is created on first boot if no users exist, according to .env.example. If the login page loads but the session does not stick, the session secret is the first thing to check: it signs the session cookies.

The repository also ships a docker-compose.yml, which is the better base for anything long-lived because configuration lives in a file instead of a command line. The compose file reads its variables through env_file, so the documented first step is copying the example file.

```bash
cp .env.example .env
# edit .env with your values, then:
docker compose up -d
```

The compose file mounts ./tududi_db and ./uploads relative to the compose file and sets restart: unless-stopped, so the container comes back after a reboot. Two settings in .env.example deserve attention before you expose the app. TUDUDI_ALLOWED_ORIGINS controls which origins may call the API and defaults to http://localhost:3002, so a different hostname needs to be added. TUDUDI_TRUST_PROXY is required when running behind Nginx, Caddy or Traefik so that Express reads client IPs from X-Forwarded-For correctly; the documented values are false, true or 1, loopback, or a specific subnet such as 172.16.0.0/12. Getting this wrong affects rate limiting and logging rather than the UI, which makes it easy to miss.

## Telegram capture, OIDC login and the API

Three integrations change how tududi fits into a day. Telegram is the capture channel: the README says you can create tasks directly through Telegram messages, receive daily digests, and capture ideas quickly. This is the answer to the usual failure mode of self-hosted task managers, where adding a task takes long enough that you stop doing it. Capture from a chat client is faster than opening a web app, and the digest pushes the day's list to you rather than waiting for you to look.

OIDC is the second. The README lists Google, Okta, Keycloak, Authentik, PocketID and Azure AD, with Just-In-Time user provisioning, account linking for hybrid authentication, .env-based configuration, and automatic admin role assignment based on email domains. For a small team already running an identity provider, that removes a separate password store. It also means the login path depends on your provider being reachable, so an OIDC-only setup is a single point of failure for getting into your own tasks. Keep the local admin account as a fallback.

The third is the API. The README documents versioned Swagger docs at /api/v1 plus personal API keys for integrating tududi with your own tooling. Versioning the path is a small but real signal: it gives the maintainer room to change endpoints without breaking existing scripts. Note that the personal API keys are separate from CalDAV's HTTP Basic Authentication, so a CalDAV client and a script do not share credentials.

## Where tududi gets in the way

The storage engine is the first constraint. The Dockerfile installs sqlite and the compose file mounts a single database directory. SQLite is a reasonable fit for one household or a small team, and it is the wrong fit for concurrent write-heavy multi-team use. The README does not document a supported path to PostgreSQL or MySQL, and .sequelizerc in the repository root shows Sequelize is the ORM, so a migration would be possible in principle but is not a documented feature. If your team is large enough that concurrent writes matter, this is the wrong tool.

Upgrades are the second. The release list includes v1.6.0-rc.1, v1.5.1-dev.1 and v1.5.0, and the package.json version field carries the rc tag. Release candidates and development tags are published alongside stable ones, so pulling chrisvel/tududi:latest is not the same as pinning a stable version. The README does not document rollback or a downgrade procedure, and the database lives in a volume you mount. Back up that volume before every upgrade, and pin a tag rather than tracking latest if you care about stability.

The third is mobile. The PWA is installable on Android, iOS and desktop browsers, and the README describes cached reads plus queued writes when offline. That is not the same as a native app, and the README does not promise one. If your workflow depends on widgets, share-sheet capture or background sync that survives the OS killing the browser tab, the PWA may not hold up. Test it on your own device before migrating a real task list into it.

## How tududi differs from Vikunja and Nextcloud Tasks

The closest self-hosted alternative in shape is Vikunja, and the difference is the organising model. Vikunja is built around projects, labels and kanban-style views with a broad set of list and board presentations. tududi puts areas above projects and keeps the depth fixed at three levels, which is a GTD framing rather than a board framing. If you think in boards and swimlanes, Vikunja's model maps more directly. If you think in domains, projects and next actions, tududi's does.

Nextcloud Tasks is the other comparison, and there the difference is architectural. Nextcloud Tasks is a CalDAV client inside a larger file-and-collaboration suite, so your tasks live in the same account as your files and calendar. tududi is a standalone application that speaks CalDAV outward to a server such as Nextcloud or Baikal. If you already run Nextcloud, adding Tasks is nearly free and gives you one account for everything. If you do not, standing up Nextcloud to get a task list is a large amount of infrastructure for the job, and tududi's own SQLite database plus optional CalDAV sync is the smaller footprint.

The practical consequence is that tududi can coexist with either. Point its CalDAV sync at your Nextcloud server and your tasks appear in tasks.org, Apple Reminders, Thunderbird or Evolution while tududi remains the primary interface. That is a genuinely useful position, and it is also the configuration most likely to surface RRULE edge cases.

## Licence, maintenance and what an upgrade costs

tududi is MIT licensed. In practice that means you can run it commercially, modify it, and redistribute it, provided the copyright notice and permission notice are preserved. It does not grant trademark rights, and it comes with no warranty. This is not legal advice; read the LICENSE file in the repository if the distinction matters to your organisation.

The repository is not archived and the last push was on 2026-09-23, the same day as the v1.6.0-rc.1 release two days after v1.5.0. That cadence cuts both ways. Fixes arrive quickly. So do changes, and the presence of -rc and -dev tags in the release list means the newest published artifacts are not all stable. The README links a GitHub Project for the roadmap, which is where planned features and progress are tracked, and the repository carries a CHANGELOG.md at the root. Read the changelog between versions rather than assuming a patch bump is cosmetic.

The real upgrade cost is operational, not financial. You maintain the container, the reverse proxy, the session secret, the volume backups and the CalDAV credentials. The README points to a docs/ directory with numbered files, including 19-people-and-roles.md for the roles and groups model, so the deeper configuration answers live there rather than in the README. Budget an hour for the first deployment and a short check after each upgrade: log in, open a recurring task, confirm CalDAV still syncs.

## Conclusion

Adopt tududi if you want a GTD-shaped task manager you host yourself and you are willing to run a SQLite-backed container with a session secret and a reverse proxy. Skip it if you need a managed sync service with a native mobile app, or if you cannot absorb breaking changes between releases. Before you commit, verify three things: that your chosen CalDAV server round-trips recurring tasks, that TUDUDI_TRUST_PROXY is set correctly behind your proxy, and that you have a tested restore of the ./tududi_db volume.

## FAQ

### What is a good self-hosted task manager?

tududi is one candidate: an MIT-licensed, self-hosted task manager built around tasks, projects, areas, notes and tags, with recurring tasks, Telegram capture, OIDC login and CalDAV sync. It ships as the chrisvel/tududi Docker image and listens on port 3002.

### Is the tududi app free?

The code is MIT licensed and self-hosting is the default path, so running it costs only your own infrastructure. The README also offers a hosted subscription as a managed alternative and lists donation and sponsorship options.

### What is the best app for organizing tasks?

There is no single answer, but tududi's model is areas containing projects, with tasks and notes inside projects and tags on both. The README also documents subtasks, recurring tasks and filters such as Today, Upcoming and Someday.

### How does tududi compare with other task apps?

The README does not name competitors. It does document the features that distinguish tududi: areas above projects, completion-based recurring tasks, CalDAV sync with RRULE support, Telegram capture, and OIDC providers such as Google, Okta, Keycloak and Azure AD.

## Sources

- [chrisvel/tududi on GitHub](https://github.com/chrisvel/tududi)
- [License: MIT](https://github.com/chrisvel/tududi/blob/main/LICENSE)
- [Project website](https://tududi.com/)
- [README](https://github.com/chrisvel/tududi/blob/main/README.md)
- [Releases](https://github.com/chrisvel/tududi/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/chrisvel-tududi
