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

Plugin settings are stored in:

.obsidian/plugins/obsidian-project-planner/data.json

As of v0.8.3 this file contains settings only. It has one top-level key:

  • settings — all plugin configuration values

Task data is no longer stored here.

Per-Project Task Files (new in v0.8.3)

Each project's tasks are stored in a dedicated JSON file inside the vault:

{projectsBasePath}/{Project Name}/.planner-tasks.json

The default projectsBasePath is Project Planner, so a project named "My Project" stores its tasks at:

Project Planner/My Project/.planner-tasks.json

Because these files live inside your vault (not in .obsidian/), they are Git-trackable and synced by Obsidian Sync. Each file contains a single JSON object:

{
  "version": 1,
  "projectId": "a1b2c3d4-...",
  "tasks": [ ... ]
}

Markdown Task Files

When Bidirectional Markdown Sync is enabled, each task is also stored as an individual Markdown file:

{projectsBasePath}/{Project Name}/Tasks/{TaskTitle}.md

These files mirror the task data and are kept in sync automatically.

View Preferences

Per-view display settings (column widths, sort order, visible columns, etc.) are stored inside data.json as part of settings. They sync across devices with Obsidian Sync.

Data Schema

Project Object

{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "name": "My Project",
  "storageKey": "My Project",
  "createdDate": "2026-01-15T10:00:00.000Z",
  "lastUpdatedDate": "2026-08-01T14:22:00.000Z",
  "lastSyncTimestamp": 1700000000000,
  "buckets": [
    { "id": "bucket-uuid-1", "name": "To Do", "color": "#0078d4" },
    { "id": "bucket-uuid-2", "name": "In Progress" },
    { "id": "bucket-uuid-3", "name": "Done" }
  ],
  "unassignedBucketName": "Unassigned",
  "budgetTotal": 10000,
  "defaultHourlyRate": 75,
  "currencySymbol": "$"
}
  • id (required) — UUID v4 unique identifier
  • name (required) — display name shown in the UI
  • storageKey (required, v0.8.3+) — the folder name used on disk; set at creation and never changes, so renaming a project does not orphan its files
  • createdDate — ISO 8601 timestamp of project creation
  • lastUpdatedDate — ISO 8601 timestamp of last task change
  • lastSyncTimestamp (optional) — Unix timestamp (ms) of the last Markdown sync
  • buckets — array of Board view bucket objects; each has id, name, and optional color
  • unassignedBucketName — custom label for the Unassigned bucket
  • budgetTotal — total project budget (cost tracking)
  • defaultHourlyRate — default hourly rate applied to hourly-cost tasks
  • currencySymbol — display symbol for currency (e.g. $, , £)

Task Object

{
  "id": "f8e7d6c5-b4a3-2190-fedc-ba0987654321",
  "title": "Design landing page",
  "status": "In Progress",
  "completed": false,
  "priority": "High",
  "parentId": null,
  "collapsed": false,
  "bucketId": "bucket-uuid-2",
  "startDate": "2026-02-01",
  "dueDate": "2026-02-14",
  "createdDate": "2026-01-20",
  "lastModifiedDate": "2026-02-03",
  "tags": ["tag-uuid-1"],
  "description": "Create 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", "title": "Figma file", "url": "https://figma.com/...", "type": "external" }
  ],
  "dependencies": [
    { "predecessorId": "other-task-uuid", "type": "FS" }
  ],
  "effortCompleted": 4,
  "effortRemaining": 6,
  "percentComplete": 40,
  "costEstimate": 750,
  "costActual": 300,
  "costType": "hourly",
  "hourlyRate": 75,
  "cardPreview": "none"
}

Required Fields

  • id — UUID v4 unique identifier
  • title — task name
  • status — current status label (must match a configured status name)
  • completed — boolean

Optional Fields

  • priority"Low", "Medium", "High", or "Critical"
  • parentId — UUID of the parent task; null or omitted for root-level tasks
  • collapsed — whether children are hidden in Grid view
  • bucketId — UUID of the Board view bucket
  • startDate / dueDate / createdDate / lastModifiedDate — dates in YYYY-MM-DD format
  • tags — array of tag ID strings
  • description — Markdown-formatted body text
  • subtasks — array of checklist items (id, title, completed)
  • links — array of link objects (id, title, url, type); type is "obsidian" or "external"
  • dependencies — array of objects with predecessorId (UUID) and type: "FS" (Finish-to-Start), "SS" (Start-to-Start), "FF" (Finish-to-Finish), or "SF" (Start-to-Finish)
  • effortCompleted / effortRemaining — hours of work done and remaining
  • percentComplete — 0–100; auto-calculated from effort values
  • costEstimate / costActual — numeric cost values
  • costType"fixed" or "hourly"
  • hourlyRate — per-task rate override; uses project defaultHourlyRate when omitted
  • cardPreview — what to show on Board cards: "none", "checklist", or "description"

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

Per-Project Task Files

As of v0.8.3, tasks are no longer stored inside data.json. Each project maintains its own task file at {projectsBasePath}/{storageKey}/.planner-tasks.json:

{
  "version": 1,
  "projectId": "project-uuid-1",
  "tasks": [
    { "id": "task-uuid-1", "title": "Task A", "status": "Not Started", "completed": false },
    { "id": "task-uuid-2", "title": "Task B", "status": "In Progress", "completed": false }
  ]
}

Tasks are ordered by their position in the tasks array, which reflects manual drag-and-drop ordering.

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: 2026-02-01
dueDate: 2026-02-14
tags:
  - tag-uuid-1
dependencies:
  - FS:other-task-uuid
effortCompleted: 4
effortRemaining: 6
percentComplete: 40
---

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., 2026-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": true,
    "autoCreateTaskNotes": true,
    "syncOnStartup": false,
    "enableDailyNoteSync": false,
    "dailyNoteTagPattern": "#planner",
    "dailyNoteScanFolders": [],
    "dailyNoteDefaultProject": "",
    "projectsBasePath": "Project Planner",
    "defaultView": "grid",
    "showCompleted": true,
    "openViewsInNewTab": false,
    "enableDependencyScheduling": true,
    "enableParentRollUp": true,
    "dateFormat": "iso",
    "ganttLeftColumnWidth": 300,
    "myDayDefaultView": "today"
  }
}

Data Backup

Best Practices

  1. Version control: Keep your vault in a Git repository. Task data lives in {projectsBasePath}/{Project}/.planner-tasks.json inside the vault and is fully Git-trackable. data.json holds settings only.
  2. Regular copies: Back up your vault folder periodically.
  3. Before upgrades: Note your current version before updating the plugin.
  4. Enable Markdown Sync: With sync enabled, tasks also exist as individual .md 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 .planner-tasks.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

As of v0.8.3, each project stores its tasks in a separate vault file rather than a single shared data.json. This significantly reduces the read/write surface for large vaults — only the active project's file is loaded during task operations. The limits below apply per project.

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 the plugin loads after an upgrade, it checks for legacy task data in data.json. If found, tasks are silently migrated to the new per-project vault files and removed from data.json. No manual steps are required. Back up your vault with Git or Obsidian Sync before upgrading if you want a manual snapshot.

Exporting Data

  • JSON: Copy .planner-tasks.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.

Related Documentation