# How to build nested comments in Bubble

- Tool: Bubble
- Difficulty: Beginner
- Time required: 20-25 min
- Compatibility: All Bubble plans
- Last updated: March 2026

## TL;DR

Nested comments in Bubble display threaded replies with visual indentation using a self-referencing Comment Data Type. This tutorial covers designing the parent-child comment relationship, displaying nested comments with indentation levels, building collapse and expand functionality, and optimizing database queries for efficient loading of nested comment threads.

## Overview: Implementing Nested Comments in Bubble

This tutorial shows you how to build a Reddit-style nested comment system in Bubble. You will create a self-referencing Comment Data Type, display threaded replies with visual indentation, add collapse and expand controls, and optimize the database structure for efficient loading.

## Before you start

- A Bubble app with user authentication set up
- A content page (blog post, article, or similar) where comments will appear
- Basic understanding of Bubble Data Types and Repeating Groups
- Familiarity with custom states

## Step-by-step guide

### 1. Create the self-referencing Comment Data Type

In the Data tab, create a Data Type called Comment with these fields: content (text), author (User), parent_item_type (text — the type of content being commented on, e.g., 'Post'), parent_item_id (text — the unique ID of the content), parent_comment (Comment — self-reference for nesting), depth (number — 0 for top-level, 1 for replies, 2 for replies-to-replies), is_deleted (yes/no — for soft delete). The self-referencing parent_comment field is the key to nesting — a comment with no parent_comment is a top-level comment, and a comment with a parent_comment is a reply.

> Pro tip: Add a depth field to control how many levels deep replies can go. Most platforms cap nesting at 3-5 levels to keep the UI readable.

**Expected result:** Your Comment Data Type supports self-referencing nesting with depth tracking and soft deletion.

### 2. Display top-level comments in a Repeating Group

On your content page, add a Repeating Group with data source: Do a Search for Comments where parent_item_id = Current Page Item's Unique ID and parent_comment is empty (this gives you only top-level comments). Sort by Created Date descending. In each cell, display the author name, comment content, timestamp, and a Reply button. Add a reply count text showing 'X replies' using Do a Search for Comments where parent_comment = Current Cell's Comment:count. Below the Repeating Group, add a comment input form with a Multiline Input and Submit button.

**Expected result:** Top-level comments display in chronological order with reply counts and a form for adding new comments.

### 3. Build the nested reply display with indentation

Inside each top-level comment cell, add another Repeating Group (nested) with data source: Do a Search for Comments where parent_comment = Current Cell's Comment, sorted by Created Date ascending. Set this nested Repeating Group's left margin to 40px to create visual indentation. Inside each nested cell, display the same author, content, and timestamp layout as the parent. For deeper nesting (replies to replies), you can add a third Repeating Group inside the nested one with another 40px left margin. Bubble does not support infinite recursive nesting in Repeating Groups, so limit to 2-3 levels of nesting visually.

**Expected result:** Replies appear indented beneath their parent comments, with deeper replies further indented.

### 4. Add the reply form with parent tracking

When a user clicks the Reply button on a comment, show an inline reply form. Use a custom state on the page called 'replying_to' (type: Comment). The Reply button's workflow sets this custom state to the Current Cell's Comment. Add a Group below each comment cell that is only visible when the page's replying_to is the Current Cell's Comment — this group contains a Multiline Input and Submit button. The Submit workflow: (1) Create a new Comment with parent_comment = page's replying_to, depth = parent_comment's depth + 1, parent_item_id = same as parent. (2) Reset the replying_to state to empty. (3) Clear the input.

**Expected result:** Clicking Reply on any comment opens an inline reply form, and submitting creates a properly nested reply.

### 5. Implement collapse and expand for threads

Add a custom state on each top-level comment cell called 'is_collapsed' (yes/no, default no). Add a toggle text or icon that shows 'Collapse' when is_collapsed is no and 'Expand (X replies)' when is_collapsed is yes. The toggle click workflow switches the custom state. Set the nested Repeating Group's visibility condition to: Current Cell's Comment's is_collapsed is no. When collapsed, only the top-level comment is visible, saving screen space. For the toggle text, use a Conditional: when is_collapsed is yes, show the reply count to indicate hidden content.

> Pro tip: Consider collapsing threads with more than 5 replies by default to keep the page readable. Set is_collapsed to yes initially when the reply count exceeds your threshold.

**Expected result:** Users can collapse and expand comment threads, with collapsed threads showing the reply count.

### 6. Optimize queries and add moderation controls

To reduce workload units, avoid running Do a Search for inside each nested Repeating Group cell. Instead, load all comments for the page content in one search at the page level: Do a Search for Comments where parent_item_id = Current Page Item's Unique ID. Store this in a custom state (list of Comments). Then filter this list for display: top-level comments use :filtered where parent_comment is empty, and replies use :filtered where parent_comment = Current Cell's Comment. This reduces database queries from N+1 to 1. For moderation, add a Report button that flags comments and an admin view showing flagged comments for review.

