Guide / 05
File-Based Routing
The structure of the pages/ directory fully defines the application's routing. No routing configuration is necessary.
File Conventions
pages/
βββ @layout.stew β Root layout (wraps all pages)
βββ @page.stew β GET /
βββ about/
β βββ @page.stew β GET /about
βββ blog/
β βββ @layout.stew β Nested layout for /blog/*
β βββ @page.stew β GET /blog
β βββ __slug__/
β βββ @page.stew β GET /blog/{slug}
βββ api/
βββ users/
βββ server.go β Custom Go handlers (POST, DELETE, etc.)
URL Parameters
A folder named __param__ creates a dynamic parameter in the URL. Accessible via data.Params["param"]:
<!-- pages/users/__id__/@page.stew -->
<p>User Profile: {{ data.Params["id"] }}</p>
Generates the route: GET /users/{id}
Query Parameters
Query parameters are accessible via data.Query (of type url.Values):
<goscript>
import "strconv"
page := 1
if p := data.Query.Get("page"); p != "" {
page, _ = strconv.Atoi(p)
}
</goscript>
<p>Page {{ page }}</p>
Router Generation
The stew generate command scans pages/ and generates stew_router_gen.go:
// Code generated by Stew. DO NOT EDIT.
func RegisterStewRoutes(mux *http.ServeMux) {
// Static assets
mux.Handle("GET /static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
// Route /
mux.Handle("GET /", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
data := stew.PageData{URL: r.URL.Path, Query: r.URL.Query(), ...}
pages.Layout(w, data, func() {
pages.Page(w, data)
})
}))
// Parameterized route
mux.Handle("GET /users/{id}", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
data.Params["id"] = r.PathValue("id")
stew_pages_users_id.Page(w, data)
}))
}
β οΈ Do not modify
stew_router_gen.go β This file is completely regenerated with each stew generate.
Static Assets
All files placed in static/ are automatically served under the /static/ prefix. The static/wasm/ folder contains generated Wasm binaries.
<link rel="stylesheet" href="/static/style.css">
<img src="/static/images/logo.png">