Embedding Nuxt Frontend into Go App

Embedding Nuxt Frontend into Go App

September 21, 2023

We will create a Go application with web interface powered by the Nuxt framework.

Prepare Go project

Read more how to create your First App with Go.

Create component for Web Interface

Make directory for new component called ui to store our web interface. This component will also implement HTTP handlers, allowing us to access static files:

mkdir -p internal/ui

Create Nuxt Project

In console, open the ui component directory and create new Nuxt project:

cd internal/ui
npx nuxi@latest init web
cd $_

Read more in the Getting Started guide on official website. In the Nuxt configuration file turn off Server Side Rendering (SSR). Open nuxt.config.ts file and append ssr option:

export default defineNuxtConfig({
    ssr: false,
})

Now we can build web interface:

npm install
npm run generate

All files will be stored in the .output/public directory.

Implementing Go component

Create source file internal/ui/ui.go:

package ui

import (
	"embed"
	"io/fs"
	"net/http"
)

var (
	//go:embed web/.output/public/_nuxt/* web/.output/public/favicon.ico
	public embed.FS

	//go:embed web/.output/public/index.html
	indexHTML []byte
)

func webSPA() http.HandlerFunc {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html; charset=utf-8")
		_, _ = w.Write(indexHTML)
	})
}

func webStatic() http.HandlerFunc {
	fsPublic, _ := fs.Sub(public, "web/.output/public")
	fileServer := http.FileServer(http.FS(fsPublic))

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Cache-Control", "public, max-age=31536000, immutable")
		fileServer.ServeHTTP(w, r)
	})
}

func WebHandler() http.Handler {
	mux := http.NewServeMux()
	mux.HandleFunc("/_nuxt/", webStatic())
	mux.HandleFunc("/favicon.ico", webStatic())
	mux.HandleFunc("/", webSPA())
	return mux
}

This component could be imported in the application file internal/app/app.go and handler added to the HTTP server:

package app

import (
	"net/http"

	"example/internal/ui"
)

func Start() error {
	return http.ListenAndServe(":8080", ui.WebHandler())
}

Handle static files

In the default project only one file exists in the public directory, this is favicon.ico. If you want to use more static files you may create directory public/static in the Nuxt project. And embed this directory into the Go App:

var (
	//go:embed web/.output/public/_nuxt/* web/.output/public/static/*
	public embed.FS

	//go:embed web/.output/public/index.html
	indexHTML []byte
)

func WebHandler() http.Handler {
	mux := http.NewServeMux()
	mux.HandleFunc("/_nuxt/", webStatic())
	mux.HandleFunc("/static/", webStatic())
	mux.HandleFunc("/", webSPA())
	return mux
}

Check out this project in our repository.