lokalguiden/react-renderer
Lokalguiden React Renderer lets Laravel apps render React components from PHP and Blade views, bridging server-side PHP with client-side React for SEO-friendly, fast-loading interfaces. Simple helpers and configurable asset handling make it easy to add React UI without a separate frontend.
This is a server-side rendering (SSR) bridge for React that lets you send your component tree down as HTML on first paint and hydrate on the client. It's a fork/descendant of the hammerstone/react-renderer lineage, so most of the public API mirrors that package — when in doubt, check the README and src/ in the repo, and cross-reference hammerstone's docs for method signatures.
Minimal setup:
composer require lokalguiden/react-rendererphp artisan vendor:publish --tag=react-renderer-configresources/js/ssr.js exporting a render function that takes props and returns { html, head }.{!! $renderer->render() !!}.First use case: a single marketing or detail page where SEO matters. Don't refactor everything — wire up one controller, verify the HTML source contains real markup (view-source, not devtools), and confirm the client bundle hydrates without a mismatch warning. That one vertical slice validates the whole pipeline: Node availability, bundle correctness, prop serialization, and hydration.
Where to look first in the repo: the config file (tells you the renderer driver and paths), the Renderer/Engine classes (tells you what render() actually returns), and any example Inertia root view if you're using Inertia.
Inertia integration (most common). If you're on Inertia, register this as the SSR engine and swap the client entrypoint from createInertiaApp to hydrateRoot. The pattern is: resolve page component → renderToString → return { head, body } → the middleware injects those into the root template. Laravel-side, you typically only need the standard Inertia setup plus this package's renderer; the page object is serialized and passed straight to the Node renderer.
Standalone components. For non-Inertia apps, you'll call the renderer directly in a controller or view composer:
$renderer->component('Product/Show', ['product' => $product->toArray()])
->render();
Keep props JSON-serializable — Eloquent models, closures, resources with lazy loading, and Carbon instances will either blow up in json_encode or silently send more data than you expect.
Shared props / layout data. Anything global (auth user, flash messages, CSRF, feature flags) should be collected in one place — a middleware or a base controller method — so both the SSR pass and the client hydration see identical data. Asymmetry here is what produces hydration warnings.
Cache aggressively. SSR is CPU-heavy and spawns Node or hits V8Js per request. Wrap rendered output in Cache::remember keyed on component + a hash of props for pages that don't vary by user. For per-user pages, consider rendering the shell SSR and deferring user-specific widgets to client-only.
Static/edge generation. For content pages, treat SSR output as pre-renderable: run the renderer in an artisan command, write HTML to disk or object storage, serve via CDN. React hydration still runs on the client; you just skip the Node call per request.
Testing. Unit-test components in JS (React Testing Library); in PHP, assert that the renderer returns a non-empty string containing expected markers. Snapshot the HTML for regressions, but store snapshots as fixtures, not inline strings, or you'll fight whitespace diffs forever.
renderToString works but pages are blank in the browser, you built/pointed at the wrong entry. This is the most common single-point failure.Did not expect server HTML to contain... in console means your props differ between passes or you branched on typeof window. Fix the props first; suppressHydrationWarning is a last resort, not a fix.window, document, localStorage all crash SSR. Guard with typeof window !== 'undefined' or move to useEffect. Third-party libs that touch document at import time will fail before you can guard — use dynamic imports or SSR-safe shims..nvmrc/Docker and match CI.bootstrap/ssr/ssr.js). In dev, verify you're running the Vite SSR server or rebuilding — otherwise you'll edit React and see no change, then waste an hour.How can I help you explore Laravel packages today?