httpserver.NewApp(...) is the app-facing runtime entrypoint.
Use it with the generated App Bundle:
handler, err := httpserver.NewApp(httpserver.Config[*view.Context]{
App: generated.Bundle(appContext),
})httpserver.NewApp(...) is the supported happy path. The lower-level
httpserver.New(...) exists for advanced composition, but most apps should not
build the runtime from raw pieces.
When you stay on the default path, httpserver.NewApp(...) does this for you:
- mounts the generated route handlers
- enables built-in i18n middleware when the
App Bundlecontains i18n config - serves hashed static assets from
web/assets-build/manifest.jsonwhen the manifest exists - uses
/_assets/as the base static prefix before the manifest hash is added - serves
web/publicat fixed request paths when the directory exists - exposes
/healthzwith bodyok - adds gzip compression
- uses
public, max-age=3600, s-maxage=3600as the default cache policy for HTML, static assets, health, and generic error responses
generated.Bundle(appContext) returns the App Bundle that NewApp(...)
expects.
The generated bundle supplies:
- route handlers
- discovery handlers
- built-in i18n config
- site-root resolution through
appContext.ResolveRoot - generated not-found rendering
- templ CSS registration
- static asset base-path callback through
view.SetStaticAssetBasePathwhen yourweb/viewpackage defines that hook
Do not hand-build the bundle unless you are intentionally doing advanced composition.
Custom Config is the main escape hatch around the default runtime.
handler, err := httpserver.NewApp(httpserver.Config[*view.Context]{
App: generated.Bundle(appContext),
Custom: httpserver.CustomConfig{
MainMiddlewares: []func(http.Handler) http.Handler{
requestIDMiddleware,
},
},
})Supported Custom Config fields:
ExtraRoutesMount extra handlers on a dedicatedhttp.ServeMux.MainMiddlewaresWrap the main generated route handler.CachePoliciesOverride cache headers for HTML, HTMX, static, health, and error responses.StaticAssetsOverride manifest path or base URL prefix.PublicFilesOverride public-file directory, request-path prefix, or cache policy.ServerErrorPageRender a generic custom 500 page. The hook receives the error, but not the request, so it should not be used for localized or request-scoped content.LogServerErrorEventReplace the default server-error logger with request-aware event logging. The event includes the error, request pointer, method, path, query, host, remote address, user agent, and common request ID headers.LogServerErrorReplace the default server-error logger with the legacy error-only callback. Ignored whenLogServerErrorEventis set.LogResolverTimingReceive resolver timing events when resolver debug is enabled.EnableResolverDebugTurn on resolver timing logs.DisableHealthDisable the health endpoint entirely.HealthPathOverride the health endpoint path.HealthBodyOverride the health endpoint body.
ManifestPathPath to the manifest file read at runtime.URLPrefixBase prefix used before the manifest hash is added.
DirFilesystem directory to serve.RequestPathPrefixOptional prefix to add before public request paths.CachePolicyOptional cache header override. Default:public, max-age=0
HTMLFull-page HTML responses.LiveHTMX partial responses.LiveNavigationHTMX navigation responses marked with__live=navigation.StaticHashed static assets.HealthHealth endpoint responses.ErrorNot-found and error-page responses.
Stay on the default path when you just need:
- generated routes
- built-in i18n
- hashed static assets
- public files
- discovery conventions
- standard health and gzip behavior
Reach for Custom Config when you need app-owned middleware, extra routes, or
runtime overrides. Reach for Advanced composition only when NewApp(...)
cannot express the shape you need.