Database Schema
Mindwtr keeps the local data model intentionally small and sync-friendly. The desktop app uses SQLite as the primary store, and mobile uses the same core schema where SQLite is available.
The source of truth for the SQLite schema lives in:
packages/core/src/sqlite-schema.tspackages/core/src/sqlite-adapter.ts
This page is a practical map of that schema for contributors.
Core Tables
tasks
Primary task records, including GTD status, scheduling fields, checklist data, attachments, ordering, and sync metadata.
Notable columns:
status: GTD lane (inbox,next,waiting,someday,reference,done,archived)projectId,sectionId,areaId: parent relationshipsdueDate,startTime,reviewAt,completedAt: time-based workflow fieldslocation: physical/location context for search, calendar-created tasks, and pushed calendar eventschecklist,attachments,tags,contexts,recurrence: JSON-backed fieldsshowFutureRecurrence: boolean flag stored as an integer; enables one planning-only next-occurrence preview in CalendardeletedAt,purgedAt: tombstone fields used by syncrev,revBy,updatedAt: merge/conflict metadata
projects
Project containers and their planning metadata.
Notable columns:
status:active,someday,waiting,archivedareaId: optional parent areaorderNum: project ordering within an areatagIds,attachments: JSON-backed fieldssupportNotes,reviewAt: planning/review fieldsdeletedAt,rev,revBy,updatedAt: sync metadata
sections
Project-local grouping lanes for tasks.
Notable columns:
projectId: owning projectorderNum: section ordering inside the projectisCollapsed: persisted UI statedeletedAt,rev,revBy,updatedAt: sync metadata
areas
Higher-level GTD areas of focus.
Notable columns:
name,color,iconorderNum: manual orderingdeletedAt,rev,revBy,updatedAt: sync metadata
people
Managed assignees for delegated/person-centered work.
Notable columns:
name: display name used by task assignee suggestions andassigned:searchnote,referenceLink: optional person notes and reference URLdeletedAt,rev,revBy,updatedAt: sync metadata
settings
Single-row JSON store for app settings.
id = 1data: serialized settings object
saved_filters
Saved Focus filter definitions used by the Focus view.
Notable columns:
name,icon,view: display metadatacriteria: serialized filter criteriasortBy,sortOrder: optional saved orderingcreatedAt,updatedAt: local metadata
calendar_sync
Device-calendar push-sync mapping table.
Notable columns:
task_id: Mindwtr task IDcalendar_event_id,calendar_id: native calendar identifiersplatform: platform namespace for the mappinglast_synced_at: last successful push timestamp
schema_migrations
Tracks applied schema versions for additive migrations.
Full-Text Search Tables
SQLite FTS5 powers desktop/mobile local search.
tasks_fts
Indexed task search fields:
titledescriptiontagscontextslocation
projects_fts
Indexed project search fields:
titlesupportNotestagIdsareaTitle
FTS tables are maintained by triggers in packages/core/src/sqlite-schema.ts.
Indexes
The schema includes targeted indexes for the common UI and sync paths:
- task status and deletion filters
- task date queries (
dueDate,startTime,reviewAt,completedAt) - task grouping queries (
projectId,areaId,sectionId) - project status and area ordering queries
The current index definitions live in SQLITE_INDEX_SCHEMA inside packages/core/src/sqlite-schema.ts.
Validation Rules
SQLite triggers reject invalid enum values and malformed JSON on write.
Current validation checks include:
- valid task/project status values
- JSON validity for task tags, contexts, checklist, attachments, recurrence
- JSON validity for project tag IDs and attachments
This keeps the on-disk database aligned with the TypeScript model and prevents partial corruption from bypassing the store layer.
Sync Semantics
Mindwtr does not rely on cascading relational deletes for core entities. The data model uses soft-delete tombstones so deletions can sync safely across devices.
See also:
- Architecture
- Data and Sync
- Sync Algorithm
docs/adr/0001-sqlite-constraints.md
Contributor Notes
- Prefer additive schema changes over destructive rewrites.
- When adding a field, update both the schema and the adapter mapping logic.
- If a new field affects search, update FTS tables/triggers deliberately.
- When changing constraints or delete behavior, check sync/tombstone implications first.