goravelinertia

package module
v1.18.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2026 License: MIT Imports: 22 Imported by: 0

README

Goravel Inertia

Goravel Inertia

Build server-driven single-page apps in Goravel with Inertia.js — no API layer, no client routing.

CI Go Reference Go 1.26 Inertia v3 MIT


goravel-inertia is an Inertia.js adapter for the Goravel framework. It exposes a Laravel-style API on top of petaki/inertia-go (which implements the Inertia v3 protocol) and wires it into Goravel's HTTP lifecycle, session, validation and routing.

func (c *HomeController) Index(ctx http.Context) http.Response {
    return facades.Inertia().Render(ctx, "Home", map[string]any{
        "message": "Hello from Goravel + Inertia",
    })
}

Features

  • 🧩 Inertia v3 props — deferred, optional, always, merge / deep-merge / prepend, scroll, once.
  • Vite integration — HMR dev server (Laravel-style public/hot) and hashed production builds.
  • 🖥️ SSR with an automatic CSR fallback when the SSR server is unreachable (no blank pages).
  • 💬 Flash & validation bridged from Goravel's session into props.flash / props.errors.
  • 🔁 Inertia-aware redirects (303 on mutating methods) and external Location redirects.
  • 🏷️ Asset versioning auto-derived from the Vite manifest hash for cache busting.
  • 🛠️ inertia:install artisan command that scaffolds a full demo app — Vue 3 or React.

Requirements

  • Go 1.26+
  • Goravel v1.18+ (for Goravel v1.17 use v0.3.x of this package)
  • Node 18+ (for the Vite frontend)

Installation

Install the package and register its service provider automatically:

go run . artisan package:install github.com/goravel/inertia

This runs the package's setup, which adds &goravelinertia.ServiceProvider{} to bootstrap/providers.go (or config/app.go on a non-bootstrap setup) for you.

Manual registration
go get github.com/goravel/inertia
import goravelinertia "github.com/goravel/inertia"

var Providers = []foundation.ServiceProvider{
    // ...
    &goravelinertia.ServiceProvider{},
}

Then scaffold the frontend, config, root template and a demo app. Pick a stack with --stack (vue is the default):

go run . artisan inertia:install                 # Vue 3 (default)
go run . artisan inertia:install --stack=react   # React 19

This creates config/inertia.go, resources/inertia/app.gohtml, the JS app under resources/js/, demo pages (Home / Feed / Contact / About) with their controllers, the app/http/middleware/handle_inertia_requests.go middleware (your shared-props entry point), vite.config.ts, tsconfig.json and package.json. It also wires routes/web.go (session + HandleInertiaRequests middleware, demo routes) and removes the default Goravel welcome view. Pass --force to overwrite existing files.

The Go controllers, middleware, routes and config are identical across stacks — only the resources/js/ frontend (.vue vs .tsx) and the JS toolchain (package.json / vite.config.ts) differ.

Finally:

npm install
npm run dev   # writes public/hot, then in another shell:
go run .

Open http://localhost:3000.

Configuration

config/inertia.go:

Key Env Default Description
root_view resources/inertia/app.gohtml Root Blade-like template.
version INERTIA_VERSION manifest hash Asset version for the version check.
ssr INERTIA_SSR false Enable server-side rendering.
ssr_url INERTIA_SSR_URL http://127.0.0.1:13714/render SSR Node endpoint.
ssr_timeout INERTIA_SSR_TIMEOUT 5 Seconds before SSR is abandoned for CSR.
flash_keys success,error,warning,info,message Session keys mirrored into props.flash.
vite.public_path public Public web root served to clients.
vite.build_dir build Production build dir under public_path.
vite.hot_file public/hot Hot file written by npm run dev.
vite.dev_url VITE_DEV_URL `` Dev-server URL (usually set via public/hot).

Usage

Access the manager via the facade:

import "github.com/goravel/inertia/facades"

Render

return facades.Inertia().Render(ctx, "Users/Index", map[string]any{"users": users})

Shared props

Shared props are sent on every Inertia response. This adapter offers a hybrid model — pick by lifecycle:

Mechanism Where Lifecycle Use for
share() middleware app/http/middleware/handle_inertia_requests.go Per-request (ctx-aware) Auth user, anything request-dependent. Recommended default.
Inertia().ShareFunc(key, fn) Provider Boot Per-request (ctx-aware) Same as above, but registered from a provider/package instead of the app middleware.
Inertia().Share(key, value) Provider Boot Static, set once Constants known at boot (app name, build info). No request access.

