← UI Rendering & SSR

UI RENDERING & SSR FEATURE

Live Widgets

Set refreshInterval and the server keeps re-rendering the widget for you. Live UI without converting the page into an app shell.

Feature Guide

A quick orientation block that answers the essential questions: what this feature does, how it works, why it matters, and the key concepts behind it.

What this does

A live slot can keep refreshing itself while the page remains SSR-first and HTML-driven.

How it works

refreshInterval on #[AsSlotResource] tells the framework to re-fetch the slot over SSE on a timer. The client swaps HTML in place and reconnects automatically if the stream drops.

Why it matters

This gives you live widgets without building a parallel client-side rendering system just to maintain one dynamic region.

Key concepts

refreshInterval
Declarative live-refresh interval for a slot resource.
SSE reconnection
Keeps the live slot updating even if the stream temporarily drops.
SSR-first live UI
A live region remains part of the server-rendered page model instead of becoming a mini SPA.

Reactive Slot Refresh

Live widgets without a client-side data loop

The server keeps re-rendering the slot as HTML, and the page swaps it in place. The widget feels live, but the UI model stays SSR-first.

Why this matters

  • Live UI often pushes teams toward a separate client-side state system for even simple status widgets.
  • Polling code and reconnection logic usually leak into ad hoc JavaScript instead of staying part of the rendering model.
  • The shell and the live widget can drift into two different architectures even though they belong to one page.
5s refresh interval declared on the slot
1 rendering model for static and live regions
0 custom polling loop to maintain

Client Loop Creep

Widget becomes a mini frontend app

State fetches, retry logic, and rendering drift into custom client code for what should be one live region.

The page stops having one rendering story.

SSR-First Live Region

Slot keeps itself fresh

refreshInterval stays on the slot contract, and the framework handles reconnection and HTML replacement.

Live behavior feels native without turning the page into a SPA shell.

refreshInterval auto-refresh SSE reconnection SSR-first live UI

Verified against Semitexa Ultimate 2026.09.19.1020

Live Widgets

Set refreshInterval and the server keeps re-rendering the widget for you. Live UI without converting the page into an app shell.

The problem

Live UI often pushes teams toward a separate client-side state system for even simple status widgets. Polling code and reconnection logic usually leak into ad hoc JavaScript instead of staying part of the rendering model. The shell and the live widget can drift into two different architectures even though they belong to one page.

How it works

A deferred slot with refreshInterval set keeps its SSE connection open after the first delivery. The SERVER holds a coroutine for that page, re-renders the slot when the interval elapses, and pushes the new HTML down the connection the page already has; the client swaps it into position. Nothing is re-requested on a timer: there is no polling interval and no request per refresh. The browser does still open a request when the SSE connection itself has to be re-established — recovery is handled by the framework, so reconnection logic does not need to be written by hand, but those reconnects are real HTTP requests and count against authentication, rate limits and capacity like any other.

Key mechanisms

  • refreshInterval — declares the push cadence in seconds directly on the slot resource. Its cost is a held coroutine per connected user for as long as the page is open, which is what makes this a capacity decision and not only a UX one.
  • server push — the framework re-renders on its own clock and pushes; the page never polls.
  • SSE reconnection — the framework recovers dropped connections automatically without custom retry code.
  • SSR-first live UI — the slot stays part of the server-rendered page model rather than becoming a client-managed widget.

Why this matters

Without a framework-level refresh mechanism, live regions require bespoke polling loops, reconnection handlers, and custom HTML replacement code. Declaring refreshInterval on the slot keeps the live behavior co-located with the slot contract and removes the need for per-widget polling infrastructure.

© Edsger W. Dijkstra: "Simplicity is prerequisite for reliability."

Notification Slot Secondary page region
<?phpdeclare(strict_types=1);namespace App\Application\Resource\Slot;use Semitexa\Ssr\Attribute\AsSlotResource;#[AsSlotResource(    handle: 'dashboard',    slot: 'dashboard.sidebar',    template: '@project/dashboard/deferred-sidebar.html.twig',    deferred: true,)]final class DeferredSidebarSlot{    /**     * @param list<string> $items     */    public function __construct(        public readonly string $headline,        public readonly array $items,    ) {}}

How it works

refreshInterval on #[AsSlotResource] tells the framework to re-fetch the slot over SSE on a timer. The client swaps HTML in place and reconnects automatically if the stream drops.

Why it matters

This gives you live widgets without building a parallel client-side rendering system just to maintain one dynamic region.

Key concepts

refreshInterval
Declarative live-refresh interval for a slot resource.
SSE reconnection
Keeps the live slot updating even if the stream temporarily drops.
SSR-first live UI
A live region remains part of the server-rendered page model instead of becoming a mini SPA.

Support Semitexa
Built for developers who prefer control over magic. Your support helps keep it fast, open, and evolving.

Donate via PayPal