Data Structure Reference
A comprehensive reference for how Project Planner stores, organizes, and manages your project data. Understanding the data structure helps with troubleshooting, backups, advanced customization, and integration with other tools.
Storage Locations
Project Planner stores data across three distinct locations depending on the type of information.
Primary Data File
All project, task, and settings data lives in a single JSON file inside your vault:
.obsidian/plugins/obsidian-project-planner/data.json
This file contains four top-level keys:
- projects — array of project objects
- tasksByProject — object mapping project IDs to arrays of tasks
- tags — array of tag objects
- settings — plugin configuration values
Markdown Task Files
When Bidirectional Markdown Sync is enabled, each task is also stored as an individual Markdown file:
{ProjectName}/Tasks/{TaskTitle}.md
These files mirror the data in data.json and are kept in sync automatically.
View Preferences
Per-view display settings (column widths, sort order, collapsed groups, etc.) are stored in the browser's localStorage. These preferences are local to the device and are not synced between machines.
Data Schema
Project Object
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "My Project",
"buckets": [
{ "id": "bucket-uuid-1", "name": "To Do" },
{ "id": "bucket-uuid-2", "name": "In Progress" },
{ "id": "bucket-uuid-3", "name": "Done" }
],
"startDate": "2025-01-15",
"dueDate": "2025-06-30",
"lastSyncTimestamp": 1700000000000
}
- id (required) — UUID v4 unique identifier
- name (required) — display name of the project
- buckets (required) — array of bucket objects used in Board view; each has an
idandname - startDate (optional) — project start date in
YYYY-MM-DDformat - dueDate (optional) — project due date in
YYYY-MM-DDformat - lastSyncTimestamp (optional) — Unix timestamp (ms) of the last Markdown sync
Task Object
{
"id": "f8e7d6c5-b4a3-2190-fedc-ba0987654321",
"title": "Design landing page",
"status": "In Progress",
"completed": false,
"priority": "high",
"parentId": null,
"bucketId": "bucket-uuid-2",
"startDate": "2025-02-01",
"dueDate": "2025-02-14",
"tags": ["design", "frontend"],
"description": "Create the initial wireframes and high-fidelity mockups.",
"subtasks": [
{ "id": "sub-uuid-1", "title": "Wireframe", "completed": true },
{ "id": "sub-uuid-2", "title": "Hi-fi mockup", "completed": false }
],
"links": [
{ "id": "link-uuid-1", "label": "Figma file", "url": "https://figma.com/..." }
],
"dependencies": [
{ "taskId": "other-task-uuid", "type": "blockedBy" }
]
}
Required Fields
- id — UUID v4 unique identifier
- title — task name (string)
- status — current status label; must match a bucket name in the parent project
- completed — boolean indicating whether the task is done
Optional Fields
- priority —
"high","medium","low", ornull - parentId — UUID of the parent task for hierarchical nesting;
nullfor root-level tasks - bucketId — UUID of the bucket the task belongs to in Board view
- startDate / dueDate — dates in
YYYY-MM-DDformat - tags — array of tag name strings
- description — Markdown-formatted description text
- subtasks — array of subtask objects (
id,title,completed) - links — array of link objects (
id,label,url) - dependencies — array of dependency objects (
taskId,type); type is"blockedBy"or"blocking"
Tag Object
{
"id": "tag-uuid-1",
"name": "design",
"color": "#4a90d9"
}
- id — UUID v4 unique identifier
- name — tag display name
- color — hex color string used in the UI
Data Organization
tasksByProject Structure
Tasks are grouped by project ID inside the tasksByProject object:
{
"tasksByProject": {
"project-uuid-1": [
{ "id": "task-uuid-1", "title": "Task A", ... },
{ "id": "task-uuid-2", "title": "Task B", ... }
],
"project-uuid-2": [
{ "id": "task-uuid-3", "title": "Task C", ... }
]
}
}
Hierarchical Relationships
Parent-child task relationships are established through the parentId field. A task with parentId: null is a root-level task; otherwise it is nested under the referenced parent.
// Root task
{ "id": "parent-uuid", "title": "Epic: Redesign", "parentId": null }
// Child task
{ "id": "child-uuid", "title": "Update header", "parentId": "parent-uuid" }
// Grandchild task
{ "id": "grandchild-uuid", "title": "New logo", "parentId": "child-uuid" }
Markdown File Format
When Markdown Sync is enabled, each task is written as a .md file with YAML frontmatter followed by body content:
---
id: f8e7d6c5-b4a3-2190-fedc-ba0987654321
title: Design landing page
status: In Progress
completed: false
priority: high
bucketId: bucket-uuid-2
startDate: 2025-02-01
dueDate: 2025-02-14
tags:
- design
- frontend
dependencies:
- blockedBy:other-task-uuid
---
Create the initial wireframes and high-fidelity mockups.
## Subtasks
- [x] Wireframe
- [ ] Hi-fi mockup
## Links
- [Figma file](https://figma.com/...)
Date Format
- Current format:
YYYY-MM-DD(e.g.,2025-02-14) - Legacy format: Full ISO 8601 strings (e.g.,
2025-02-14T00:00:00.000Z)
Project Planner is backward-compatible and accepts both formats when reading data. New dates are always written in the short YYYY-MM-DD format.
Settings Schema
{
"settings": {
"enableMarkdownSync": false,
"autoCreateTaskNotes": false,
"syncOnStartup": false,
"enableDailyNoteSync": false,
"dailyNoteTagPattern": "#planner",
"dailyNoteScanFolders": "",
"dailyNoteDefaultProject": "",
"defaultView": "list",
"showCompletedTasks": true,
"confirmBeforeDelete": true,
"theme": "system"
}
}
Data Backup
Best Practices
- Version control: Keep your vault in a Git repository so every change to
data.jsonis tracked. - Regular copies: Periodically copy
data.jsonto a separate backup location. - Before upgrades: Always back up
data.jsonbefore updating the plugin. - Enable Markdown Sync: With sync enabled, your tasks also exist as individual Markdown files—a built-in secondary copy.
- Cloud storage: Store your vault on a cloud-synced folder (iCloud, Dropbox, OneDrive) for automatic off-site backup.
Recovery Options
- Restore
data.jsonfrom a Git commit or backup copy. - Re-import tasks from existing Markdown files using Markdown Sync.
- Manually reconstruct the JSON from exported or printed task lists.
Performance Considerations
Because all data is stored in a single JSON file, performance can degrade with very large datasets.
For best performance, keep individual projects under 500 tasks and the total across all projects under 2,000 tasks.
Optimization Tips
- Archive completed projects by exporting and removing them from the active data file.
- Minimize the number of subtasks and links per task to reduce file size.
- Use tags and buckets instead of deeply nested hierarchies.
- Periodically review and clean up orphaned tasks (tasks whose
parentIdpoints to a deleted parent).
Recommended Limits
- Tasks per project: ≤ 500
- Total tasks: ≤ 2,000
- Subtasks per task: ≤ 50
- Nesting depth: ≤ 5 levels
Data Migration
Version Upgrades
When a new plugin version changes the data schema, Project Planner automatically migrates data.json on first load. A backup of the pre-migration file is saved as data.json.bak in the same directory.
Exporting Data
- JSON: Copy
data.jsondirectly—it is valid, portable JSON. - Markdown: Enable Markdown Sync to generate individual
.mdfiles that can be used in any Markdown-compatible tool.
Technical Notes
UUID Generation
All IDs are RFC 4122 v4 UUIDs generated client-side using crypto.randomUUID() (or a polyfill on older platforms). This guarantees uniqueness without a central server.
Sync Conflict Resolution
When Markdown Sync detects a conflict between the JSON data and a Markdown file, the last write wins. A syncInProgress guard prevents recursive writes during a sync cycle. See Bidirectional Markdown Sync for details.
Data Integrity
- Plugin validates required fields on every save.
- Orphaned child tasks (invalid
parentId) are promoted to root level automatically. - Duplicate IDs are detected and regenerated on load.