**Expected result:** Comment loading is optimized to a single database query, and moderation controls are available for flagging inappropriate content.

## Complete code example

File: `Workflow summary`

```text
NESTED COMMENTS ARCHITECTURE
==============================

DATA TYPE:
  Comment:
    - content: text
    - author: User
    - parent_item_type: text (e.g., 'Post')
    - parent_item_id: text (Unique ID of content)
    - parent_comment: Comment (self-reference)
    - depth: number (0 = top-level, 1 = reply, 2 = reply-to-reply)
    - is_deleted: yes/no

DISPLAY STRUCTURE:
  Page custom state: all_comments (list of Comments)
    Loaded once: Do a Search for Comments
      where parent_item_id = Current Page Item's Unique ID

  Repeating Group (top-level):
    Data source: all_comments :filtered (parent_comment is empty)
    Sort: Created Date descending
    │
    ├── Author name, content, timestamp
    ├── Reply button → sets page state 'replying_to'
    ├── Collapse/Expand toggle
    ├── Reply form (visible when replying_to = this comment)
    │
    └── Nested Repeating Group (replies, left margin 40px):
        Data source: all_comments :filtered
          (parent_comment = Current Cell's Comment)
        Visible when: is_collapsed is no
        │
        ├── Author name, content, timestamp
        ├── Reply button
        │
        └── Deeper Nested RG (left margin 40px):
            Data source: all_comments :filtered
              (parent_comment = Current Cell's Comment)
            Max depth: 2-3 levels

KEY WORKFLOWS:
  Submit Top-Level Comment:
    → Create Comment (parent_comment: empty, depth: 0)
    → Add to page all_comments state

  Submit Reply:
    → Create Comment (parent_comment: replying_to, depth: parent+1)
    → Reset replying_to state
    → Add to page all_comments state

  Toggle Collapse:
    → Set is_collapsed = not is_collapsed on the comment cell
```

## Common mistakes

- **Running a separate database search for replies inside each comment cell** — If you have 50 top-level comments, each with a 'Do a Search for' in the nested Repeating Group, that is 50+ database queries on a single page load Fix: Load all comments once into a page-level custom state, then use :filtered to split them by parent_comment
- **Allowing unlimited nesting depth** — Bubble cannot recursively nest Repeating Groups infinitely, and deeply nested comments become unreadable on mobile screens Fix: Cap nesting at 2-3 visual levels. For deeper replies, flatten them under the third level with an @mention to indicate who they are replying to
- **Hard-deleting comments that have replies** — Deleting a parent comment orphans all its replies, breaking the thread structure and leaving replies without context Fix: Use soft deletion with an is_deleted field. Display deleted comments as 'This comment was deleted' while keeping the reply thread intact.

## Best practices

- Load all comments in a single search and use client-side :filtered to split by parent — reduces workload units dramatically
- Cap visual nesting at 2-3 levels to keep the UI readable on all screen sizes
- Use soft deletion (is_deleted flag) to preserve thread structure when comments are removed
- Collapse long threads by default and show a reply count to indicate hidden content
- Store depth as a number field for easy level-based styling and nesting limits
- Add a page-level custom state for replying_to to manage inline reply form visibility

## Frequently asked questions

### How many nesting levels should I support?

Two to three visual levels work best. Beyond that, the indentation becomes too narrow on mobile screens. For deeper replies, flatten them at the third level and use @mentions to indicate the reply target.

### How do I efficiently count replies for each comment?

Instead of running a search per comment, load all comments once and use :filtered with parent_comment = Current Cell's Comment followed by :count. This uses the already-loaded data without additional database queries.

### Can I sort comments by most liked or most recent?

Yes. Add a like_count field to Comment (updated when users like a comment). Add a sort toggle above the Repeating Group that switches the data source sort between Created Date and like_count.

### How do I handle comment moderation?

Add a report_count field to Comment. When users click a Report button, increment the count. When report_count exceeds a threshold (e.g., 3), auto-hide the comment and add it to an admin review queue.

### Can RapidDev help implement a nested comment system in Bubble?

Yes. RapidDev can build optimized nested comment systems with threading, moderation, real-time updates, and performance optimization for high-volume comment sections.

### Will nested comments work on mobile?

Yes, but reduce the indentation amount on mobile breakpoints (e.g., 20px instead of 40px) to prevent content from becoming too narrow. Consider limiting mobile nesting to 2 levels maximum.

---

Source: https://www.rapidevelopers.com/bubble-tutorial/implement-a-nested-comments-feature-in-bubble
© RapidDev — https://www.rapidevelopers.com/bubble-tutorial/implement-a-nested-comments-feature-in-bubble
