SSR adapter. So we will use use Go templates to inject dynamic content in your Astro projects by serving the static files generated by Astro with a Go server.
It doesn’t even have to be Astro - any static site generator will work - but we will focus on Astro in this article as it’s our favorite.
Before you begin, make sure you have the following prerequisites:
Initialize a new Go project:
go mod init github.com/wingravity/go-astro
Create a new Go file named main.go
:
package main
import (
"log"
"net/http"
)
func main() {
app := NewRouter()
tmp := NewTemplatesHandler()
app.mux.Handle("GET /", http.HandlerFunc(tmp.IndexView))
log.Fatal(app.ListenAndServe(":8080"))
}
Here we have a simple Go program that initializes a new router and a templates handler.
The router listens on port 8080.
Let’s create the router and templates handler in a new Go file named router.go
:
package main
import (
"net/http"
"text/template"
)
type Router struct {
mux *http.ServeMux
}
func NewRouter() *Router {
return &Router{
mux: http.NewServeMux(),
}
}
func (r *Router) ListenAndServe(address string) error {
return http.ListenAndServe(address, r.mux)
}
type ViewsHandler struct {
Index *template.Template
}
func NewTemplatesHandler() *ViewsHandler {
return &ViewsHandler{
// IMPORTANT: We specify custom delimiters for Go templates,
// so they don't conflict with Astro's delimiters {{ and }}
Index: template.Must(template.New("index").Delims("[[", "]]").ParseFiles("client/dist/index.html")),
}
}
type IndexParams struct {
Name string
}
func (h *ViewsHandler) IndexView(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
h.Index.ExecuteTemplate(w, "index.html", IndexParams{Name: "Go Astro"})
return
}
http.ServeFile(w, r, "client/dist"+r.URL.Path)
}
The IndexView
method in the ViewsHandler
struct renders the index.html
template with the name “Go Astro”. Here, we can inject dynamic content into the Astro-generated static files. This can be any data you want to pass to the template.
We also specify custom delimiters for Go templates so they don’t conflict with Astro’s delimiters.
Now let’s add the client files generated by Astro to the project. Let’s initialize a new Astro project:
npm create astro@latest
Put the Astro project in the client
directory:
Respond to the other questions as you see fit.
What we’re interested in is the index page, as this is the one we will be injecting dynamic content into.
Create a new file named index.astro
under client/src/pages and add the following content (you can remove the existing content):
---
import { Image } from "astro:assets";
import logo from "../astro-logo-dark.png";
---
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} />
<title>Astro</title>
</head>
<body>
<Image src={logo} alt="LOGO" width={200} />
<!-- This is where the dynamic content will be injected. -->
<h1>Hello [[.Name]]</h1>
</body>
</html>
There are 2 important things to note here:
[[.Name]]
as the template variable for the name. This is because we have specified custom delimiters for Go templates in the router.go
file.Now we need to build the Astro project:
cd client
npm run build
This will generate the static files in the client/dist
directory.
Now we need to run the Go server:
go run .
Open your browser and navigate to https://localhost:8080
. You should see the Astro logo and the text “Hello Go Astro”.
This experiment is available as a GitHub repository for you to clone and play around with.
This method introduces some dynamism to your Astro projects and can be expanded to include components, similar to the GoTH stack. You also have full flexibility on how to handle routing, data fetching and other server-side logic. However, it also comes with limitations: you won’t be able to use Astro’s built-in features like partial hydration or server-side rendering, lose file-based routing and other Astro-specific features. But if you’re looking for a way to inject dynamic content into your Astro projects, this is a good starting point.
CTO @ Wingravity by day, Co-Founder @ Slashscore whenever I can fit it in. Do you have a question, or are you interested in working with my team and me? Just fill out the contact form.
Read more about
Tags