Skip to content

feat: Partial rendering (WIP)#548

Draft
stravo1 wants to merge 5 commits intofrappe:developfrom
stravo1:partial-rendering
Draft

feat: Partial rendering (WIP)#548
stravo1 wants to merge 5 commits intofrappe:developfrom
stravo1:partial-rendering

Conversation

@stravo1
Copy link
Copy Markdown
Member

@stravo1 stravo1 commented Apr 15, 2026

This PR introduces partial rendering to Builder.

Until now, Builder could only render entire pages. With this change, it can render specific blocks (currently called Tiles, name subject to change) independently, without re-rendering the full page.

This enables dynamic updates for specific sections of a page—without requiring a full page refresh—preserving client state in other section, somewhat mimicking SPA behaviour.


Demo

In the Only SSR scenario, dynamic values (e.g., comments) can only be updated via a full page refresh.

With partial rendering, the comments section can be updated independently:

Screen.Recording.2026-04-17.at.9.47.35.AM.mp4

The counter section demonstrates whether a full page refresh occurred, since its state is entirely client-side:

Screen.Recording.2026-04-17.at.10.17.10.AM.mp4

We can also handle cases where comments are edited or deleted after the initial render:

Screen.Recording.2026-04-17.at.10.45.06.AM.mp4

How it works

This is how Builder renders a block:

partial-rendering

So we can theoretically render specific blocks in isolation given their inherited block data and block props. This is exactly what we do:

A Tile can be re-rendered on the client using:

refreshTile(el)

Where el can be:

  • a query selector, or
  • a DOM node representing the Tile

Flow:

  1. refreshTile sends a request to the server with:

    • block_id
    • inherited block_data
    • inherited block_props
  2. The server re-renders the block using this context

  3. It returns HTML for that specific block

  4. The client merges the returned HTML into the existing DOM

Screen.Recording.2026-04-17.at.10.47.42.AM.mp4
Screenshot 2026-04-17 at 10 49 09 AM ---

Additional improvements on Block Client Scripts (QoL)

Event system for inter-block communication

  • dispatch(event, detail?, target?)

    • Publish events (default target: document)

    • Example:

      dispatch("refresh-comments")
  • listen(event, callback)

    • Subscribe to events

    • Example:

      listen("refresh-comments", callback)

Global reactive store

  • $reactive: a lightweight global reactive store

For more details:
28465c4

stravo1 added 3 commits April 7, 2026 01:55
- blocks which can be partially rendered are named Tiles (subject to change)
- AlpineJS is now bundled (if opted for or if page contains Tiles)
- Tiles for a page are saved upon preview or publish, NOT every time that page is saved
- a Tile can be rendered by making a POST request to the same URL as the page and providing the block_id, block_data and props or simply using the refreshTile function
a lightweight Alpine-based reactive library for managing global state across scripts.

API:

set(key, value)
  $reactive.set('count', 1)
  $reactive.set('user', { name: "A" })

get(key)
  const count = $reactive.get('count')

update(key, updater, options?)
  $reactive.update('count', c => (c || 0) + 1)
  $reactive.update('user', { name: "B" })
  $reactive.update('count', 10)
  $reactive.update('count', c => c, { skipEqual: true })

watch(key, callback)
  $reactive.watch('count', (val, old) => {
    console.log(old, '→', val)
  })

effect(fn)
  $reactive.effect(() => {
    console.log($reactive.get('count'))
  })

delete(key)
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 15, 2026

Codecov Report

❌ Patch coverage is 51.85185% with 39 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.50%. Comparing base (bcaece0) to head (47f75de).
⚠️ Report is 13 commits behind head on develop.

Files with missing lines Patch % Lines
...ilder/builder/doctype/builder_page/builder_page.py 47.88% 37 Missing ⚠️
builder/utils.py 66.66% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #548      +/-   ##
===========================================
- Coverage    63.49%   57.50%   -5.99%     
===========================================
  Files           27       29       +2     
  Lines         2802     3163     +361     
===========================================
+ Hits          1779     1819      +40     
- Misses        1023     1344     +321     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant