mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-23 01:26:42 +02:00
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>
325 lines
11 KiB
Markdown
325 lines
11 KiB
Markdown
# 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)
|
|
|
|
```bash
|
|
# 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)
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
pnpm dev # Start dev server
|
|
pnpm build # Build for production
|
|
pnpm preview # Preview production build
|
|
```
|
|
|
|
### Landing Page (apps/todo/apps/landing)
|
|
|
|
```bash
|
|
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
|
|
|
|
1. **Projects** - Organize tasks into color-coded projects
|
|
2. **Tasks** - Full CRUD with priority, due dates, and status
|
|
3. **Subtasks** - Checklist items within tasks
|
|
4. **Labels** - Tag tasks with colored labels
|
|
5. **Recurring Tasks** - Daily, weekly, monthly (RFC 5545 RRULE)
|
|
6. **Reminders** - Push and email notifications
|
|
7. **Calendar Integration** - Sync tasks with Calendar app
|
|
8. **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_id` columns use TEXT type (not UUID) because Mana Core Auth generates non-UUID user IDs.
|
|
|
|
### projects
|
|
- `id` (UUID) - Primary key
|
|
- `user_id` (TEXT) - Owner (Better Auth format)
|
|
- `name` (VARCHAR) - Project name
|
|
- `color` (VARCHAR) - Hex color
|
|
- `icon` (VARCHAR) - Icon name
|
|
- `order` (INTEGER) - Sort order
|
|
- `is_archived` (BOOLEAN) - Archive flag
|
|
- `is_default` (BOOLEAN) - Inbox project
|
|
|
|
### tasks
|
|
- `id` (UUID) - Primary key
|
|
- `project_id` (UUID) - FK to projects (nullable = Inbox)
|
|
- `user_id` (TEXT) - Owner (Better Auth format)
|
|
- `title` (VARCHAR) - Task title
|
|
- `description` (TEXT) - Description
|
|
- `due_date` (TIMESTAMP) - Due date
|
|
- `priority` (VARCHAR) - low/medium/high/urgent
|
|
- `is_completed` (BOOLEAN) - Completion flag
|
|
- `order` (INTEGER) - Sort order
|
|
- `recurrence_rule` (VARCHAR) - RFC 5545 RRULE
|
|
- `subtasks` (JSONB) - Subtask array
|
|
- `metadata` (JSONB) - Extra data
|
|
|
|
### labels
|
|
- `id` (UUID) - Primary key
|
|
- `user_id` (TEXT) - Owner (Better Auth format)
|
|
- `name` (VARCHAR) - Label name
|
|
- `color` (VARCHAR) - Hex color
|
|
|
|
### task_labels
|
|
- `task_id` (UUID) - FK to tasks
|
|
- `label_id` (UUID) - FK to labels
|
|
|
|
### reminders
|
|
- `id` (UUID) - Primary key
|
|
- `task_id` (UUID) - FK to tasks
|
|
- `user_id` (TEXT) - Owner (Better Auth format)
|
|
- `minutes_before` (INTEGER) - Offset
|
|
- `type` (VARCHAR) - push/email/both
|
|
- `status` (VARCHAR) - pending/sent/failed
|
|
|
|
## Environment Variables
|
|
|
|
### Backend (.env)
|
|
|
|
```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)
|
|
|
|
```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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
1. **Authentication**: Uses Mana Core Auth (JWT in Authorization header)
|
|
2. **Database**: PostgreSQL with Drizzle ORM (port 5432)
|
|
3. **Ports**: Backend=3018, Web=5188, Landing=4323
|
|
4. **Recurrence**: Uses RFC 5545 RRULE format
|
|
5. **Calendar**: Tasks can sync bidirectionally with Calendar app
|