Gonertia
The Go adapter for Inertia.js
Install / Use
/learn @romsar/GonertiaREADME
Gonertia
<img src="https://user-images.githubusercontent.com/27378369/215432769-35e7b0f5-29a9-41d0-ba79-ca81e624b970.png" style="width: 200px" alt="gonertia"/>Gonertia is a well-tested and zero-dependency Inertia.js server-side adapter for Golang. Visit inertiajs.com to learn more.
Introduction
Inertia allows you to create fully client-side rendered single-page apps without the complexity that comes with modern SPAs. It does this by leveraging existing server-side patterns that you already love.
This package based on the official Laravel adapter for Inertia.js inertiajs/inertia-laravel, supports all the features and works in the most similar way.
Roadmap
- [x] Tests
- [x] Helpers for testing
- [x] Helpers for validation errors
- [x] Examples
- [x] SSR
- [x] Inertia 2.0 compatibility
Installation
Install using go get command:
go get github.com/romsar/gonertia/v2
Usage
Basic example
Initialize Gonertia in your main.go:
package main
import (
"log"
"net/http"
inertia "github.com/romsar/gonertia"
)
func main() {
i, err := inertia.New(rootHTMLString)
// i, err := inertia.NewFromFile("resources/views/root.html")
// i, err := inertia.NewFromFileFS(embedFS, "resources/views/root.html")
// i, err := inertia.NewFromReader(rootHTMLReader)
// i, err := inertia.NewFromBytes(rootHTMLBytes)
if err != nil {
log.Fatal(err)
}
// Now create your HTTP server.
// Gonertia works well with standard http server library,
// but you are free to use some external routers like Gorilla Mux or Chi.
mux := http.NewServeMux()
mux.Handle("/home", i.Middleware(homeHandler(i)))
}
func homeHandler(i *inertia.Inertia) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
err := i.Render(w, r, "Home/Index", inertia.Props{
"some": "data",
})
if err != nil {
handleServerErr(w, err)
return
}
}
return http.HandlerFunc(fn)
}
Create root.html template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Put here your styles, meta and other stuff -->
{{ .inertiaHead }}
</head>
<body>
{{ .inertia }}
<script type="module" src="/build/assets/app.js"></script>
</body>
</html>
Starter kits
- Gonertia + Vue + Vite + Tailwind
- Gonertia + Svelte + Vite + Tailwind
- Gonertia + React + Vite + Tailwind
- Also you can use Alpacaproj project generator
More examples
Set asset version (learn more)
i, err := inertia.New(
/* ... */
inertia.WithVersion("some-version"), // by any string
inertia.WithVersionFromFile("./public/build/manifest.json"), // by file checksum
inertia.WithVersionFromFileFS(embedFS, "./public/build/manifest.json"), // by file checksum from fs.FS
)
SSR (Server Side Rendering) (learn more)
To enable server side rendering you have to provide an option in place where you initialize Gonertia:
i, err := inertia.New(
/* ... */
inertia.WithSSR(), // default is http://127.0.0.1:13714
inertia.WithSSR("http://127.0.0.1:1234"), // custom url http://127.0.0.1:1234
)
Also, you have to use asset bundling tools like Vite or Webpack (especially with Laravel Mix). The setup will vary depending on this choice, you can read more about it in official docs or check an example that works on Vite.
Optional and Always props (learn more)
props := inertia.Props{
"optional": inertia.Optional{func () (any, error) {
return "prop", nil
}},
"always": inertia.Always("prop"),
}
i.Render(w, r, "Some/Page", props)
Merging props (learn more)
props := inertia.Props{
"merging": inertia.Merge([]int{rand.Int63()}),
}
Deferred props (learn more)
props := inertia.Props{
"defer_with_default_group": inertia.Defer(func () (any, error) {
return "prop", nil
}),
"defer_with_custom_group": inertia.Defer("prop", "foobar"),
"defer_with_merging": inertia.Defer([]int64{rand.Int63()}).Merge(),
}
Once props (learn more)
Gonertia supports light version of Once props (feel free to send a pr with support of other features).
props := inertia.Props{
"foo": inertia.Once("bar"),
}
Infinite scrolling (learn more)
props := inertia.Props{
// Basic scroll prop (defaults to "data" wrapper)
"items": inertia.Scroll(items),
// Scroll prop with custom wrapper
"results": inertia.Scroll(items, inertia.WithWrapper("results")),
// Scroll prop with pagination metadata
"posts": inertia.Scroll(posts, inertia.WithMetadata(inertia.ScrollMetadata{
PageName: "page",
PreviousPage: 1,
NextPage: 3,
CurrentPage: 2,
})),
// Scroll prop with metadata function (extracts metadata from your data structure)
"articles": inertia.Scroll(paginatedData, inertia.WithMetadataFunc(
func(data PaginatedData) inertia.ProvidesScrollMetadata {
return inertia.ScrollMetadata{
PageName: "page",
CurrentPage: data.CurrentPage,
NextPage: data.NextPage,
PreviousPage: data.PrevPage,
}
},
)),
}
Redirects (learn more)
i.Redirect(w, r, "https://example.com") // plain redirect
i.Location(w, r, "https://example.com") // external redirect
NOTES: If response is empty - user will be redirected to the previous url, just like in Laravel official adapter.
To manually redirect back, you can use Back helper:
i.Back(w, r)
Share template data (learn more)
i.ShareTemplateData("title", "Home page")
<h1>{{ .title }}</h1>
Share template func
i.ShareTemplateFunc("trim", strings.TrimSpace)
<h1>{{ trim " foo bar " }}</h1>
Pass template data via context (in middleware)
ctx := inertia.SetTemplateData(r.Context(), inertia.TemplateData{"foo", "bar"})
// or inertia.SetTemplateDatum(r.Context(), "foo", "bar")
// pass it to the next middleware or inertia.Render function using r.WithContext(ctx).
Share prop globally (learn more)
i.ShareProp("foo", "bar")
Pass props via context (in middleware)
ctx := inertia.SetProps(r.Context(), inertia.Props{"foo": "bar"})
// or inertia.SetProp(r.Context(), "foo", "bar")
// pass it to the next middleware or inertia.Render function using r.WithContext(ctx).
Validation errors (learn more)
ctx := inertia.SetValidationErrors(r.Context(), inertia.ValidationErrors{"some_field": "some error"})
// or inertia.AddValidationErrors(r.Context(), inertia.ValidationErrors{"some_field": "some error"})
// or inertia.SetValidationError(r.Context(), "some_field", "some error")
// pass it to the next middleware or inertia.Render function using r.WithContext(ctx).
Replace standard JSON marshaller
- Implement JSONMarshaller interface:
import jsoniter "github.com/json-iterator/go"
type jsonIteratorMarshaller struct{}
func (j jsonIteratorMarshaller) Decode(r io.Reader, v any) error {
return jsoniter.NewDecoder(r).Decode(v)
}
func (j jsonIteratorMarshaller) Marshal(v any) ([]byte, error) {
return jsoniter.Marshal(v)
}
- Provide your implementation in constructor:
i, err := inertia.New(
/* ... */,
inertia.WithJSONMarshaller(jsonIteratorMarshaller{}),
)
Use your logger
i, err := inertia.New(
/* ... */
inertia.WithLogger(), // default logger
// inertia.WithLogger(somelogger.New()),
)
Set custom container id
i, err := inertia.New(
/* ... */
inertia.WithContainerID("inertia"),
)
Set flash provider
Unfortunately (or fortunately) we do not have the advantages of such a framework as Laravel in terms of session management. In this regard, we have to do some things manually that are done automatically in frameworks.
One of them is displaying validation errors after redirects.
You have to write your own implementation of gonertia.FlashProvider which will have to store error data into the user's session and return this data (you can get the session ID from the c
Related Skills
node-connect
350.8kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
xurl
350.8kA CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.
frontend-design
110.4kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
350.8kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
