Parent-Child Tasks: Master Project Hierarchies and Subtask Management
Real projects aren't flat lists—they're hierarchies. "Launch website" breaks down into design, development, content, and testing. Each of those splits further: homepage design, about page design, blog template. And deeper still: wireframes, mockups, final designs.
Flat task lists force you to fake hierarchy with indentation, prefixes, or tags:
- "Launch Website - Design"
- "Launch Website - Design - Homepage"
- "Launch Website - Design - About Page"
This is tedious, error-prone, and doesn't capture relationships. When the parent project is cancelled, you manually find and close every child task. When a child task activates, the parent's status doesn't reflect that work has started.
Parent-child task systems make hierarchy explicit:
- Tasks have formal parent-child relationships
- Visual tree structure shows dependencies
- State changes cascade logically (close parent → close active children)
- Project rollup becomes possible (total time spent = sum of child task times)
To-Track's parent-child system goes beyond basic subtasks with:
- Automatic cascading state changes (close parent → close children, activate child → activate parent)
- Circular reference prevention (can't set a child as parent of its ancestor)
- Hierarchy visualization (task history timeline shows parent-child relationships)
- Flexible depth (unlimited nesting levels)
This guide explains how to organize complex projects with parent-child tasks and leverage cascading logic for automatic workflow management.
Core Concepts
Parent Tasks
Top-level tasks representing projects, epics, or collections of work.
Examples:
- "Website Redesign"
- "Q1 Marketing Campaign"
- "Thesis Research"
- "Home Renovation"
Properties:
- Can have multiple child tasks
- Can also be a child of another task (nested hierarchy)
- Closing a parent cascades to active children
Child Tasks
Subtasks that belong to a parent.
Examples (for parent "Website Redesign"):
- "Design homepage mockup"
- "Implement contact form"
- "Write about page copy"
- "Set up hosting"
Properties:
- Have exactly one parent (or none)
- Activating a child activates parent (if parent isn't already active)
- Closing all children doesn't automatically close parent (manual decision)
State Cascading Rules
To-Track implements intelligent cascading to keep hierarchy consistent:
Rule 1: Close Parent → Close Active Children
- When parent moves to CLOSED state (DONE, CANCELLED, ARCHIVED)
- Active children (IN-PROGRESS, REVIEW, BLOCKED, etc.) also close
- Open children (TODO, BACKLOG) remain unchanged
Why: Closing a project should close in-progress work, but preserve unstarted tasks (maybe they'll be useful later).
Rule 2: Activate Child → Activate Parent
- When child moves to ACTIVE state (IN-PROGRESS, etc.)
- If parent is OPEN, it also moves to ACTIVE
- If parent already ACTIVE, no change
Why: Starting work on a subtask means the project is now in progress.
Rule 3: Deactivate Parent → Deactivate Active Children
- When parent moves from ACTIVE to OPEN (e.g., IN-PROGRESS → TODO)
- Active children also move to an OPEN state
- Open children remain unchanged
- Closed children remain closed
Why: Pausing a project should pause in-progress subtasks.
Rule 4: Target State Unavailable → First Available State
- If cascading tries to move a task to a state it can't enter (due to tag requirements)
- Task moves to the first available state in the target category instead
Example: Parent closes to CANCELLED, but child doesn't have required tags for CANCELLED state → child moves to DONE (first available CLOSED state).
Creating Parent-Child Relationships
Method 1: Assign Parent When Creating Child
- Create new task (tap + button)
- Fill in task details (name, tags, dates, etc.)
- Scroll to "Parent Task" section
- Tap "Select Parent Task"
- Modal opens showing available parent tasks
- Search or browse to find parent
- Tap parent to select
- Save task
Result: Task is created with parent relationship.
Visual indicator: Task detail page shows parent task name under "Parent Task" section.
Method 2: Add Children to Existing Parent
- Open parent task (tap to view detail page)
- Scroll to "Child Tasks" section
- Tap "Add Child Tasks" (if no children) or "Manage Child Tasks"
- Modal shows:
- Selected child tasks (currently assigned) at top
- Available tasks (orphaned tasks you can add) at bottom
- Tap an available task to add as child
- Tap a selected task to unassign (remove relationship)
- Changes save automatically when closing modal
Result: Child tasks appear in "Child Tasks" section of parent.
Method 3: Create New Child from Parent Context
- Open parent task
- Scroll to "Child Tasks" section
- Tap "Manage Child Tasks"
- In the modal, tap "Create New Child" button
- New task popup opens with parent pre-filled:
- Parent task: Set to current parent automatically
- Tags: Inherited from parent (editable)
- Start/End times: Inherited from parent (editable)
- Repeat rule: Inherited from parent (editable)
- Modify details as needed
- Save to create child task
Result: New task created with parent relationship and inherited attributes.
Why inheritance: Child tasks often share parent's tags, timeline, and recurrence—pre-filling saves time.
Hierarchy Visualization
To-Track displays parent-child relationships in multiple places:
Task Detail Page
Parent Task Section:
- Shows parent task name (if assigned)
- Tap to navigate to parent's detail page
Child Tasks Section:
- Lists all child tasks using
SelectableTodoItemdesign - Shows task name, state, and state color
- Tap task to navigate to child's detail page (tap navigation currently disabled)
- Displays state colors for visual status at a glance
Task History Timeline
- Shows when child tasks were added
- Displays when parent-child relationships changed
- Visual indicator (icon + description) for hierarchy events
List View (Future Enhancement)
Currently, list view shows flat task list. Future updates may add:
- Indented child tasks under parents
- Collapsible/expandable project hierarchies
- Visual tree structure
Use Cases & Examples
Use Case 1: Software Project
Parent: "Build Mobile App"
Children:
- "Design UI mockups" (state: IN-PROGRESS)
- "Set up backend API" (state: TODO)
- "Implement user authentication" (state: BLOCKED)
- "Write unit tests" (state: TODO)
- "Submit to App Store" (state: TODO)
Scenario: Project gets cancelled (client pulls budget).
Action: Mark parent as CANCELLED.
Cascading result:
- "Design UI mockups" → CANCELLED (was ACTIVE)
- "Set up backend API" → remains TODO (was OPEN)
- "Implement user authentication" → CANCELLED (was ACTIVE)
- "Write unit tests" → remains TODO (was OPEN)
- "Submit to App Store" → remains TODO (was OPEN)
Benefit: One action closes in-progress work, preserving unstarted tasks for potential future use.
Use Case 2: Content Creation
Parent: "Write Blog Post Series on AI"
Children:
- "Research AI task generation" (state: DONE)
- "Draft post 1: Introduction" (state: IN-REVIEW)
- "Draft post 2: Use cases" (state: TODO)
- "Draft post 3: Implementation" (state: TODO)
- "Create social media graphics" (state: TODO)
Scenario: You start drafting post 2.
Action: Move "Draft post 2: Use cases" to IN-PROGRESS.
Cascading result:
- Parent "Write Blog Post Series on AI" → IN-PROGRESS (was TODO, now activated by child)
Benefit: Parent automatically reflects that work is ongoing.
Use Case 3: Event Planning
Parent: "Plan Company Retreat"
Nested hierarchy:
- Parent: "Plan Company Retreat"
- Child: "Book Venue" (state: DONE)
- Child: "Organize Activities"
- Grandchild: "Research team building activities" (state: IN-PROGRESS)
- Grandchild: "Book hiking guide" (state: TODO)
- Grandchild: "Reserve kayaks" (state: TODO)
- Child: "Arrange Catering" (state: IN-PROGRESS)
- Child: "Send Invitations" (state: TODO)
Scenario: Client decides to pause retreat planning indefinitely.
Action: Mark parent "Plan Company Retreat" as TODO (move from IN-PROGRESS to OPEN).
Cascading result:
- "Organize Activities" → TODO (was ACTIVE, deactivated)
- "Research team building activities" → TODO (grandchild also deactivated)
- "Book hiking guide" → TODO (already OPEN, no change)
- "Reserve kayaks" → TODO (already OPEN, no change)
- "Arrange Catering" → TODO (was ACTIVE, deactivated)
- "Send Invitations" → TODO (already OPEN, no change)
Benefit: Entire project hierarchy pauses with one action.
Use Case 4: Personal Goal with Subtasks
Parent: "Learn Spanish (A2 Level)"
Children:
- "Complete Duolingo lessons" (state: IN-PROGRESS, recurring: any-time)
- "Watch Spanish TV shows 3x/week" (state: IN-PROGRESS, recurring: scheduled)
- "Read Spanish news articles" (state: TODO, recurring: any-time)
- "Practice with language partner" (state: BLOCKED, note: "Need to find partner")
- "Take A2 certification exam" (state: TODO, end date: June 30)
Scenario: You achieve A2 certification early (May 15).
Action: Mark parent "Learn Spanish (A2 Level)" as DONE.
Cascading result:
- "Complete Duolingo lessons" → DONE (was ACTIVE)
- "Watch Spanish TV shows 3x/week" → DONE (was ACTIVE)
- "Read Spanish news articles" → remains TODO (was OPEN)
- "Practice with language partner" → DONE (was ACTIVE, even though BLOCKED)
- "Take A2 certification exam" → remains TODO (was OPEN, you completed early without the exam)
Benefit: Closes active work, preserves unstarted tasks in case you continue learning.
Advanced Features
Circular Reference Prevention
To-Track prevents creating loops where A is parent of B, and B is parent of A.
How it works:
- When selecting a parent for task X, the system excludes:
- Task X itself (can't be your own parent)
- All descendants of task X (children, grandchildren, etc.)
Example:
Task A (parent)
├─ Task B (child of A)
└─ Task C (child of B, grandchild of A)
If you try to set Task C as parent of Task A, the system rejects it (would create a loop).
Implementation:
getRootAncestorId(taskId): Traverses hierarchy upward to find root- Infinite loop protection: Stops after 100 iterations (should never happen)
Orphaned Task Queries
Orphaned tasks: Tasks with no parent_id and no children.
Use case: When selecting available parents, exclude tasks that are descendants of the child (prevents loops).
Query: getOrphanedTodos({excludeId: childTaskId})
- Returns tasks with
parent_id IS NULL - Excludes root ancestors of the excluded task
Root Ancestor Calculation
Root ancestor: The top-most task in a hierarchy.
Algorithm:
1. Start with task ID
2. Query for parent_id
3. If parent exists, repeat from step 2 with parent's ID
4. If no parent, current task is root
5. Return root ID
Use: Prevents assigning a descendant as parent (check if candidate parent's root is the child task itself).
Best Practices
1. Keep Hierarchies 2-3 Levels Deep
Optimal:
Project (parent)
├─ Phase 1 (child)
├─ Task 1.1 (grandchild)
└─ Task 1.2 (grandchild)
└─ Phase 2 (child)
├─ Task 2.1 (grandchild)
└─ Task 2.2 (grandchild)
Too deep (hard to navigate):
Project
└─ Phase
└─ Sub-phase
└─ Work package
└─ Activity
└─ Task
└─ Subtask (7 levels!)
Guideline: 3 levels = sweet spot for most projects.
2. Use Tags for Cross-Cutting Concerns
Don't use parent-child for categorization—use tags:
Wrong (parent-child for categorization):
Work (parent)
├─ Task A
└─ Task B
Personal (parent)
├─ Task C
└─ Task D
Right (tags for categorization):
Website Project (parent)
├─ Design homepage (tag: work, design)
└─ Write copy (tag: work, content)
Home Renovation (parent)
├─ Paint living room (tag: personal, diy)
└─ Install shelves (tag: personal, diy)
Why: Tasks belong to projects (parent-child), but have attributes (tags).
3. Set Parent When Creating Child
If you know a task is a subtask, assign the parent immediately:
- Avoids orphaned tasks
- Ensures cascading logic applies from the start
- Inherits parent attributes (tags, dates, repeat rules)
4. Review Child Tasks Before Closing Parents
Before marking a parent DONE or CANCELLED, review child tasks:
- Check for valuable open children (preserve them?)
- Ensure active children should close
- Manually close children you don't want cascaded (to control which state they end in)
Why: Cascading is automatic—once you close the parent, active children close too. Make sure that's what you want.
5. Use Parent-Child for Sequential Dependencies
When task B can't start until task A finishes:
Option 1: Make B a child of A (if A is a project) Option 2: Use BLOCKED state + note ("Waiting for task A")
Guideline: Parent-child works best for "belongs to" relationships, not just "depends on" relationships.
Comparing Parent-Child Systems
| Feature | To-Track | Todoist | Things 3 | Notion |
|---|---|---|---|---|
| Parent-child support | ✅ Formal relationships | ⚠️ Projects/sections | ⚠️ Headings (visual only) | ✅ Relational databases |
| Unlimited nesting | ✅ Yes | ⚠️ Projects → sections → tasks (3 levels) | ⚠️ Projects → headings → tasks (3 levels) | ✅ Yes |
| Cascading state changes | ✅ Automatic | ❌ No | ❌ No | ⚠️ Manual formulas |
| Activate child → activate parent | ✅ Yes | ❌ No | ❌ No | ⚠️ Manual |
| Close parent → close children | ✅ Configurable (active only) | ❌ Manual | ❌ Manual | ⚠️ Manual |
| Circular reference prevention | ✅ Built-in | N/A (no formal parent-child) | N/A | ⚠️ Manual checks |
| Visual hierarchy | ⚠️ Detail page only | ✅ List view | ✅ List view | ✅ Database views |
| Inherit parent attributes | ✅ Tags, dates, repeat rules | ❌ No | ❌ No | ⚠️ Formulas |
Verdict: To-Track's cascading logic is unique and powerful, though visual hierarchy in list view lags competitors (future enhancement planned).
Limitations & Considerations
Current Limitations
No list view hierarchy: Child tasks appear as flat items in the main list, not indented under parents.
- Workaround: Use tags to group related tasks
- Future: Collapsible parent-child trees in list view
No auto-close parent when all children close: Closing all children doesn't automatically close the parent.
- Reasoning: User should explicitly decide when a project is "done" (maybe you want to add more children)
- Workaround: Manually review and close parent when ready
No dependency chains: Cascading only goes one level (parent → child or child → parent), not through entire hierarchy.
- Example: Great-grandparent closes → cascades to grandparent → cascades to parent → cascades to child (only first two levels cascade)
- Workaround: Manually close deeply nested hierarchies if needed
When NOT to Use Parent-Child
Don't use for:
- Simple tagging: Use tags instead ("work", "personal")
- Loose associations: "Related to project X" → use tags
- Linear dependencies: "Task B after Task A" → use BLOCKED state + note
Do use for:
- True decomposition: Project breaks into parts
- Ownership: "This subtask belongs to this project"
- Cascading logic: You want automatic state syncing
Conclusion: Organize Complexity with Hierarchy
Flat task lists fail for complex projects. Parent-child relationships bring structure:
- Decompose large projects into manageable pieces
- Visualize relationships between tasks
- Automate state changes with cascading logic
- Inherit attributes for faster child creation
To-Track's parent-child system goes beyond basic subtasks with intelligent cascading:
- Close parent → close active children (but preserve open children)
- Activate child → activate parent (projects start when work starts)
- Deactivate parent → deactivate children (pause projects gracefully)
Whether you're managing software sprints, content calendars, event planning, or personal goals, parent-child tasks transform chaos into organized hierarchies.
Stop flattening your projects. Start organizing them with parent-child tasks.
FAQ
Q: Can a task have multiple parents? A: No—each task has at most one parent. For tasks that belong to multiple projects, use tags instead.
Q: What happens if I delete a parent task? A: Child tasks remain (they don't get deleted), but their parent_id becomes null (orphaned). You can reassign them to a new parent or leave them standalone.
Q: Can I move a child to a different parent? A: Yes. Open the child task, tap "Parent Task" section, select a different parent (or "None" to remove parent relationship).
Q: Do grandchildren cascade when closing a parent? A: Only direct children cascade. If you close a parent, its children close (if active), but grandchildren are not affected directly. However, if a child closes and has its own children, those grandchildren would cascade based on the child's closure.
Q: Can I prevent cascading for specific tasks? A: Not currently. Cascading is automatic based on state categories. If you don't want a child to close, manually reopen it after the parent closes.
Q: How do I see all tasks in a project hierarchy? A: Create a custom list filtering by the parent task ID or use a shared tag across all related tasks.
Q: Can parent-child relationships cross between recurring and non-recurring tasks? A: Yes, but be cautious. If a parent is recurring and resets, children remain as-is (they don't reset). This can create orphaned children over time.
Q: What's the maximum nesting depth? A: Unlimited technically, but 3-4 levels are recommended for usability.
Ready to organize complex projects? Download To-Track and master parent-child task hierarchies with intelligent cascading logic.
Try To-Track free
Offline-first tasks, custom states, time tracking. No account required.