API Docs
When entrest.Config.DisableSpecHandler is false
at generation time, entrest embeds the OpenAPI spec in your generated rest package and registers
GET {BasePath}/openapi.json and GET {BasePath}/docs (an embedded Scalar
UI). With the stdlib handler, GET / (after BasePath is stripped) redirects to /docs.
See Configuration — Base URL and path for how mount paths
affect these URLs.

The /docs route is implemented by Server.Docs. It renders a single inline HTML document on each
request and loads Scalar from the jsDelivr CDN — there is no separate static site.
Route registration, spec serving, and DisableDocsHandler are covered in
Configuration — OpenAPI spec endpoint and
API reference docs.
Any OpenAPI viewer that accepts a spec URL can replace the embedded Scalar page:
- Set
DisableDocsHandlertotrueso/docsis not registered by the generated handler. - Keep
/openapi.jsonenabled (unless you serve the spec from another origin). - Register your own
GEThandler that returns a single HTML document. - Point the viewer at
{BasePath}/openapi.json(or an absolute URL if the UI is on another host).
The examples below use RapiDoc and mount custom docs at /v1/docs.
This example serves one self-contained HTML page from Go with fmt.Fprintf, loads RapiDoc from the
unpkg CDN, and overrides component attributes for a focused dark layout.
// [...]
func rapidocDocs(baseURL string) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { uri := strings.TrimSuffix(baseURL, "/")
w.Header().Set("Content-Type", "text/html") w.WriteHeader(http.StatusOK) fmt.Fprintf(w, `<!doctype html><html><head> <meta charset="utf-8"> <meta name="referrer" content="no-referrer"> <script type="module" src="https://unpkg.com/rapidoc@9.3.8/dist/rapidoc-min.js"></script> <title>Pet Store API</title></head><body> <rapi-doc allow-server-selection="false" bg-color="#18181C" fill-request-fields-with-example="false" font-size="large" layout="row" load-fonts="false" mono-font="Consolas, monaco, monospace" nav-bg-color="#0F0F0F" nav-hover-bg-color="#1B1B1B" primary-color="#10B981" regular-font="Consolas, monaco, monospace" render-style="focused" schema-description-expanded="true" show-curl-before-try="true" show-header="false" show-method-in-nav-bar="as-colored-text" spec-url=%q text-color="#BBBBBB" theme="dark" use-path-in-nav-bar="true" persist-auth="true" ></rapi-doc></body></html>`, uri+"/openapi.json") }}
func main() { // [...]
mux := http.NewServeMux() mux.HandleFunc("GET /v1/docs{$}", rapidocDocs(cfg.BaseURL)) mux.Handle("/", srv.Handler())
log.Fatal(http.ListenAndServe(":8080", mux))}Register the docs route on the same sub-router where you mount the generated API. Set BasePath to
match the mount point so spec URLs stay correct — see
Configuration — Stdlib vs chi.
cfg := &rest.ServerConfig{ BaseURL: "https://api.example.com/v1", BasePath: "/v1", DisableDocsHandler: true,}srv, err := rest.NewServer(db, cfg)if err != nil { panic(err)}
r := chi.NewRouter()r.Route("/v1", func(r chi.Router) { r.Get("/docs", rapidocDocs(cfg.BaseURL)) srv.Handler(r)})http.ListenAndServe(":8080", r)
