skip to content

For public, search-indexed pages in a Laravel app, how do Blade, Livewire, Inertia with or without SSR, and a separate SPA compare in the HTML the first response contains?

level: seniorimportance: should knowfreq 32%

answer

  1. Blade and Livewire render HTML on the server
  2. Inertia without SSR: JSON plus an empty div
  3. inertia:start-ssr runs a JavaScript process
  4. a separate SPA needs its own SSR
  5. SSR is optional per page type

basics

~20 s

Blade and Livewire send fully rendered HTML first. Inertia without SSR sends page JSON and an empty mount element, so content appears only after JavaScript runs; Inertia SSR adds a separate JavaScript process. A separate SPA needs its own SSR.

solid answer

~40 s

A **Blade** view is rendered by PHP, so the first response already contains every heading and paragraph. **Livewire** components also render their initial HTML on the server, then attach behaviour. **Inertia** by default renders a root view whose `@inertia` directive (or `<x-inertia::app />`) outputs the page object as a JSON `<script>` plus an empty `<div>`; the React, Vue or Svelte page renders in the browser, so the raw HTML carries no page content. Inertia's **SSR** mode renders that first response on the server through a JavaScript process you start with `php artisan inertia:start-ssr` and keep running in production. A **separate SPA** faces the same empty-HTML problem and needs its own SSR framework or prerendering. For a mostly public site, server-driven pages are the simpler route to indexable HTML.

code

html · 11 lines
html
<!DOCTYPE html>
<html lang="en">
<head>
    @vite(['resources/css/app.css', 'resources/js/app.tsx'])
    <x-inertia::head />
</head>
<body>
    {{-- without SSR this outputs a JSON script tag and an empty div --}}
    <x-inertia::app />
</body>
</html>

go deeper

for a junior

Know that Blade and Livewire send finished HTML, while Inertia and SPAs render in the browser unless SSR is added.

for a middle

Describe what Inertia's root view outputs without SSR and what inertia:start-ssr adds to the deployment.

for a senior

Match rendering to page type: Blade for public content, Inertia for app screens, SSR only where rich pages must be indexed.

for a principal

Count SSR as an operational commitment, another supervised runtime, and decide early which surfaces justify it.

## Why the first response matters Search engines, link-preview bots and users on slow devices all benefit when the **first HTML response** already contains the content. Whatever JavaScript does afterwards, that response is what non-rendering crawlers index, what social previews read, and what appears before scripts finish downloading. Each Laravel frontend approach produces a very different first response. ## Approach by approach | Approach | First response contains | Extra infrastructure | |---|---|---| | Blade-only | complete rendered HTML | none | | Livewire | complete rendered HTML for components, plus the snapshot | none | | Inertia, no SSR | layout, a JSON `<script>` with the page's props, an empty mount `<div>` | none | | Inertia with SSR | rendered page HTML plus the same JSON for the client to take over | a long-running JavaScript SSR process | | Separate SPA | typically an empty shell from the SPA's host | its own SSR framework or a prerendering step | ### Blade and Livewire Both are **server-rendered by construction**. A Livewire component's first render is ordinary Blade output; interactivity attaches afterwards. The exception is a component you deliberately mark as lazy: it renders a placeholder first and fetches its real content in a follow-up request, so do not lazy-load content you want indexed. Titles and meta tags come from the Blade layout, set per page like any server-rendered site. ### Inertia without SSR The root Blade template (for example the starter kits' `app.blade.php`) uses `<x-inertia::app />` or the `@inertia` directive. That outputs a `<script data-page="app" type="application/json">` holding the page object — component name, props, URL, version — and an empty `<div id="app">`. The client adapter reads the JSON and renders the component in the browser. Until then, the document has no page content, which is fine for an authenticated dashboard and poor for public landing pages. ### Inertia with SSR Inertia can render the first visit on the server: the Laravel side sends the page object to a **JavaScript SSR server**, receives HTML and embeds it. You build a separate SSR bundle (the kits' `npm run build:ssr`) and run the server with `php artisan inertia:start-ssr` (stopped with `inertia:stop-ssr`). That process has to be supervised in production like a queue worker. Subsequent navigations are still client-side. ### Separate SPA A standalone React, Vue or Svelte app served from a static host gets no help from Laravel's rendering at all. It needs an SSR-capable meta-framework or build-time prerendering — both beyond Laravel, and both adding a second server-side runtime to operate. ## Deciding in practice 1. **Mostly public, content-led pages** (marketing, listings, docs): Blade, with Livewire for interactive widgets. Indexable HTML comes free. 2. **Mostly authenticated app screens** with a small public surface: Inertia without SSR is common — crawlers never see the app screens anyway — and public pages can be separate Blade routes in the same app. 3. **Rich JavaScript UI that must also be indexed**: Inertia with SSR, accepting the extra process and the constraint that page components must render without browser-only APIs on the server. 4. **A separate SPA for public pages** is usually the most expensive way to get indexable HTML. ## Metadata and titles Indexable HTML is not only body content; titles and meta tags matter too. Blade and Livewire pages set them in the layout on the server. Inertia pages set them with the `<Head>` component, and the root template's `<x-inertia::head>` slot (or `@inertiaHead`) is where server-rendered head tags land when SSR is running — without SSR, the title is set by JavaScript after load, so crawlers that do not run scripts see only the layout's defaults. ## Common misconceptions - "Inertia apps cannot be indexed" — they can, with SSR, or by serving public pages from Blade routes. - "SSR is all or nothing" — a single Laravel app can mix Blade pages and Inertia pages on different routes. - "Livewire needs SSR configuration" — its first render already is server HTML. - Treating SSR as free: it is another runtime to deploy, monitor and restart on every release.

  • Your Inertia app's SSR process crashes in production. What happens to page loads?
    By default the Laravel adapter falls back to the client-rendered response — the JSON page object and an empty mount element — and dispatches an `SsrRenderFailed` event (it throws only if `inertia.ssr.throw_on_error` is on). Users with JavaScript still see the page; crawlers and link previews see no content until the process is back, so it must be supervised.
  • Can one Laravel app serve its marketing pages with Blade and its dashboard with Inertia?
    Yes. Both are ordinary routes in `routes/web.php`: marketing routes return `view(...)` and dashboard routes return `Inertia::render(...)`. The public pages get server-rendered HTML without an SSR process, while the authenticated screens keep Inertia's client rendering.

saying these in an interview costs you the question

  • Livewire pages arrive as an empty div that JavaScript fills in
  • Inertia apps can never be indexed by search engines
  • Inertia SSR runs inside PHP with no extra process
  • A separate SPA gets server rendering from Laravel automatically
  • One Laravel app cannot mix Blade pages and Inertia pages