The underlying petaki/inertia-go engine only provides the static Share(key, value). The per-request pieces — HandleInertiaRequests and ShareFunc — are added by this adapter so shared props can read the request (e.g. the authenticated user), the Go analogue of Laravel's HandleInertiaRequests::share().

1. Per-request via the middleware (recommended). inertia:install scaffolds handle_inertia_requests.go; its share() runs once per request and you own it:

// app/http/middleware/handle_inertia_requests.go
func share(ctx http.Context) map[string]any {
    return map[string]any{
        "appName": facades.Config().GetString("app.name"),
        "auth": map[string]any{
            "user": authUser(ctx),
        },
    }
}

Validation errors and session flash are shared by the package automatically — you only own share(). Internally each entry is applied as a per-request prop.

2. From a provider via the facade. Useful when a provider or reusable package must contribute shared props without touching the app middleware. Share is static; ShareFunc is resolved per request from the context:

facades.Inertia().Share("appName", "My App")          // static, set once
facades.Inertia().ShareFunc("user", func(ctx http.Context) any { // per-request
    if !ctx.Request().HasSession() {
        return nil
    }
    return ctx.Request().Session().Get("user")
})

Inertia here is session-based: persist the user with ctx.Request().Session().Put("user", user) at login and ctx.Request().Session().Forget("user") at logout.

Inertia v3 props

