Contents

Chapter 1

Responsive Design Notes for Bubble.io

How to make each template work across desktop, tablet, and mobile using Bubble's responsive engine.


Bubble's Responsive Engine (Current Version)

Bubble uses a flexbox-based layout system with rows and columns. Key concepts:

  • Container layout: Every group is either a Row (horizontal), Column (vertical), or Align to Parent (absolute positioning)
  • Min/Max width: Elements stretch to fill their container but respect min-width and max-width constraints
  • Wrapping: Row containers can wrap their children to the next line when they don't fit
  • Conditional visibility: Hide/show elements based on page width
  • Gap: Spacing between child elements in a container

If your Bubble app still uses the legacy fixed-width engine, you'll need to migrate to the responsive engine first. In the Bubble editor, go to Settings → General → check "Make this application responsive."


Breakpoint Strategy

Bubble doesn't have explicit breakpoints like CSS media queries. Instead, you achieve responsive behavior through:

1. Flexible widths (min/max instead of fixed)

2. Row wrapping (children flow to next line)

3. Conditional visibility (hide elements at narrow widths)

DeviceViewport WidthLayout Approach
Desktop1024px+Full layout — sidebar + main content, multi-column grids
Tablet768px – 1023pxCollapsed sidebar, 2-column grids
Mobile< 768pxSingle column, hamburger menu, stacked layout

Per-Template Responsive Notes

SaaS Dashboard

Desktop (1024px+):

  • Sidebar: 240px fixed width, always visible
  • Widget grid: 4 columns
  • Dashboard header: row layout with controls inline

Tablet (768px):

  • Sidebar: collapsed to icon-only (60px) or hidden behind hamburger
  • Widget grid: 2 columns
  • Header controls: stack vertically or move to a dropdown

Mobile (<768px):

  • Sidebar: hidden, accessed via hamburger menu (floating group)
  • Widget grid: 1 column, full-width cards
  • Date range picker: full-width dropdown
  • Hide export button (move to a menu)

Implementation:

  • Sidebar group: min-width 60px, max-width 240px. Add a conditional: when page width < 768, this element's width = 0 (hidden)
  • Widget repeating group: set to "Min width of column" = 280px with wrapping enabled. On desktop, 4 fit per row. As the page narrows, it naturally becomes 2, then 1.

Marketplace

Desktop: 3-column listing grid, sidebar filters visible

Tablet: 2-column grid, filters collapse into a "Filters" button that opens a popup

Mobile: 1-column listing cards, search bar at top, filters in a bottom sheet

Key responsive elements:

  • Search results grid: Use min-width 300px per column with wrapping
  • Filter sidebar: Visible on desktop, hidden on mobile with a toggle button
  • Listing detail image gallery: Full-width on mobile, 60/40 split on desktop
  • Messaging inbox: Two-panel on desktop, conversation list only on mobile (tap to open thread in separate view)

Booking System

Desktop: Calendar shows full week view, sidebar with service list

Tablet: Calendar shows 3-day view, service list above calendar

Mobile: Calendar shows day view only, available slots in a scrollable list

Key responsive elements:

  • Booking flow steps: Horizontal stepper on desktop, vertical on mobile
  • Calendar: This is typically handled by the calendar plugin's responsive settings. Most plugins auto-adapt.
  • Available time slots: Grid of buttons on desktop (4 per row), 2 per row on mobile
  • Booking confirmation: Full-width card layout on mobile

Directory

Desktop: Map + list split view (60% list, 40% map), sidebar filters

Tablet: List view with map toggle button (not split)

Mobile: List view only, map accessible via "View Map" button, search bar sticky at top

Key responsive elements:

  • Map/list split: Use a row container with wrapping. Map has min-width 300px. When viewport is too narrow, map wraps below the list
  • Listing cards: 3-column on desktop, 2 on tablet, 1 on mobile (use min-width wrapping)
  • Contact info on listing detail: Sidebar on desktop, below description on mobile
  • Hours table: Horizontal on desktop, vertical/accordion on mobile

Community Platform

Desktop: Three-column layout (sidebar nav, main content, trending/leaderboard sidebar)

Tablet: Two columns (nav sidebar collapsed, main content + trending below)

Mobile: Single column, bottom navigation bar, trending hidden

Key responsive elements:

  • Post list: Compact card layout on mobile (hide view count, show just title + author + reply count)
  • Reply threading: Reduce indent depth on mobile (max 2 levels instead of unlimited)
  • Reply editor: Full-width on mobile with simplified toolbar
  • Leaderboard sidebar: Hidden on mobile, accessible from bottom nav

Universal Responsive Patterns

Pattern: Collapsible Sidebar

Works for: SaaS Dashboard, Booking System

1. Create the sidebar as a group with min-width 0 and max-width 240

2. Add a custom state sidebar_open (yes/no, default: yes)

3. When sidebar_open = yes → width = 240, show labels

4. When sidebar_open = no → width = 60, show icons only

5. On page load: If page width < 768, set sidebar_open = no

6. Add a hamburger icon that toggles the state

