mTodo is a modern, self-hostable TODO app — lists, tags, recurring tasks, Markdown, list sharing, a Telegram bot and an installable PWA. Built with Express, SQLite, React & TypeScript.
A focused feature set that scales from a personal LAN install to a locked-down public deployment.
Create, edit, complete and delete tasks, organized into TODO lists with a clean sidebar.
Share a list by email as read-only or editor. Manage members, change permissions, or leave a shared list.
Daily, weekly (pick weekdays), monthly (pick days) or fully custom every N days/weeks/months.
Autocomplete from existing tags or type a new one to create it on the fly.
Write task descriptions in a Markdown editor; they render as rich HTML.
See tasks due today plus recurring tasks that occur today, all in one focused place.
Type Buy milk #groceries tomorrow to set title, tags and due date in one go.
Link your account to review lists, add tasks and complete them from Telegram — or log in with Telegram.
English, Russian, Ukrainian and Serbian, with automatic browser language detection.
Toggle in the navbar; your preference is remembered across sessions.
Install on desktop & mobile, run in a standalone window, and work offline via a service worker.
JWT sign-up / sign-in, an admin panel to manage users, plus Helmet, CORS, rate limiting & Zod validation.
A Docker sidecar takes a consistent SQLite snapshot on deploy and daily, gzips it to a host folder, prunes old ones, and ships a one-command restore.
Run the whole stack in Docker for production, or locally with hot reload for development.
Copy the example env file and adjust secrets / admin credentials.
# requires Docker + Docker Compose
git clone https://github.com/devapro/mtodo.git
cd mtodo
cp .env.example .env
Builds the API and client, with a persistent SQLite volume.
npm run docker:up
# add -d to run in the background; npm run docker:down to stop
A backup sidecar snapshots the database on startup and every day, copying gzipped backups to ./backups. Restore any time.
# on-demand backup / list backups
npm run db:backup
npm run db:backups
# restore newest backup (stop the server during the swap)
docker compose -p mtodo -f docker/docker-compose.yml stop server
npm run db:restore
docker compose -p mtodo -f docker/docker-compose.yml start server
http://localhost:5173
API: http://localhost:4000/api
Requires Node.js 24+ (for the built-in node:sqlite module).
git clone https://github.com/devapro/mtodo.git
cd mtodo
cp .env.example .env
npm run install:all
Run each in its own terminal — both support hot reload.
# terminal 1 — API on http://localhost:4000
npm run dev:server
# terminal 2 — Vite client on http://localhost:5173
npm run dev:client
ADMIN_EMAIL / ADMIN_PASSWORD from .env
From first sign-in to tasks in your pocket, here's the typical flow.
Open the client and sign up, or log in as admin using the credentials from your .env.
Add TODO lists, then create tasks with tags, due dates, repeats and Markdown notes.
Share a list by email as read-only or editor, and manage members from the list menu.
Install the PWA on desktop or mobile, and link the Telegram bot to manage tasks on the go.