2. App
New() *App
- Returns a new
*App. - Initializes internal state:
state: map[string]any{}pages: map[string]Handler{}actions: map[string]Handler{}cookieSecure: false(default).
Run(addr string) error
- Starts an HTTP server with
http.ListenAndServe(addr, a.Handler()). - Logs
marionette listening at http://<addr>to stdout before serving. - Returns any
ListenAndServeerror as-is.
Desktop runtime: desktop.Run(app *backend.App, options desktop.Options) error
- Starts the app on a private
127.0.0.1:0server usingapp.Handler(). - Opens that local URL in a native WebView shell.
- Shuts the local server down when the WebView exits.
- Requires building with
-tags marionette_desktopto enable the native WebView adapter.
Desktop options
Title string: native window title; defaults to"Marionette".Width int: native window width; defaults to1200.Height int: native window height; defaults to800.Debug bool: passes WebView debug mode through to the adapter.
Page options
type PageOptions struct { Title string }type PageOption func(*PageOptions)WithTitle(title string) PageOption- Trims whitespace and sets the HTML
<title>for that page route.
- Trims whitespace and sets the HTML
SetCookieSecure(secure bool)
- Enables/disables
Secureon the flash cookie (marionette_flash). - Default is
false. - Affects both:
- flash write (
Context.AddFlash) - flash clear (when flashes are consumed on next request).
- flash write (
Assets(prefix string, fsys fs.FS, options ...AssetOption)
- Serves static files from
fsysunderprefix. - Use
os.DirFS("assets")for local files orembed.FSplusfs.Subfor single-binary assets. - Directory index responses are disabled by default; pass
WithAssetIndex(true)only when directory browsing is intentional. - Asset routes are included in
Handler()andRun().
UseAssetProvider(provider assets.AssetProvider) / UseAssets(provider assets.AssetProvider)
- Replaces the provider that resolves Marionette’s built-in framework/library CSS and JavaScript URLs in generated shells.
- Use a custom provider when you need full control over the URLs for DaisyUI, Tailwind browser, HTMX, or Chart.js.
UseAssetsis the existing shorthand;UseAssetProvideris a descriptive alias for the same behavior.
UseOfflineAssets(basePath string)
- Uses Marionette’s standard local vendor file names under
basePathinstead of CDN URLs. The default logical file names are:daisyui.csstailwindcss-browser.jshtmx.min.jschart.umd.js
- Pair it with
Assetsto serve the files from a local directory or embedded filesystem:
package main
import (
"embed"
"io/fs"
"log"
"time"
"github.com/YoshihideShirai/marionette/backend"
)
//go:embed frontend/assets/vendor/*
var embeddedAssets embed.FS
func main() {
app := backend.New()
vendorFS, err := fs.Sub(embeddedAssets, "frontend/assets/vendor")
if err != nil {
log.Fatal(err)
}
app.Assets("/vendor", vendorFS, backend.WithAssetCache(24*time.Hour), backend.WithAssetImmutable())
app.UseOfflineAssets("/vendor")
// register pages/actions...
log.Fatal(app.Run("127.0.0.1:8080"))
}
Downloads(prefix string, fsys fs.FS, options ...AssetOption)
- Serves static files from
fsysunderprefixwithContent-Disposition: attachment. - Equivalent to
Assets(prefix, fsys, WithAssetDownload(), options...). - Uses the requested file basename as the attachment filename.
Asset(name string) string
- Builds an asset URL from the first registered asset prefix.
- Example: after
app.Assets("/assets", ...),app.Asset("hero.jpg")returns"/assets/hero.jpg". - Absolute
http://,https://, anddata:URLs pass through unchanged.
Asset options
WithAssetCache(maxAge time.Duration)emitsCache-Control: public, max-age=<seconds>.WithAssetImmutable()addsimmutablewhen asset caching is enabled.WithAssetIndex(enabled bool)allows directory index responses from the underlying file server.WithAssetDownload()serves matching files as attachment downloads.WithAssetContentTypes(types map[string]string)setsContent-Typeby extension before serving.
AddStylesheet(href string)
- Adds a custom stylesheet link to the full-page HTML shell.
- Empty/whitespace-only values are ignored.
- Stylesheets are emitted after the built-in Tailwind/daisyUI assets.
AddStyle(css string)
- Adds trusted inline CSS to the full-page HTML shell.
- Empty/whitespace-only values are ignored.
- Use for small app-level overrides or CSS variables.
AddScript(src string)
- Adds an external JavaScript file to the full-page HTML shell.
- Empty/whitespace-only values are ignored.
- Scripts are emitted after Marionette’s built-in JavaScript.
AddJavaScript(js string)
- Adds trusted inline JavaScript to the full-page HTML shell.
- Empty/whitespace-only values are ignored.
- Inline JavaScript is emitted after custom external scripts, so it can use
libraries registered with
AddScript.
EnableSSE() / EnableServerSentEvents(enable bool)
- Includes Marionette’s built-in EventSource connector runtime in full-page shells.
- The connector automatically opens
data-marionette-sse-urlelements, readshtmlSSE events emitted byStreamAction, and applieshx-swap-oobfragments. - This is opt-in so apps that do not use SSE keep their default shell small.
Handler() http.Handler
- Builds and returns
*http.ServeMuxwith all registered routes. Pageroutes:- path match is strict (
r.URL.Pathmust equal registered path, otherwise404). - method is
GETonly, otherwise405 Method Not Allowed. - renders full HTML shell.
- path match is strict (
Actionroutes:- method is
POSTonly, otherwise405 Method Not Allowed. - executes
r.ParseForm(), parse failure is400 Bad Request. - renders HTML fragment only.
- method is
- If
/is not registered byPage/Render:GET /returns500 Internal Server Errorwith configuration message.- non-root unmatched paths are
404.
Page(path string, fn Handler, options ...PageOption)
- Registers full-page handler for
GET. - Path normalization:
""->"/"- no leading slash -> leading slash is added.
- Render mode: handler
Nodeis wrapped in Marionette shell HTML.
Action(name string, fn Handler)
- Registers fragment handler for
POST. - Name normalization:
- always stored as
"/" + strings.TrimPrefix(name, "/").
- always stored as
- Parse failure in request form body ->
400. - Render mode: handler
Nodeis returned as fragment HTML.
Render(fn Handler, options ...PageOption)
- Compatibility alias for root page registration.
- Equivalent to
Page("/", fn).
Handle(name string, fn Handler)
- Compatibility alias for action registration.
- Equivalent to
Action(name, fn).
App state helpers
App state helpers whose names include Global read or write app-wide state shared by all users and all requests.
SetGlobal(key string, value any)
- Writes into the app shared state map with lock.
- Because this API is named
Global, the value is shared by all users of the app.
GetGlobal(key string) any
- Reads from the app shared state map with lock.
- Because this API is named
Global, the value is shared by all users of the app. - If the value is a mutable slice, map, or pointer, do not mutate it directly after
GetGlobalreturns; mutate underUpdateGlobalor read viaGetGlobalSnapshotwith a clone function.
GetGlobalSnapshot(key string, clone func(any) any) any
- Reads from app shared state and returns
clone(value)while holding the app read lock. - Use this for read-only snapshots of slices, maps, or other mutable values before rendering or handing them to code that might mutate them.
UpdateGlobal(key string, fn func(old any) any) any
- Atomically reads, transforms, and writes app shared state while holding the app mutex.
- Use when the next value depends on the old value, such as counters, progress ticks, or append-style updates.
GetGlobalInt(key string) int
- Reads app shared state and type-asserts to
int. - Returns
0when value is missing or notint.
IncrementGlobalInt(key string, delta int) int
- Convenience wrapper around
UpdateGlobalfor integer counters/progress values. - Treats missing or non-
intvalues as0, storesold + delta, and returns the newint.