Pattern: Stack on Mobile

Convert horizontal rows to vertical columns on narrow screens:

1. Use a Row container with wrapping enabled

2. Set each child's min-width to approximately 50% of mobile viewport (e.g., 300px)

3. On desktop, children sit side by side

4. On mobile, wrapping causes them to stack vertically

This is the single most useful responsive pattern in Bubble.

Pattern: Responsive Navigation

Desktop: Horizontal nav bar or vertical sidebar with text labels

Mobile: Bottom tab bar (for apps) or hamburger menu (for content sites)

Implementation:

1. Create two navigation elements: desktop_nav and mobile_nav

2. desktop_nav: visible when page width >= 768

3. mobile_nav: visible when page width < 768

4. mobile_nav is a floating group pinned to the bottom with 4–5 icon tabs

Pattern: Responsive Tables

Tables don't work well on mobile. Three alternatives:

1. Card layout: Each row becomes a card with fields stacked vertically

2. Horizontal scroll: Wrap the table in a group with horizontal scrolling

3. Priority columns: Show only essential columns on mobile, full table on desktop

Card layout is best for most cases:

Desktop: Repeating group layout = Full list (table rows)
Mobile: Repeating group layout = Extended (card-style cells)

Pattern: Responsive Typography

Use Bubble's responsive text settings:

  • Heading 1: 28px desktop → 22px mobile
  • Heading 2: 22px desktop → 18px mobile
  • Body: 16px on all sizes (never go below 14px on mobile)
  • Caption: 14px desktop → 12px mobile

Set these in your app's Styles tab for consistency.


Testing Responsive Layouts

1. Bubble's responsive viewer: In the editor, click "Responsive" tab to drag the viewport width

2. Chrome DevTools: F12 → toggle device toolbar → select device presets

3. Real devices: Always test on at least one actual phone — emulators miss touch target size issues

Common Responsive Bugs

"My sidebar overlaps the content on mobile"

Set the sidebar's min-width to 0 and use conditional width. Make sure the main content group doesn't have a fixed left margin — use the sidebar as a flex sibling instead.

"Text is too small on mobile"

Check your font sizes. Body text should be at least 14px on mobile. Don't rely on users pinch-zooming.

"Buttons are too small to tap"

