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
Create the self-referencing Comment Data Type
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.
Display top-level comments in a Repeating Group
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.
Build the nested reply display with indentation
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.
Add the reply form with parent tracking
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.
Implement collapse and expand for threads
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.
Optimize queries and add moderation controls
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
1NESTED COMMENTS ARCHITECTURE2==============================34DATA TYPE:5 Comment:6 - content: text7 - author: User8 - 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/no1314DISPLAY STRUCTURE:15 Page custom state: all_comments (list of Comments)16 Loaded once: Do a Search for Comments17 where parent_item_id = Current Page Item's Unique ID1819 Repeating Group (top-level):20 Data source: all_comments :filtered (parent_comment is empty)21 Sort: Created Date descending22 │23 ├── Author name, content, timestamp24 ├── Reply button → sets page state 'replying_to'25 ├── Collapse/Expand toggle26 ├── Reply form (visible when replying_to = this comment)27 │28 └── Nested Repeating Group (replies, left margin 40px):29 Data source: all_comments :filtered30 (parent_comment = Current Cell's Comment)31 Visible when: is_collapsed is no32 │33 ├── Author name, content, timestamp34 ├── Reply button35 │36 └── Deeper Nested RG (left margin 40px):37 Data source: all_comments :filtered38 (parent_comment = Current Cell's Comment)39 Max depth: 2-3 levels4041KEY WORKFLOWS:42 Submit Top-Level Comment:43 → Create Comment (parent_comment: empty, depth: 0)44 → Add to page all_comments state4546 Submit Reply:47 → Create Comment (parent_comment: replying_to, depth: parent+1)48 → Reset replying_to state49 → Add to page all_comments state5051 Toggle Collapse:52 → Set is_collapsed = not is_collapsed on the comment cellCommon 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.
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.
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.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation