Skip to main content
Inertia lets you build a modern React frontend with classic server-side routing. Your Go routers decide which page to show and what data it receives, while React renders it. Since the server drives navigation, there is no client-side router to maintain and no REST layer between your pages and your services. This is the default stack for new Copper projects. The inertia package (from gocopper/pkg) provides the server-side adapter, wired in automatically by copper create.

Rendering a Page

Inject *inertia.Renderer into your router and call Render with a component name and props:
pkg/rockets/router.go
Components live in web/src/pages/ and receive props directly:
web/src/pages/rockets.tsx
On a full page load, Copper renders the HTML shell with the page data embedded. On navigation, Inertia requests only the JSON; the renderer will detect which is which automatically.

Forms

You may read and validate a form submission using ReadForm, which decodes the JSON body and validates its valid: tags (govalidator). On validation failure, the error is flashed automatically and ReadForm returns false, so you simply redirect back:
This is the classic post/redirect/get pattern: mutations always end in Redirect303, and the next render picks up any flashed props. Validation errors appear on the client under flash.validationError.
ReadForm’s two failure modes differ: a body that fails validation flashes the error and leaves the response for you to write, but a body that can’t be decoded as JSON at all writes an error response itself. Both return false.

Flash Props

FlashProps stores props for a single upcoming render, which is perfect for success and error messages across a redirect:
The next page render receives them under the flash prop, after which they are gone:

Shared Props

ShareProps adds props to the current request’s render from anywhere. It is typically called from a middleware so that every page in a section receives common data:
You may attach the middleware per-route via Middlewares, or globally in pkg/app/handler.go.
ShareProps identifies the request via its request ID, so chttp.SetRequestIDInCtxMiddleware() must be in your global middlewares. Scaffolded projects include it by default. Successive calls for the same request replace previously shared props rather than merging them, so you should share everything in a single call.

Partial Reloads

When the client reloads only specific props (router.reload({ only: ["rockets"] })), you may skip computing everything else with ShouldLoadProp:
ShouldLoadProp returns true on full renders and only for the requested props on partial reloads.

Deferred Props

Deferred props let a page render immediately while slow data loads in a follow-up request. Declare them in DeferredProps, and guard the expensive work with ShouldLoadDeferredProp:
Unlike ShouldLoadProp, ShouldLoadDeferredProp returns false on the initial render: the prop is stripped from the first response and fetched immediately afterwards. On the client, wrap the slow section in Inertia’s <Deferred>:

Customizing the Renderer

The renderer is immutable; each With* method returns a copy, so you may configure it once in your constructor:
  • WithBasePath(path) mounts a section under a URL prefix. Redirects and page URLs have the prefix stripped so that client-side paths stay clean; it pairs with chttp.base_path.
  • WithLayoutTemplate(name) renders pages inside a different layout than main.html.
  • WithComponent(name) sets a default component for all renders.
RenderParams accepts per-render LayoutTemplate and BasePath overrides too.

Server-Side Rendering

SSR is opt-in. Run the Inertia SSR server (see the Inertia SSR guide) and enable it in config:
Copper sends each page to the SSR server and injects the rendered HTML. If the SSR server is down or errors, Copper logs a warning and falls back to client-side rendering, so SSR will never take your pages down.

Configuration