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 id and name
  • startDate (optional) — project start date in YYYY-MM-DD format
  • dueDate (optional) — project due date in YYYY-MM-DD format
  • 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", or null
  • parentId — UUID of the parent task for hierarchical nesting; null for root-level tasks
  • bucketId — UUID of the bucket the task belongs to in Board view
  • startDate / dueDate — dates in YYYY-MM-DD format
  • 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

  1. Version control: Keep your vault in a Git repository so every change to data.json is tracked.
  2. Regular copies: Periodically copy data.json to a separate backup location.
  3. Before upgrades: Always back up data.json before updating the plugin.
  4. Enable Markdown Sync: With sync enabled, your tasks also exist as individual Markdown files—a built-in secondary copy.
  5. Cloud storage: Store your vault on a cloud-synced folder (iCloud, Dropbox, OneDrive) for automatic off-site backup.

Recovery Options

  • Restore data.json from 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.

Tip

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 parentId points 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.json directly—it is valid, portable JSON.
  • Markdown: Enable Markdown Sync to generate individual .md files 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.