spa

package
v1.801.490 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 6, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

Documentation

Overview

Package spa serves a built single-page app out of an embedded filesystem.

It is the ONE way an app in this repo serves its own UI. Three apps had byte-identical copies of this handler (tasks, research, and meet as it landed); the policy in it is not obvious enough to be worth restating three times, and a policy restated three times drifts:

  • a content-addressed asset under assets/ carries an immutable cache hint, because Vite hashes the filename — the bytes at that name never change;
  • everything else is no-cache, so a freshly deployed shell replaces the stale one on the next request rather than on the next cache expiry;
  • a path that is not a real file rewrites to index.html, which is what lets a deep link survive a reload under a client-side router — EXCEPT under assets/, where a miss is a 404. That subtree holds only content-addressed build output, so a name that is not there is a stale shell asking for a purged chunk, never a client-side route. Answering the shell there hands a <script> tag a document — "Unexpected token '<'", which reads as a corrupt bundle rather than the cache miss it is;
  • a DIRECTORY is not a page. http.FileServer lists one, so serving whatever stat succeeds on publishes the whole asset manifest at /<app>/assets/; a directory falls through to the shell (or 404s under assets/) instead;
  • a MISSING index.html is 503, not a blank 200. A bundle that failed to sync is then loud in staging instead of being a white page in production.

It is NOT the console at "/" (webui). That one is a different handler on purpose: it owns the root catch-all, so it has to refuse the API namespaces outright and rewrite the document title per white-label host. This one is mounted under its app's own prefix and never sees a path that is not its own.

It is a LEAF — stdlib only — so any app can serve its UI without linking the fleet.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Handler

func Handler(root fs.FS, name string) http.Handler

Handler serves the built SPA rooted at root. Mount it under StripPrefix("/<app>", …) so it sees root-relative paths.

name is the app the bundle belongs to and appears only in the 503 body, so an operator reading a failed deploy is told WHICH bundle is missing rather than that "the UI" is.

func Sub

func Sub(embedded fs.FS) fs.FS

Sub is fs.Sub(embedded, "dist") without the error a caller cannot act on: an embed.FS is validated at COMPILE time, so a missing dist/ is a build failure, never a runtime branch. Every ui package spells the same two lines otherwise.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL