Serve Help Over HTTP

Use `glaze serve` to browse help pages in a browser, and reuse the help API and SPA handlers in your own HTTP server.

Sections

Terminology & Glossary
📖 Documentation
Navigation
74 sectionsv0.1
📄 Serve Help Over HTTP — glaze help serve-help-over-http
serve-help-over-http

Serve Help Over HTTP

Use `glaze serve` to browse help pages in a browser, and reuse the help API and SPA handlers in your own HTTP server.

Topichelphttpserveapidocumentationservehelpaddress

Why glaze serve exists

glaze 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:

  • you want a quick local browser for an existing help tree such as docs/ or pkg/doc/, or
  • you are embedding Glazed help into a larger application and want to reuse the API and SPA handlers under your own HTTP routes.

The 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.

Use glaze serve from the command line

The 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:

  • If no paths are given, the built-in Glazed documentation (loaded at startup via doc.AddDocToHelpSystem) is used.
  • If paths are given, Glazed walks the supplied directories recursively.
  • It loads .md files with Glazed help frontmatter into the help store.
  • It exposes the help API under /api/....
  • It serves the embedded SPA for browser routes such as /.

API endpoints exposed by glaze serve

The browser UI talks to a small HTTP API. You can call the same endpoints yourself.

GET /api/health

Returns a simple health response with the number of loaded sections.

curl http://localhost:18100/api/health

Example response:

{"ok":true,"sections":65}

GET /api/sections

Returns section summaries.

curl http://localhost:18100/api/sections

You can filter using query parameters:

  • type=GeneralTopic|Example|Application|Tutorial
  • topic=...
  • command=...
  • flag=...
  • q=... for text search
  • limit=...
  • 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

Embed the help API in your own server

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 API

API-only mode

Pass 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.

With the browser UI (in-repo only)

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.

Mount under a prefix such as /help

Use 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 listing

Browsing help from multiple tools

The 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.

Package names and section visibility

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.

Loading help pages 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.

Troubleshooting

ProblemCauseSolution
Browser shows a blank page or errorThe SPA assets were not generated or embeddedRun 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 assetUse 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 dataSections have no package name; the SPA filters by packageNewServeHandler auto-assigns a default package. For direct Store usage, call hs.Store.SetDefaultPackage(ctx, "myapp", "") after loading docs
/api/health works but no sections appearThe supplied markdown files were not loaded or were skippedVerify the path exists, the files end in .md, and the frontmatter has fields like Title, Slug, and SectionType
glaze serve exits immediatelyInvalid path or startup errorRe-run with valid file/directory arguments and inspect the error output
Mounted /help route returns 404Prefix mounting was not wired correctly in the outer muxRegister both /help and /help/, and use server.NewMountedHandler("/help", ...)
API calls work but browser routes failSPA handler was not mounted or the embedded filesystem root is wrongUse 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

See Also

  • glaze help distribute-help-browser-spa — Fetch and embed the versioned SPA release asset in another Go binary
  • glaze help serve-external-help-sources — Serve help exported from other Glazed binaries and snapshots
  • glaze help export-help-entries — Export help sections to files, JSON, CSV, or SQLite
  • glaze help export-help-static-website
  • glaze help help-system
  • glaze help writing-help-entries
  • glaze help how-to-write-good-documentation-pages
  • glaze help sections-guide