Static Files

Serve CSS, JavaScript, images, and other static assets from your project's public/ directory. Nimbus uses Go's built-in http.FileServer under the hood, registered as a route on the Chi router.

Project structure

Place your static assets in the public/ directory at the project root:

myapp/
  public/
    css/
      app.css
    js/
      app.js
    images/
      logo.png
    favicon.ico
  views/
  main.go

Configuring the file server

Register a wildcard route that serves files from public/. Use http.StripPrefix so the URL path maps correctly to the file system.

import (
    "github.com/CodeSyncr/nimbus"
    "github.com/go-chi/chi/v5"
)

func main() {
    app := nimbus.New()

    // Serve /static/* from the public/ directory
    fileServer := http.FileServer(http.Dir("public"))
    app.Router.Handle("/static/*",
        http.StripPrefix("/static/", fileServer),
    )

    app.Run()
}

With this setup, /static/css/app.css serves the file at public/css/app.css.

Referencing assets in templates

In your .nimbus templates, reference static assets using the path prefix you configured:

<link rel="stylesheet" href="/static/css/app.css">
<script src="/static/js/app.js"></script>
<img src="/static/images/logo.png" alt="Logo">

Setting cache headers

Wrap the file server with a middleware that sets Cache-Control headers for better performance in production.

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

fileServer := http.FileServer(http.Dir("public"))
cached := cacheControl(http.StripPrefix("/static/", fileServer))
app.Router.Handle("/static/*", cached)

Serving from the root path

If you prefer serving assets without a prefix (e.g. /css/app.css directly), mount the file server at the root. Be careful with route conflicts — define your API and page routes first.

// Serve files directly from public/ at the root
fileServer := http.FileServer(http.Dir("public"))
app.Router.Handle("/*", fileServer)

Serving a single file

For individual files like favicon.ico or robots.txt, use a dedicated route with http.ServeFile.

app.Router.Get("/favicon.ico", func(c *http.Context) error {
    http.ServeFile(c.Response, c.Request, "public/favicon.ico")
    return nil
})

app.Router.Get("/robots.txt", func(c *http.Context) error {
    http.ServeFile(c.Response, c.Request, "public/robots.txt")
    return nil
})

Using embedded files (Go 1.16+)

For single-binary deployments, embed static files at compile time using embed.FS.

import "embed"

//go:embed public/*
var publicFS embed.FS

func main() {
    app := nimbus.New()
    sub, _ := fs.Sub(publicFS, "public")
    fileServer := http.FileServer(http.FS(sub))
    app.Router.Handle("/static/*",
        http.StripPrefix("/static/", fileServer),
    )
    app.Run()
}

Tips

  • In development, disable caching so changes to CSS/JS are reflected immediately.
  • In production, use long max-age values and fingerprinted filenames (e.g. app.abc123.css).
  • For large-scale apps, serve static files from a CDN and use Nimbus only for the API and server-rendered pages.