An open API service indexing awesome lists of open source software.

https://github.com/petaki/inertia-go

⏩ Inertia.js server-side adapter for Go.
https://github.com/petaki/inertia-go

go golang inertiajs

Last synced: 3 months ago
JSON representation

⏩ Inertia.js server-side adapter for Go.

Awesome Lists containing this project

README

          

Inertia GO

# Inertia.js Go Adapter

[![Build Status](https://github.com/petaki/inertia-go/workflows/tests/badge.svg)](https://github.com/petaki/inertia-go/actions)
[![License: MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg)](LICENSE.md)

An Inertia.js server-side adapter for Go. Visit [inertiajs.com](https://inertiajs.com) to learn more.

## Installation

Install the package using the `go get` command:

```
go get github.com/petaki/inertia-go
```

## Usage

### 1. Create new instance

```go
url := "http://inertia-app.test" // Application URL for redirect
rootTemplate := "./app.gohtml" // Root template, see the example below
version := "" // Asset version

inertiaManager := inertia.New(url, rootTemplate, version)
```

Or create with `embed.FS` for root template:

```go
import "embed"

//go:embed template
var templateFS embed.FS

// ...

inertiaManager := inertia.New(url, rootTemplate, version, templateFS)
```

### 2. Register the middleware

```go
mux := http.NewServeMux()
mux.Handle("/", inertiaManager.Middleware(homeHandler))
```

### 3. Render in handlers

```go
func homeHandler(w http.ResponseWriter, r *http.Request) {
// ...

err := inertiaManager.Render(w, r, "home/Index", nil)
if err != nil {
// Handle server error...
}
}
```

Or render with props:

```go
// ...

err := inertiaManager.Render(w, r, "home/Index", map[string]any{
"total": 32,
})

//...
```

### 4. Server-side Rendering (Optional)

First, enable SSR with the url of the Node server:

```go
inertiaManager.EnableSsrWithDefault() // http://127.0.0.1:13714/render
```

Or with custom url:

```go
inertiaManager.EnableSsr("http://ssr-host:13714/render")
```

Or with the Vite dev server:

```go
inertiaManager.EnableSsr("http://localhost:5173/__inertia_ssr")
```

You can also provide a custom `*http.Client`:

```go
client := &http.Client{
Timeout: 10 * time.Second,
}

inertiaManager.EnableSsr("http://ssr-host:13714/render", client)
inertiaManager.EnableSsrWithDefault(client)
```

For more information, please read the official Server-side Rendering documentation on [inertiajs.com](https://inertiajs.com).

## Props

| Prop Type | Method(s) | Evaluation | Full | Partial |
|-----------|-----------|------------|------|---------|
| Base | `Share`, `WithProp`, `Render` | Eager | ✅ | ✅ if requested |
| Optional | `WithOptionalProp` | Lazy | ❌ | ✅ if requested |
| Always | `WithAlwaysProp` | Lazy | ✅ | ✅ always |
| Deferred | `WithDeferredProp` | Lazy | ❌ deferred | ✅ if requested |
| Merge | `WithMergeProp` | Lazy | ✅ | ✅ if requested |
| Deep Merge | `WithDeepMergeProp` | Lazy | ✅ | ✅ if requested |
| Prepend | `WithPrependProp` | Lazy | ✅ | ✅ if requested |
| Scroll | `WithScrollProp` | — | ✅ metadata | ✅ metadata |
| Once | `WithOnceProp`, `WithOnce` | Lazy | ✅ | ❌ if in except-once |
| Flash | `WithFlashProp` | Eager | ✅ | ✅ |

`WithOnce` can be combined with Deferred, Merge, Deep Merge, Prepend, and Optional props.
`WithScrollProp` adds scroll metadata to the page response for infinite scroll support.

## Examples

The following examples show how to use the package.

### Share a function with root template (globally)

```go
inertiaManager.ShareFunc("asset", assetFunc)
```

```html

```

### Share data with root template (globally)

```go
inertiaManager.ShareViewData("env", "production")
```

```html
{{ if eq .env "production" }}
...
{{ end }}
```

### Share data with root template (context based)

```go
ctx := inertiaManager.WithViewData(r.Context(), "meta", meta)
r = r.WithContext(ctx)
```

```html

```

### Share a prop (globally)

```go
inertiaManager.Share("title", "Inertia App Title")
```

### Share a prop (context based)

```go
func authenticate(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// ...

ctx := inertiaManager.WithProp(r.Context(), "authUserID", user.ID)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
```

### Optional prop (context based)

```go
ctx := inertiaManager.WithOptionalProp(r.Context(), "extra", func() any {
return getExtra()
})
r = r.WithContext(ctx)
```

### Always prop (context based)

```go
ctx := inertiaManager.WithAlwaysProp(r.Context(), "errors", func() any {
return getErrors()
})
r = r.WithContext(ctx)
```

### Deferred prop (context based)

```go
ctx := inertiaManager.WithDeferredProp(r.Context(), "comments", func() any {
return getComments()
})
r = r.WithContext(ctx)
```

### Deferred prop with group (context based)

```go
ctx := inertiaManager.WithDeferredProp(r.Context(), "comments", func() any {
return getComments()
}, "my-group")
r = r.WithContext(ctx)
```

### Merge prop (context based)

```go
ctx := inertiaManager.WithMergeProp(r.Context(), "results", func() any {
return getResults()
})
r = r.WithContext(ctx)
```

Or with match on:

```go
ctx := inertiaManager.WithMergeProp(r.Context(), "results", func() any {
return getResults()
}, "id")
r = r.WithContext(ctx)
```

Or with multiple nested match on paths:

```go
ctx := inertiaManager.WithMergeProp(r.Context(), "complexData", func() any {
return getComplexData()
}, "users.data.id", "messages.uuid")
r = r.WithContext(ctx)
```

### Deep merge prop (context based)

```go
ctx := inertiaManager.WithDeepMergeProp(r.Context(), "settings", func() any {
return getSettings()
})
r = r.WithContext(ctx)
```

Or with match on:

```go
ctx := inertiaManager.WithDeepMergeProp(r.Context(), "settings", func() any {
return getSettings()
}, "id")
r = r.WithContext(ctx)
```

### Prepend prop (context based)

```go
ctx := inertiaManager.WithPrependProp(r.Context(), "notifications", func() any {
return getNotifications()
})
r = r.WithContext(ctx)
```

Or with match on:

```go
ctx := inertiaManager.WithPrependProp(r.Context(), "notifications", func() any {
return getNotifications()
}, "id")
r = r.WithContext(ctx)
```

### Scroll prop (context based)

```go
ctx := inertiaManager.WithScrollProp(r.Context(), "items", inertia.ScrollPageProp{
PageName: "page",
CurrentPage: 1,
NextPage: 2,
})
r = r.WithContext(ctx)
```

### Once prop (context based)

```go
ctx := inertiaManager.WithOnceProp(r.Context(), "plans", func() any {
return getPlans()
})
r = r.WithContext(ctx)
```

### Once modifier (context based)

```go
ctx := inertiaManager.WithMergeProp(r.Context(), "activity", func() any {
return getActivity()
})
ctx = inertiaManager.WithOnce(ctx, "activity")
r = r.WithContext(ctx)
```

Or with expiration:

```go
expiresAt := time.Now().Add(24 * time.Hour).UnixMilli()
ctx := inertiaManager.WithDeferredProp(r.Context(), "permissions", func() any {
return getPermissions()
})
ctx = inertiaManager.WithOnce(ctx, "permissions", inertia.OncePageProp{ExpiresAt: &expiresAt})
r = r.WithContext(ctx)
```

### Flash prop (context based)

```go
ctx := inertiaManager.WithFlashProp(r.Context(), map[string]any{
"success": "Item created successfully",
})
r = r.WithContext(ctx)
```

### Clear history (context based)

```go
ctx := inertiaManager.WithClearHistory(r.Context())
r = r.WithContext(ctx)
```

### Encrypt history (context based)

```go
ctx := inertiaManager.WithEncryptHistory(r.Context())
r = r.WithContext(ctx)
```

### Root template

```html








{{ marshal .page }}



```

### Root template with Server-side Rendering (SSR)

```html






{{ if .ssr }}
{{ raw .ssr.Head }}
{{ end }}


{{ if not .ssr }}
{{ marshal .page }}


{{ else }}
{{ raw .ssr.Body }}
{{ end }}

```

## Example Apps

### Satellite

Vite Vite /
Vue3 Vue3

https://github.com/petaki/satellite

### Homettp

Vite Vite /
Vue3 Vue3

https://github.com/homettp/homettp

### Waterkube

Vite Vite /
Vue3 Vue3

https://github.com/waterkube/waterkube

## Contributors

- [@monstergron](https://github.com/monstergron) for logo ([ArtStation](https://www.artstation.com/danielmakaro))

## Reporting Issues

If you are facing a problem with this package or found any bug, please open an issue on [GitHub](https://github.com/petaki/inertia-go/issues).

## License

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.