Guide / 09 β€” Go Logic

PageData

stew.PageData is the central data structure passed to every page, layout, and component during SSR.

Structure

// sdk/stew/types.go
type PageData struct {
    URL     string              // Current URL path (e.g., "/users/42")
    Params  map[string]string   // URL parameters ({id} β†’ "42")
    Query   url.Values          // Query parameters (?page=2)
    Request *http.Request       // Raw HTTP request
    Store   map[string]any      // Free-form map for data storage
}

Template Access

<goscript>
    import "strconv"

    // Current URL
    currentPath := data.URL

    // Dynamic URL parameter (/users/{id})
    userId := data.Params["id"]

    // Query string (?page=2&sort=desc)
    page := data.Query.Get("page")
    sort := data.Query.Get("sort")

    // HTTP Header
    userAgent := data.Request.Header.Get("User-Agent")

    // Free-form Store
    data.Store["user"] = "Baptiste"
</goscript>

<p>URL: {{ currentPath }}</p>
<p>User #{{ userId }}</p>

Propagation Through Layouts

The same PageData object is created once per request in the router and passed to the entire rendering chain (root layout β†’ nested layouts β†’ page β†’ components). Changes made to data.Store in a <goscript> are visible throughout the entire rendering of that request.

Execution Order: The <goscript> code of a page is executed before the HTML rendering of that page. However, the layout is rendered around the page: its HTML is generated both before and after the page content in the stream.

Accessing Data in Wasm

To avoid JSON unmarshaling boilerplate, Stew provides a virtual import stew/data. When imported, a local data variable (of type stew.PageData) becomes available in your client-side scope.

<goscript client>
    import "stew/data"

    func HandleClick() {
        // Access URL parameters directly
        userId := data.Params["id"]
        
        // Access the free-form Store
        if title, ok := data.Store["Title"].(string); ok {
            println("Page title: " + title)
        }
        
        // Current URL
        println("Current path: " + data.URL)
    }
</goscript>
Recommended: Using import "stew/data" is the standard way to retrieve state passed from the server in your Wasm scripts.

Low-level JSON Serialization (Manual)

When a page contains a <goscript client> block, the compiler automatically injects the state as JSON:

<script type="application/json" id="stew-pagedata">
    {"URL":"/","Params":{},"Store":{"Title":"My App"},...}
</script>

If you need to unmarshal it manually (low-level access):

<goscript client>
    import "encoding/json"

    pageData := wasm.GetPageDataJSON() // Get raw JSON string
    var state map[string]interface{}
    json.Unmarshal([]byte(pageData), &state)
</goscript>
Security Constraint: Never place sensitive data in data.Store if it should not be exposed to the client. All data in the Store is serialized into JSON and visible in the HTML source code.