Method Behaviour
Defer(ctx, key, fn, group...) Loaded after the initial render (<Deferred>).
Optional(ctx, key, fn) Only evaluated on partial reloads.
Always(ctx, key, fn) Always present, even on partial reloads.
Merge(ctx, key, fn, matchOn...) Client shallow-merges (e.g. pagination "load more").
DeepMerge(ctx, key, fn, matchOn...) Client deep-merges.
Prepend(ctx, key, fn, matchOn...) Merge, prepending new values.
Scroll(ctx, key, prop) Infinite-scroll / pagination metadata.
Once(ctx, key, fn) Sent once, then cached client-side.
Prop(ctx, key, value) Eager per-request prop.
PreserveFragment(ctx) Keep the URL fragment (#hash) across the visit.
func (c *HomeController) Index(ctx http.Context) http.Response {
    facades.Inertia().Defer(ctx, "stats", func() any { return loadStats() })
    return facades.Inertia().Render(ctx, "Home", nil)
}

Flash & validation

The middleware mirrors session flash and validation errors into props (props.flash, props.errors) automatically. On a failed validation, flash the errors and redirect back:

func (c *ContactController) Store(ctx http.Context) http.Response {
    validator, err := ctx.Request().Validate(map[string]any{
        "email": "required|email",
    })
    if err != nil || validator.Fails() {
        facades.Inertia().FlashErrors(ctx, validator.Errors())
        return facades.Inertia().Redirect(ctx, "/contact")
    }

    ctx.Request().Session().Flash("success", "Saved!")
    return facades.Inertia().Redirect(ctx, "/contact")
}

On the client: usePage().props.flash and usePage().props.errors (or useForm).

You can also push props imperatively: Flash(ctx, data) merges a map into props.flash, and Error(ctx, key, value) adds a single validation error.

Redirects

facades.Inertia().Redirect(ctx, "/dashboard")          // 303 on PUT/PATCH/DELETE, 302 otherwise
facades.Inertia().Location(ctx, "https://example.com") // full-page / external redirect

History

facades.Inertia().ClearHistory(ctx)
facades.Inertia().EncryptHistory(ctx)

Frontend (Vite)

  • Development: npm run dev runs Vite and writes public/hot; the backend loads assets from the dev server with HMR — no env var needed.
  • Production: npm run build emits hashed assets + a manifest under public/build; the backend serves them via the manifest. The asset version is derived from the manifest hash, so a new build busts the client cache.

The {{ vite "resources/js/app.ts" }} template helper picks dev vs prod automatically (public/hotVITE_DEV_URL → manifest).

SSR

npm run build:ssr          # client build + SSR bundle (bootstrap/ssr/ssr.js)
npm run ssr                # SSR Node server on :13714 (keeps running, in its own shell)

Then, in another shell:

INERTIA_SSR=true go run .

If the SSR server is unreachable, the adapter falls back to client-side rendering instead of returning a blank page (a warning is logged).

Credits

Built on the shoulders of:

  • Inertia.js — the protocol & client (MIT).
  • petaki/inertia-go — the Go server engine (MIT).
  • Goravel — the Go web framework (MIT).
  • Vue & React — the scaffolded frontend stacks (MIT).
  • Vite — dev server & production builds (MIT).

Attribution

The logo features the Go gopher, designed by Renée French and licensed under CC BY 3.0. It also incorporates the Inertia.js and Goravel marks to identify the projects this adapter integrates; those marks belong to their respective owners and are used here only for identification, not endorsement.

License

Code is released under the MIT License. Third-party dependencies keep their own licenses (MIT / BSD / Apache-2.0) — see THIRD_PARTY_NOTICES.md.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Adapter

type Adapter struct {
	// contains filtered or unexported fields
}

func NewAdapter

func NewAdapter(inertia *inertia.Inertia) *Adapter

func (*Adapter) CSR

func (a *Adapter) CSR() *inertia.Inertia

CSR returns the SSR-disabled fallback engine, or nil when SSR is off. It is set once at boot and read-only afterwards.

func (*Adapter) Inertia

func (a *Adapter) Inertia() *inertia.Inertia

func (*Adapter) Request

func (a *Adapter) Request(ctx contractshttp.Context) *stdhttp.Request

func (*Adapter) SetCSR

func (a *Adapter) SetCSR(i *inertia.Inertia)

SetCSR registers the SSR-disabled fallback engine used when an SSR render fails.

func (*Adapter) Writer

type InertiaManager

type InertiaManager struct {
	// contains filtered or unexported fields
}

InertiaManager is the Goravel-facing implementation of the Inertia protocol, adapting Goravel's http.Context to the underlying petaki/inertia-go engine.

func NewInertiaManager

func NewInertiaManager(adapter *Adapter, url string, version string, flashKeys ...string) *InertiaManager

NewInertiaManager builds a manager. flashKeys overrides the session keys mirrored into props.flash; when omitted it falls back to defaultFlashKeys.

func (*InertiaManager) Always

func (m *InertiaManager) Always(ctx contractshttp.Context, key string, fn func() any)

Always registers a prop included on every response, even on partial reloads.

func (*InertiaManager) ClearHistory

func (m *InertiaManager) ClearHistory(ctx contractshttp.Context)

ClearHistory instructs the client to clear its history state.

func (*InertiaManager) DeepMerge

func (m *InertiaManager) DeepMerge(ctx contractshttp.Context, key string, fn func() any, matchOn ...string)

DeepMerge registers a prop the client deep-merges with existing data.

func (*InertiaManager) Defer

func (m *InertiaManager) Defer(ctx contractshttp.Context, key string, fn func() any, group ...string)

Defer registers a prop evaluated lazily by the client after the initial load.

func (*InertiaManager) EncryptHistory

func (m *InertiaManager) EncryptHistory(ctx contractshttp.Context)

EncryptHistory instructs the client to encrypt its history state.

func (*InertiaManager) Error

func (m *InertiaManager) Error(ctx contractshttp.Context, key string, value any)

Error attaches a single validation error to the response.

func (*InertiaManager) Flash

func (m *InertiaManager) Flash(ctx contractshttp.Context, data map[string]any)

Flash attaches flash data under props.flash, matching the Inertia + Laravel convention where flash is a shared prop read via usePage().props.flash. This keeps flash consistent with props.errors instead of petaki's top-level page.flash.

func (*InertiaManager) FlashErrors

func (m *InertiaManager) FlashErrors(ctx contractshttp.Context, errors validation.Errors)

FlashErrors flattens Goravel validation errors to one message per field and flashes them to the session. Call it before redirecting back from a failed validation; ShareSession then exposes them as props.errors on the next request.

func (*InertiaManager) GetAdapter

func (m *InertiaManager) GetAdapter() *Adapter

GetAdapter returns the underlying Goravel-to-petaki adapter.

func (*InertiaManager) Location

Location performs a full-page redirect to an external URL via the Inertia protocol (409 + X-Inertia-Location for Inertia requests, 302 otherwise).

func (*InertiaManager) Merge

func (m *InertiaManager) Merge(ctx contractshttp.Context, key string, fn func() any, matchOn ...string)

Merge registers a prop the client shallow-merges with existing data.

func (*InertiaManager) Once

func (m *InertiaManager) Once(ctx contractshttp.Context, key string, fn func() any)

Once registers a prop sent only once and then cached by the client.

func (*InertiaManager) Optional

func (m *InertiaManager) Optional(ctx contractshttp.Context, key string, fn func() any)

Optional registers a prop only evaluated when explicitly requested (partial reload).

func (*InertiaManager) Prepend

func (m *InertiaManager) Prepend(ctx contractshttp.Context, key string, fn func() any, matchOn ...string)

Prepend registers a merge prop whose values are prepended instead of appended.

func (*InertiaManager) PreserveFragment

func (m *InertiaManager) PreserveFragment(ctx contractshttp.Context)

PreserveFragment keeps the URL fragment across the visit.

func (*InertiaManager) Prop

func (m *InertiaManager) Prop(ctx contractshttp.Context, key string, value any)

Prop sets an eagerly-evaluated per-request prop.

func (*InertiaManager) Redirect

Redirect issues an Inertia-aware internal redirect, picking 303 for mutating requests so the client re-fetches the target with a GET.

func (*InertiaManager) Render

func (m *InertiaManager) Render(ctx contractshttp.Context, component string, props map[string]any) contractshttp.Response

Render returns a response that renders the given component with props, merging shared props and threading any per-request v3 props from the context.

func (*InertiaManager) Scroll

func (m *InertiaManager) Scroll(ctx contractshttp.Context, key string, prop contracts.ScrollProp)

Scroll registers an infinite-scroll/pagination prop.

func (*InertiaManager) Share

func (m *InertiaManager) Share(key string, value any)

Share registers a prop included on every Inertia response for all requests. It fans out to the CSR fallback engine too so fallback renders carry the same shared props.

func (*InertiaManager) ShareFunc

func (m *InertiaManager) ShareFunc(key string, fn func(contractshttp.Context) any)

ShareFunc registers a shared prop resolved per request from the context.

func (*InertiaManager) ShareSession

func (m *InertiaManager) ShareSession(ctx contractshttp.Context)

ShareSession mirrors flash messages and validation errors stored in the session into the Inertia props for this request. It runs in the middleware before the handler, so both the initial HTML load and X-Inertia visits pick them up: props.flash for the configured flash keys, props.errors for validation errors.

func (*InertiaManager) URL

func (m *InertiaManager) URL() string

URL returns the configured application base URL.

func (*InertiaManager) Version

func (m *InertiaManager) Version() string

Version returns the configured asset version used for the version check.

type ServiceProvider

type ServiceProvider struct {
}

ServiceProvider registers and boots the Inertia singleton and facade.

Registered in a Goravel application via package:install (which wires it into bootstrap/providers.go automatically) or manually:

import goravelinertia "github.com/goravel/inertia"
&goravelinertia.ServiceProvider{}

func (*ServiceProvider) Boot

func (p *ServiceProvider) Boot(app foundation.Application)

Boot resolves the manager, registers default shared props, and exposes the facade.

func (*ServiceProvider) Register

func (p *ServiceProvider) Register(app foundation.Application)

Register binds the Inertia manager as the "goravel.inertia" singleton.

type Vite

type Vite struct {
	// contains filtered or unexported fields
}

Vite resolves asset tags for Inertia's root template, mirroring the Laravel @vite directive: it serves assets from the running dev server when one is active, otherwise from the hashed files listed in the build manifest.

func NewVite

func NewVite(publicPath, buildDir, hotFile, devURL string) *Vite

NewVite builds a Vite helper. Empty arguments fall back to Laravel-compatible defaults: publicPath "public", buildDir "build", hotFile "public/hot".

func (*Vite) Render

func (v *Vite) Render(entries ...string) template.HTML

Render produces the <script>/<link> tags for the given entry points.

func (*Vite) TemplateFunc

func (v *Vite) TemplateFunc() func(entries ...string) template.HTML

TemplateFunc returns the function registered as {{ vite "entry" ... }}.

func (*Vite) Version

func (v *Vite) Version() string

Version returns an asset version derived from the build manifest (its md5 hash), or "" when no manifest exists (e.g. during development). The hash changes whenever the built assets change, so it works as a cache-busting version.

Directories

Path Synopsis
Package console provides the artisan commands shipped with goravel-inertia.
Package console provides the artisan commands shipped with goravel-inertia.
Command setup wires goravel-inertia into a Goravel application when installed via `./artisan package:install github.com/goravel/inertia`.
Command setup wires goravel-inertia into a Goravel application when installed via `./artisan package:install github.com/goravel/inertia`.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL