golte
is a library for Go that allows you to render Svelte components in your http handlers, supporting SSR+hydration capabilities without requiring NodeJS.
- SSR + Hydration
- NodeJS not required in production
- Layouts as middleware (they can be nested)
- Custom error pages
- Works with Go stdlib,
gorilla/mux
,chi
,gin
,echo
, or any router that allows access to the underlyinghttp.ResponseWriter
and*http.Request
- Can compile to single, self-contained executable
-
Svelte source files are first compiled to client and server JavaScript code (requires NodeJS during development only).
-
The generated code is embedded using Go's
embed
package. A middleware is created from this which can then be registered in your router. -
From there, functions like
golte.RenderPage
andgolte.AddLayout
can be called to render components. -
After running
go build
, the end result is a single binary that houses a full web app, with complete support for SSR and hydration.
Make sure Go and NodeJS are installed (NodeJS is only needed during development).
Initialize go.mod and package.json if not done so already:
go mod init <projectname>
npm init
Set {"type": "module"}
in package.json
.
Install Golte:
go get github.com/nichady/golte@latest
npm install golte@latest
# Make sure that the Go module and npm package are the same version.
Suppose we have the following file structure:
web/
page/
home.svelte
about.svelte
contact.svelte
login.svelte
profile.svelte
layout/
main.svelte
app.html
main.go
...(any other files)
We can run npx golte
to generate a build/
directory.
By default, Golte will use web/app.html
as the template file and search for .svelte
files inside the web/
directory (this can be changed in the config file).
Each .svelte
file will be able to be rendered inside Go code by name. The name of the components are path of the file relative to the source directory (web/
), without the file extension.
For example:
web/page/home.svelte
=>page/home
web/layout/main.svelte
=>layout/main
- etc...
Suppose we want to make a program with the following requirements:
- Five routes:
/
,/about
,/contact
,/login
, and/profile
. /
,/about
, and/contact
will have a layout;/login
, and/profile
will not./profile
will have props passed to it, which can be accessed with "export let".
This is what main.go
would look like, using chi
as the router:
package main
import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/nichady/golte"
"example/build" // this package will be generated by golte
)
func main() {
r := chi.NewRouter()
// register the main Golte middleware
r.Use(build.Golte)
r.Group(func(r chi.Router) {
r.Use(golte.Layout("layout/main"))
// these routes will have a layout
r.Get("/", golte.Page("page/home"))
r.Get("/about", golte.Page("page/about"))
r.Get("/contact", golte.Page("page/contact"))
})
r.Get("/login", golte.Page("page/login"))
// this route will have props passed to it
r.Get("/profile", func(w http.ResponseWriter, r *http.Request) {
username := "john123"
age := 22
golte.RenderPage(w, r, "page/profile", map[string]any{
"username": username,
"age": age,
})
})
http.ListenAndServe(":8000", r)
}
For more comprehensive examples using other routers, passing props, and nesting layouts, see _examples.
For a list of all the possible functions, see the package docs.
The build process of golte
can be configured to change things like the source or build directory.
Golte will recognize one of the following files in the root directory of your project:
golte.config.js
golte.config.mjs
golte.config.ts
golte.config.mts
Here is an example for golte.config.ts
:
import { Config } from "golte/config"
export default {
template: "web/template.html",
srcDir: "web/components/",
outDir: "dist/",
} satisfies Config;
For all of the possible configuration options, see golte/config
.
Note: You must set {"type": "module"}
in your package.json
for config file to work.
If you wish to use TypeScript or other preprocessors in your Svelte files, you can add a normal svelte.config.js
file to your project root.
The golte
npm package provides some exports that you can use in your components:
import { preload } from "golte";
<a href="route1" use:preload>Route1</a>
<a href="route2" use:preload={"mount"}>Route2</a>
preload
- a Svelte action that can be used in <a>
tags. Using this turns the <a>
into a Golte link, stopping the page from reloading when clicked.
import { url } from "golte/stores";
<p>The current url is {$url.href}</p>
url
- a Svelte store that describes the current URL of the page
I wanted a way to create web apps in Svelte while using Go as the backend language to create a single, self-contained binary. One option would be to embed a Svelte SPA into a Go binary. However, that solution lacks SSR capabilities and won't work when JavaScript is disabled.
I discovered Bud, but it forces you to structure your project in a specific way rather than treating your program as a normal Go app with a main() function and your own router. It also requires you to install their own cli. It also doesn't support layouts (I think).
There is also Inertia.js, but it requires NodeJS for SSR, and I don't like how layouts need to specified inside the page components.
So, I created Golte to solve these problems.