Extend the natural language parser with duration recognition (30min, 2h, 1.5 Stunden), multi-task splitting on keywords (danach, dann, ;) with context inheritance (date/time/project), and a history-based time estimator that suggests durations from similar completed tasks. QuickAdd now shows a live parse preview and duration suggestion. All features run offline against IndexedDB — no AI/API calls needed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
11 KiB
Todo Project Guide
Overview
Todo is a full-featured task management application for the ManaCore ecosystem. It supports projects, tasks with subtasks, labels, recurring tasks, reminders, and calendar integration.
| App | Port | URL |
|---|---|---|
| Backend | 3018 | http://localhost:3018 |
| Web App | 5188 | http://localhost:5188 |
| Landing Page | 4323 | http://localhost:4323 |
Project Structure
apps/todo/
├── apps/
│ ├── backend/ # NestJS API server (@todo/backend)
│ ├── web/ # SvelteKit web application (@todo/web)
│ └── landing/ # Astro marketing landing page (@todo/landing)
├── packages/
│ └── shared/ # Shared types, utils, constants (@todo/shared)
├── package.json
└── CLAUDE.md
Commands
Root Level (from monorepo root)
# All apps
pnpm todo:dev # Run all todo apps
# Individual apps
pnpm dev:todo:backend # Start backend server (port 3018)
pnpm dev:todo:web # Start web app (port 5188)
pnpm dev:todo:landing # Start landing page (port 4323)
pnpm dev:todo:app # Start web + backend together
# Database
pnpm todo:db:push # Push schema to database
pnpm todo:db:studio # Open Drizzle Studio
pnpm todo:db:seed # Seed initial data
Backend (apps/todo/apps/backend)
pnpm dev # Start with hot reload
pnpm build # Build for production
pnpm start:prod # Start production server
pnpm db:push # Push schema to database
pnpm db:studio # Open Drizzle Studio
pnpm db:seed # Seed initial data
Web App (apps/todo/apps/web)
pnpm dev # Start dev server
pnpm build # Build for production
pnpm preview # Preview production build
Landing Page (apps/todo/apps/landing)
pnpm dev # Start dev server (port 4323)
pnpm build # Build for production
pnpm preview # Preview build
Technology Stack
| Layer | Technology |
|---|---|
| Backend | NestJS 10, Drizzle ORM, PostgreSQL |
| Web | SvelteKit 2.x, Svelte 5 (runes mode), Tailwind CSS 4 |
| Landing | Astro 5.x, Tailwind CSS |
| Auth | Mana Core Auth (JWT) |
| i18n | svelte-i18n (DE, EN) |
| Dates | date-fns |
Core Features
- Projects - Organize tasks into color-coded projects
- Tasks - Full CRUD with priority, due dates, and status
- Subtasks - Checklist items within tasks
- Labels - Tag tasks with colored labels
- Recurring Tasks - Daily, weekly, monthly (RFC 5545 RRULE)
- Reminders - Push and email notifications
- Calendar Integration - Sync tasks with Calendar app
- Quick Add - Natural language task creation
Views
| View | Route | Description |
|---|---|---|
| Inbox | / (default) |
Tasks without a project |
| Today | /today |
Due today + overdue |
| Upcoming | /upcoming |
Next 7 days, grouped by date |
| Project | /project/[id] |
Tasks in specific project |
| Label | /label/[id] |
Tasks with specific label |
| Completed | /completed |
Completed tasks archive |
| Search | /search |
Full-text search |
API Endpoints
Projects
| Endpoint | Method | Description |
|---|---|---|
/api/v1/projects |
GET | List user's projects |
/api/v1/projects |
POST | Create project |
/api/v1/projects/:id |
GET | Get project details |
/api/v1/projects/:id |
PUT | Update project |
/api/v1/projects/:id |
DELETE | Delete project |
/api/v1/projects/:id/archive |
POST | Archive project |
/api/v1/projects/reorder |
PUT | Reorder projects |
Tasks
| Endpoint | Method | Description |
|---|---|---|
/api/v1/tasks |
GET | Query tasks (filters) |
/api/v1/tasks |
POST | Create task |
/api/v1/tasks/:id |
GET | Get task details |
/api/v1/tasks/:id |
PUT | Update task |
/api/v1/tasks/:id |
DELETE | Delete task |
/api/v1/tasks/:id/complete |
POST | Mark complete |
/api/v1/tasks/:id/uncomplete |
POST | Mark incomplete |
/api/v1/tasks/:id/move |
POST | Move to project |
/api/v1/tasks/:id/labels |
PUT | Update labels |
/api/v1/tasks/inbox |
GET | Inbox tasks |
/api/v1/tasks/today |
GET | Today's tasks |
/api/v1/tasks/upcoming |
GET | Upcoming tasks |
/api/v1/tasks/reorder |
PUT | Reorder tasks |
Labels
| Endpoint | Method | Description |
|---|---|---|
/api/v1/labels |
GET | List labels |
/api/v1/labels |
POST | Create label |
/api/v1/labels/:id |
PUT | Update label |
/api/v1/labels/:id |
DELETE | Delete label |
Reminders
| Endpoint | Method | Description |
|---|---|---|
/api/v1/tasks/:taskId/reminders |
GET | List reminders |
/api/v1/tasks/:taskId/reminders |
POST | Add reminder |
/api/v1/reminders/:id |
DELETE | Delete reminder |
Database Schema
Note
:
user_idcolumns use TEXT type (not UUID) because Mana Core Auth generates non-UUID user IDs.
projects
id(UUID) - Primary keyuser_id(TEXT) - Owner (Better Auth format)name(VARCHAR) - Project namecolor(VARCHAR) - Hex coloricon(VARCHAR) - Icon nameorder(INTEGER) - Sort orderis_archived(BOOLEAN) - Archive flagis_default(BOOLEAN) - Inbox project
tasks
id(UUID) - Primary keyproject_id(UUID) - FK to projects (nullable = Inbox)user_id(TEXT) - Owner (Better Auth format)title(VARCHAR) - Task titledescription(TEXT) - Descriptiondue_date(TIMESTAMP) - Due datepriority(VARCHAR) - low/medium/high/urgentis_completed(BOOLEAN) - Completion flagorder(INTEGER) - Sort orderrecurrence_rule(VARCHAR) - RFC 5545 RRULEsubtasks(JSONB) - Subtask arraymetadata(JSONB) - Extra data
labels
id(UUID) - Primary keyuser_id(TEXT) - Owner (Better Auth format)name(VARCHAR) - Label namecolor(VARCHAR) - Hex color
task_labels
task_id(UUID) - FK to taskslabel_id(UUID) - FK to labels
reminders
id(UUID) - Primary keytask_id(UUID) - FK to tasksuser_id(TEXT) - Owner (Better Auth format)minutes_before(INTEGER) - Offsettype(VARCHAR) - push/email/bothstatus(VARCHAR) - pending/sent/failed
Environment Variables
Backend (.env)
NODE_ENV=development
PORT=3018
DATABASE_URL=postgresql://manacore:devpassword@localhost:5432/todo
MANA_CORE_AUTH_URL=http://localhost:3001
CORS_ORIGINS=http://localhost:5173,http://localhost:5186,http://localhost:8081
Web (.env)
PUBLIC_BACKEND_URL=http://localhost:3018
PUBLIC_MANA_CORE_AUTH_URL=http://localhost:3001
Quick Add Syntax
Natural language task creation:
"Meeting morgen um 14 Uhr !hoch @Arbeit #wichtig"
Recognized patterns:
- Date: heute, morgen, nächsten Montag, 15.12.
- Time: um 14 Uhr, 14:00
- Priority: !hoch, !niedrig, !dringend, !!!
- Project: @Projektname
- Labels: #label1 #label2
- Recurrence: jeden Tag, wöchentlich, monatlich
- Duration: 30min, 2h, 1.5 Stunden (maps to
estimatedDuration)
Multi-Task Input
Split multiple tasks with keywords (danach, dann, und dann, anschließend, außerdem) or semicolons:
"Morgen um 10 Zahnarzt 1h, danach Einkaufen"
→ Task 1: Zahnarzt (morgen 10:00, 1h)
→ Task 2: Einkaufen (morgen 11:00, auto-offset)
"Meeting 14 Uhr 1h @Arbeit; Report schreiben; Mails"
→ 3 tasks, all inherit date + project from first task
Context inheritance: subsequent tasks inherit date, time, and project from the first task. If the first task has a duration, the next task's time is offset accordingly.
Time Estimation
QuickAdd suggests a duration based on completed task history (weighted by project, labels, title similarity, priority). The suggestion appears after 500ms typing pause and can be accepted with one click. Runs fully offline against IndexedDB — no AI/API calls.
Code Style Guidelines
- TypeScript: Strict typing with interfaces
- Web: Svelte 5 runes mode (
$state,$derived,$effect) - Styling: Tailwind CSS with CSS variables
- Formatting: Prettier with project config
- i18n: All UI text in locale files
Production Readiness
Status: Production-Ready (2026-03-24)
Checklist
| Category | Status | Details |
|---|---|---|
| Error Handling | ✅ | Global +error.svelte with i18n (5 languages), error tracking via GlitchTip |
| Offline Support | ✅ | Offline page with shared OfflinePage component |
| PWA | ✅ | Service worker, manifest, icons, shortcuts (New task, Kanban, Settings) |
| Security Headers | ✅ | CSP, X-Frame-Options via setSecurityHeaders() |
| Loading States | ✅ | Skeleton loaders: TaskList, TaskItem, KanbanBoard, KanbanColumn, Statistics |
| i18n | ✅ | 5 languages (DE/EN/FR/ES/IT) via svelte-i18n |
| Meta/SEO | ✅ | OG tags, meta description in root layout |
| Accessibility | ✅ | Focus trapping in all modals, ARIA roles, keyboard shortcuts |
| Rate Limiting | ✅ | ThrottlerGuard global (100 req/min) |
| API Validation | ✅ | DTOs with class-validator, RRULE DoS protection (max 5000 occurrences) |
| Auth | ✅ | JWT via mana-core-auth, client-side redirect in onMount |
| Toast System | ✅ | Toast notifications via shared toastStore |
| Docker | ✅ | Multi-stage build (web + backend), health checks, Traefik labels |
| Tests | ✅ | Unit tests (7 backend, 3 web), E2E tests (3 suites: auth, projects, tasks) |
| Error Tracking | ✅ | GlitchTip integration (client + server) |
| Metrics | ✅ | Prometheus via MetricsModule |
| Context Menu | ✅ | Shared ContextMenu on TaskList (priority, project, complete, delete) |
| Auto-Save | ✅ | 500ms debounce, no save/cancel buttons needed |
| Drag & Drop | ✅ | Task reordering in list + kanban views |
Test Suites
# Unit tests
pnpm --filter @todo/backend test
pnpm --filter @todo/web test
# E2E tests
pnpm --filter @todo/web test:e2e
| Type | Suite | Coverage |
|---|---|---|
| Unit (Backend) | task.service.spec.ts |
Task CRUD, recurrence |
| Unit (Backend) | project.service.spec.ts |
Project management |
| Unit (Backend) | kanban.service.spec.ts |
Kanban operations |
| Unit (Backend) | reminder.service.spec.ts |
Reminders |
| Unit (Backend) | label.service.spec.ts |
Labels |
| Unit (Web) | task-parser.test.ts |
Natural language parsing |
| Unit (Web) | task-filters.test.ts |
Filter logic |
| Unit (Web) | view.test.ts |
View store state |
| E2E | auth.spec.ts |
Login, redirect |
| E2E | projects.spec.ts |
Project CRUD |
| E2E | tasks.spec.ts |
Task CRUD |
Important Notes
- Authentication: Uses Mana Core Auth (JWT in Authorization header)
- Database: PostgreSQL with Drizzle ORM (port 5432)
- Ports: Backend=3018, Web=5188, Landing=4323
- Recurrence: Uses RFC 5545 RRULE format
- Calendar: Tasks can sync bidirectionally with Calendar app