Minimum touch target size is 44x44 pixels (Apple's guideline). Make sure buttons and clickable elements meet this on mobile.

"My repeating group is just one column on desktop"

Check that the repeating group's layout is set to Grid or Extended, not Full List. For Grid, verify the number of columns setting.


*Responsive design isn't about making things fit — it's about making things work on every device.*

Chapter 2

Reusable Patterns for Bubble.io Apps

Common patterns that apply across all five app templates. Use these as building blocks — they're the same regardless of whether you're building a SaaS dashboard, marketplace, booking system, directory, or community platform.


1. Authentication Flow

Sign Up → Create Profile → Redirect

Every app needs this three-step flow:

1. Sign up: Use Bubble's built-in "Sign the user up" action with email + password

2. Set profile fields: Immediately after signup, use "Make changes to Current User" to set display_name, role, and any default values

3. Redirect: Navigate to the main page (dashboard, homepage, etc.)

Login with Redirect-Back

When a non-logged-in user tries to access a protected page:

1. Set a custom state or URL parameter with the intended destination: /dashboard?redirect=/settings

2. On the login page, after successful login, check for the redirect parameter

3. If it exists, navigate there. Otherwise, navigate to the default page

Password Reset

Bubble has a built-in password reset flow:

1. "Send password reset email" action — sends a link to the user's email

2. The link goes to a page you designate (e.g., /reset-password)

3. On that page, use "Reset password" action with the token from the URL


2. Role-Based Access Control

Pattern: Role Check on Page Load

On every protected page, add a page-load workflow:

When: Page is loaded
Condition: Current User's role is not [required role]
Action: Navigate to /unauthorized (or redirect to login)

Pattern: Conditional Element Visibility

For elements that should only appear for certain roles:

Element conditional:
  When: Current User's role is Admin
  This element is visible: checked
  (Default: not visible)

Pattern: Workflow Permission Gate

On every workflow that modifies data, add a condition:

Workflow condition: Current User's role is Admin or Manager

This is your second line of defense after privacy rules. Even if someone manipulates the UI to reveal a hidden button, the workflow won't execute without the correct role.


3. Search and Filtering

Pattern: State-Based Filters

Use custom states on the page to store filter values. When any filter changes, update the state. Your repeating group's data source references the states.

Setup:

1. Create custom states on the page element: filter_category (text), filter_min_price (number), filter_sort (text)

2. When a dropdown value changes → Set state filter_category to dropdown's value

3. Repeating group data source: Search for Things where category = page's filter_category

Why states instead of directly referencing inputs? States persist across tab switches, survive element re-rendering, and make your data source expressions cleaner.

For search inputs, you don't want to trigger a search on every keystroke. Two approaches:

1. Search on Enter: Add a workflow "When Input's value is changed" with a "Pause before next action: 500ms" step. If the value changes again during the pause, the workflow restarts, effectively debouncing.

2. Search Button: Only search when the user clicks a button or presses Enter. Simpler and more predictable for complex searches.

Pattern: Empty State

Always handle the case where search returns no results:

Group "empty_state":
  Visible when: Repeating Group's list of Things:count = 0
  Content: "No results found. Try adjusting your filters."

4. Pagination

Pattern: Page Number Pagination

Bubble's built-in repeating group pagination works for most cases:

1. Set "Fixed number of cells" on the repeating group (e.g., 12)

2. Add "Show previous" and "Show next" links to the repeating group

3. Display current page: Use the :current page number property

Pattern: Load More Button

For infinite-scroll-style UX:

1. Create a custom state items_to_show (number), default 12

2. Repeating group data source: Search for Things:items up to items_to_show

3. "Load More" button workflow: Set state items_to_show to items_to_show + 12

4. Hide the button when items_to_show >= total items count


5. Notification System

Pattern: In-App Notifications

Used in: SaaS Dashboard, Marketplace, Community Platform.

Data type: Notification (recipient, type, message, link_url, is_read, triggered_by, created_date)

Creating notifications: Add a "Create Notification" step to relevant workflows (new message, new review, status change, etc.).

Displaying the bell badge:

Text element in nav bar:
  Content: Search for Notifications where recipient=Current User AND is_read=no:count
  Visible when: content > 0
  Style: red circle badge

Notifications page: Repeating group sorted by created_date descending. Each row has icon, message, time ago, and link. Clicking navigates to link_url and marks as read.

Pattern: Email Notifications

Use Bubble's "Send email" action for important events. Always respect the user's notification_email preference:

Workflow condition: Target User's notification_email = yes

6. Image Handling

Pattern: Image Upload with Preview

1. Use Bubble's Picture Uploader element

2. Below it, add an Image element with data source = "Picture Uploader's value"

3. This shows a preview of the uploaded image before the form is submitted

1. Use a MultiFile Uploader (or multiple Picture Uploaders)

2. Store images as list:image on the data type

3. Display in a horizontal repeating group with fixed cell width

4. First image in the list is the "cover" — display it larger elsewhere

Pattern: Avatar with Fallback

For user avatars, handle the case where no image is uploaded:

Image element:
  Dynamic source: Current User's avatar
  Conditional: When Current User's avatar is empty → show static default avatar image

7. Real-Time Updates

Pattern: Live Data with Auto-Refresh

Bubble's repeating groups auto-refresh when their data source changes. For near-real-time updates (like chat messages), this works out of the box — no manual polling needed.

For true real-time (sub-second), consider:

  • Bubble's built-in "Do every X seconds" workflow for critical updates
  • A real-time plugin for WebSocket connections (needed for live chat)

Pattern: Optimistic UI Updates

For actions like upvoting, show the change immediately without waiting for the server:

1. User clicks upvote → immediately update a client-side state to show +1

2. In parallel, the workflow creates the Vote record and updates the count on the server

3. When the repeating group refreshes, the server count overwrites the optimistic count

This feels faster to the user. If the server action fails (rare), the count will correct itself on refresh.


8. Data Validation

Pattern: Client-Side Validation Before Submit

Before creating or modifying records, validate inputs in the workflow condition:

Workflow condition:
  Input title is not empty
  AND Input title:length > 3
  AND Input email contains "@"
  AND Input price > 0

If validation fails, the workflow doesn't run. Show error messages using conditional alerts:

Group "error_title":
  Visible when: Button was clicked AND Input title is empty
  Content: "Title is required"
  Style: red text

Pattern: Unique Value Check

Before creating a record with a field that should be unique (like a slug or username):

Workflow step 1: Search for Things where slug = generated_slug
Condition for step 2: Search result:count = 0
Step 2: Create the thing
Error: If count > 0, show "This name is already taken"

9. Soft Delete Pattern

Instead of permanently deleting records, mark them as deleted:

1. Add a is_deleted (yes/no) field to the data type

2. "Delete" workflow: Set is_deleted = yes instead of using "Delete thing"

3. All searches include constraint: is_deleted = no

4. Admin can see deleted items and permanently remove them or restore them

5. Scheduled backend workflow: Permanently delete records where is_deleted = yes AND deleted_date was more than 30 days ago

This prevents accidental data loss and supports "undo" functionality.


10. Error Handling

Pattern: Workflow Error Alerts

After any action that might fail (payment, email, external API call):

Step N: [Action that might fail]
Step N+1 (only when result of N is empty/error):
  Show alert: "Something went wrong. Please try again."
  OR
  Navigate to /error page

Pattern: Graceful Degradation

For elements that depend on data that might not exist:

Group "data_section":
  Visible when: This Thing is not empty
  
Group "empty_section":
  Visible when: This Thing is empty
  Content: "No data available yet. [Call to action]"

*These patterns appear in every no-code app you'll ever build. Master them once, apply them everywhere.*

Bubble App Templates v1.0.0 — Free Preview