Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

React Renderer Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

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:

  1. composer require lokalguiden/react-renderer
  2. The service provider is auto-discovered; publish the config if you need non-defaults: php artisan vendor:publish --tag=react-renderer-config
  3. Ensure a Node runtime is available on the app host (or V8Js if you're on the legacy path). SSR is a hard dependency — this is the first thing to verify, because it's the #1 reason installs "work" locally and die in CI/production.
  4. Build your React bundle (Vite/Webpack) so a server entrypoint exists — typically resources/js/ssr.js exporting a render function that takes props and returns { html, head }.
  5. Render from a controller by passing the component name and props to the renderer, and echo the returned markup into your Blade template as {!! $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.

Implementation Patterns

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.

Gotchas and Tips

  • Two builds, two entrypoints. You need a client bundle and a server bundle. If renderToString works but pages are blank in the browser, you built/pointed at the wrong entry. This is the most common single-point failure.
  • Hydration mismatches are silent-ish. 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.
  • Node version drift. Production Node ≠ your local Node ≠ CI Node causes subtle build failures (especially with ESM/CJS interop). Pin Node in .nvmrc/Docker and match CI.
  • Timeout failures. Node subprocess renderers have a timeout; a slow component (sync fetch, big data transform) will return an empty/error HTML and you'll only see it in logs. Set a sane timeout, log render duration, and alert on it.
  • Dev server vs built bundle. The renderer path in config usually points at a built bundle (e.g. 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.
  • CSRF and forms. SSR-rendered forms still need the token from the client session; don't put a stale token in the cached HTML. Inject it client-side or exclude from the cache key.
  • Debugging. Render to string in an artisan tinker session to isolate whether the problem is Laravel-side, Node-side, or hydration-side. If tinker works but requests fail, it's middleware/config; if tinker fails, it's the bundle.
  • Extension points. The renderer is usually swappable via the container binding in the config — a good place to decorate with logging, timing, or a cached renderer without touching call sites.
  • Upstream divergence. Because this is a GitLab fork of a widely-used package, the README may lag the code. When an API surprises you, check the tag/commit date against hammerstone's releases and read the diff — forks often trail fixes for months, and it pays to know which known issues you've inherited.
  • Stars/dependents are near zero. Treat this as unsupported: no Stack Overflow answers, no crowd-sourced debugging. Budget time for reading the source, and consider pinning to a specific commit and vendoring a patch if you need a fix upstream won't take.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table