Skip to main content
RapidDev - Software Development Agency
bubble-tutorial

How to build nested comments in Bubble

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.

What you'll learn

  • How to design a self-referencing Comment Data Type for nested threads
  • How to display nested comments with visual indentation
  • How to implement collapse and expand for comment threads
  • How to optimize queries for efficient nested comment loading
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner8 min read20-25 minAll Bubble plansMarch 2026RapidDev Engineering Team
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.

Prerequisites

  • 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 working example

Workflow summary
1NESTED COMMENTS ARCHITECTURE
2==============================
3
4DATA TYPE:
5 Comment:
6 - content: text
7 - author: User
8 - parent_item_type: text (e.g., 'Post')
9 - parent_item_id: text (Unique ID of content)
10 - parent_comment: Comment (self-reference)
11 - depth: number (0 = top-level, 1 = reply, 2 = reply-to-reply)
12 - is_deleted: yes/no
13
14DISPLAY STRUCTURE:
15 Page custom state: all_comments (list of Comments)
16 Loaded once: Do a Search for Comments
17 where parent_item_id = Current Page Item's Unique ID
18
19 Repeating Group (top-level):
20 Data source: all_comments :filtered (parent_comment is empty)
21 Sort: Created Date descending
22
23 Author name, content, timestamp
24 Reply button sets page state 'replying_to'
25 Collapse/Expand toggle
26 Reply form (visible when replying_to = this comment)
27
28 Nested Repeating Group (replies, left margin 40px):
29 Data source: all_comments :filtered
30 (parent_comment = Current Cell's Comment)
31 Visible when: is_collapsed is no
32
33 Author name, content, timestamp
34 Reply button
35
36 Deeper Nested RG (left margin 40px):
37 Data source: all_comments :filtered
38 (parent_comment = Current Cell's Comment)
39 Max depth: 2-3 levels
40
41KEY WORKFLOWS:
42 Submit Top-Level Comment:
43 Create Comment (parent_comment: empty, depth: 0)
44 Add to page all_comments state
45
46 Submit Reply:
47 Create Comment (parent_comment: replying_to, depth: parent+1)
48 Reset replying_to state
49 Add to page all_comments state
50
51 Toggle Collapse:
52 Set is_collapsed = not is_collapsed on the comment cell

Common mistakes when building nested comments in Bubble

Why it's a problem: Running a separate database search for replies inside each comment cell

How to avoid: Load all comments once into a page-level custom state, then use :filtered to split them by parent_comment

Why it's a problem: Allowing unlimited nesting depth

How to avoid: 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

Why it's a problem: Hard-deleting comments that have replies

How to avoid: 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

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I want to build a Reddit-style nested comment system in Bubble.io. Comments should have replies that indent visually, with collapse/expand functionality. Help me design the database schema and display logic.

Bubble Prompt

Create a self-referencing Comment Data Type with a parent_comment field. Display top-level comments in a Repeating Group, with nested Repeating Groups for replies indented by 40px. Add a Reply button that opens an inline form and a Collapse toggle that hides the reply thread.

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.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.