Use `glaze serve` to browse help pages in a browser, and reuse the help API and SPA handlers in your own HTTP server.
glaze serve existsglaze serve turns Glazed help pages into a browsable web application. Instead of only reading help in the terminal, you can load markdown help entries into a help store, expose a JSON API for search and filtering, and serve the embedded SPA that renders those entries in a browser.
This matters in two situations:
docs/ or pkg/doc/, orThe command is intentionally built on the same primitives you can use from Go code. That means the CLI path and the programmatic path stay aligned.
glaze serve from the command lineThe simplest way to use the feature is to run it with no arguments — it will load the built-in Glazed documentation:
glaze serve
You can also point it at one or more markdown files or directories:
glaze serve ./pkg/doc
You can also serve multiple paths at once:
glaze serve ./pkg/doc ./extras/help
If you need a different port, use --address:
glaze serve --address :18100 ./pkg/doc
When the server starts:
doc.AddDocToHelpSystem) is used..md files with Glazed help frontmatter into the help store./api/..../.glaze serveThe browser UI talks to a small HTTP API. You can call the same endpoints yourself.
GET /api/healthReturns a simple health response with the number of loaded sections.
curl http://localhost:18100/api/health
Example response:
{"ok":true,"sections":65}
GET /api/sectionsReturns section summaries.
curl http://localhost:18100/api/sections
You can filter using query parameters:
type=GeneralTopic|Example|Application|Tutorialtopic=...command=...flag=...q=... for text searchlimit=...offset=...Example:
curl 'http://localhost:18100/api/sections?type=Example&topic=help'
GET /api/sections/{slug}Returns a full section, including markdown content.
curl http://localhost:18100/api/sections/help-system
If you already have an HTTP server, you can embed the Glazed help JSON API directly into your Go application. You do not need to shell out to glaze serve.
The building block is:
server.NewServeHandler(...) or server.NewMountedHandler(...) for the REST APIPass nil as the SPA handler to serve only the JSON endpoints. This is the simplest integration mode for binaries that depend on glazed as a library, because it does not require bundling browser assets.
package main
import (
"net/http"
"github.com/go-go-golems/glazed/pkg/help"
helpserver "github.com/go-go-golems/glazed/pkg/help/server"
)
func main() {
hs := help.NewHelpSystem()
// Load your own help pages here.
// err := hs.LoadSectionsFromFS(...)
// nil = API-only mode, no browser UI.
handler := helpserver.NewServeHandler(
helpserver.HandlerDeps{Store: hs.Store},
nil,
)
_ = http.ListenAndServe(":18100", handler)
}
This serves the full JSON API (/api/health, /api/sections, /api/packages) without the browser UI. You can build your own frontend, use glaze serve --from-glazed-cmd to browse help from multiple tools in a single web interface, or fetch the versioned glazed-spa release asset and embed it in your own binary.
If you are building within the glazed repository, you can include the embedded React SPA:
package main
import (
"net/http"
"github.com/go-go-golems/glazed/pkg/help"
helpserver "github.com/go-go-golems/glazed/pkg/help/server"
"github.com/go-go-golems/glazed/pkg/web"
)
func main() {
hs := help.NewHelpSystem()
spaHandler, err := web.NewSPAHandler()
if err != nil {
panic(err)
}
handler := helpserver.NewServeHandler(
helpserver.HandlerDeps{Store: hs.Store},
spaHandler,
)
_ = http.ListenAndServe(":18100", handler)
}
Note: The SPA assets are built by go generate ./pkg/web (using Dagger/pnpm) and embedded into the glaze binary via //go:embed when building from the glazed repository with -tags embed. External binaries cannot import those embedded files directly from the Glazed Go module. If an external binary wants the same browser UI, fetch the versioned GitHub Release asset such as glazed-spa-1.2.13.tar.gz, extract it into an ignored local dist/ directory, and embed that directory in the downstream binary. See glaze help distribute-help-browser-spa for the complete pattern.
/helpUse NewMountedHandler to serve the help API under a sub-route of an existing HTTP server:
mux := http.NewServeMux()
deps := helpserver.HandlerDeps{Store: hs.Store}
// Mount API-only at /help
mounted := helpserver.NewMountedHandler("/help", deps, nil)
mux.Handle("/help", mounted)
mux.Handle("/help/", mounted)
This serves:
/help/api/health — health check/help/api/sections — section listing/help/api/packages — package listingThe recommended pattern for viewing help from multiple Glazed-based tools in a browser is:
glaze serve --from-glazed-cmd pinocchio,sqleton
This loads each tool's help data via help export --output json and serves it in a single browser UI. You don't need to embed the SPA in each individual binary. If a tool does need its own standalone browser UI, use the release-asset workflow described in glaze help distribute-help-browser-spa.
Help sections are grouped by package name. When sections are loaded from embedded markdown files (via LoadSectionsFromFS), they get an empty package name. NewServeHandler automatically assigns these sections a default package name so that they appear correctly in the API responses.
If you are using the Store directly (without NewServeHandler), you can call Store.SetDefaultPackage(ctx, "myapp", "") after loading your sections to assign them a package name. This is required for the package filter in the help API to work correctly.
The HTTP layer only serves what you load into the help system. In practice that means you should load markdown files before starting the server.
For embedded documentation packages, the usual pattern is:
helpSystem := help.NewHelpSystem()
if err := doc.AddDocToHelpSystem(helpSystem); err != nil {
panic(err)
}
For ad hoc files and directories, use the CLI:
glaze serve ./pkg/doc ./more-docs
If a page does not appear in the browser, the most common cause is that the markdown file is missing valid Glazed help frontmatter.
| Problem | Cause | Solution |
|---|---|---|
| Browser shows a blank page or error | The SPA assets were not generated or embedded | Run GOWORK=off go generate ./pkg/web, then rebuild glaze |
| SPA shows "assets have not been generated" | Building from outside the glazed repository without fetching a SPA asset | Use API-only mode, glaze serve --from-glazed-cmd, or fetch and embed the versioned glazed-spa-<version>.tar.gz release asset |
SPA shows "0 sections" but /api/sections returns data | Sections have no package name; the SPA filters by package | NewServeHandler auto-assigns a default package. For direct Store usage, call hs.Store.SetDefaultPackage(ctx, "myapp", "") after loading docs |
/api/health works but no sections appear | The supplied markdown files were not loaded or were skipped | Verify the path exists, the files end in .md, and the frontmatter has fields like Title, Slug, and SectionType |
glaze serve exits immediately | Invalid path or startup error | Re-run with valid file/directory arguments and inspect the error output |
Mounted /help route returns 404 | Prefix mounting was not wired correctly in the outer mux | Register both /help and /help/, and use server.NewMountedHandler("/help", ...) |
| API calls work but browser routes fail | SPA handler was not mounted or the embedded filesystem root is wrong | Use web.NewSPAHandler() in Glazed itself; in downstream binaries, make sure //go:embed dist is exposed with fs.Sub(..., "dist") so index.html is at the root |
glaze help distribute-help-browser-spa — Fetch and embed the versioned SPA release asset in another Go binaryglaze help serve-external-help-sources — Serve help exported from other Glazed binaries and snapshotsglaze help export-help-entries — Export help sections to files, JSON, CSV, or SQLiteglaze help export-help-static-websiteglaze help help-systemglaze help writing-help-entriesglaze help how-to-write-good-documentation-pagesglaze help sections-guide