Sessions
Per-user state that persists across requests. Session variables are reactive — update a value on the server and every element displaying it updates automatically.
Session Variables
Display any session value with the #session.key# syntax. The engine automatically wraps session variables in a <span w-bind="session.key"> element so they can be updated in real time without a page reload.
<p>Items in cart: #session.cart_count#</p>
<p>Welcome back, #session.username#</p>
Rendered output (simplified):
<p>Items in cart: <span w-bind="session.cart_count">3</span></p>
<p>Welcome back, <span w-bind="session.username">Jorge</span></p>
class="#session.theme#") are replaced with the raw value and are not wrapped in a <span>. Reactive wrapping only applies to text content.
Setting Values
Use the w-set attribute on any clickable element to mutate session data. The attribute value is an expression in the form session.key = value.
<!-- Assign a string -->
<button w-set="session.name = 'Jorge'">Set Name</button>
<!-- Assign a number -->
<button w-set="session.page = 1">Go to Page 1</button>
When clicked, the framework posts to /w-set with the expression, applies the mutation to the session, and pushes an out-of-band update to the page — every <span w-bind="session.name"> on the page updates instantly.
Increment & Decrement
Use += and -= to modify numeric session values. If the key does not exist yet, it starts at 0.
<button w-set="session.count += 1">+1</button>
<button w-set="session.count -= 1">-1</button>
<p>Count: #session.count#</p>
You can increment by any integer:
<button w-set="session.score += 10">Bonus Points</button>
Toggle
Toggle a boolean-like value by assigning a string. Combine with conditionals to build toggle patterns:
<if session.dark == true>
<button w-set="session.dark = 'false'">Light Mode</button>
</if>
<else/>
<button w-set="session.dark = 'true'">Dark Mode</button>
</else>
Multiple Mutations
Separate multiple expressions with semicolons. All mutations are applied in a single request.
<button w-set="session.step += 1; session.status = 'in_progress'">
Next Step
</button>
You can mix session, app, and wired scopes in one expression:
<button w-set="session.my_votes += 1; app.total_votes += 1">
Vote
</button>
Reactive Updates
When a w-set mutation is applied, the server responds with out-of-band swap instructions. The client-side JavaScript (what.js) finds every element with a matching w-bind attribute and updates its text content.
This means you can display the same session variable in multiple places and they all stay in sync:
<!-- Header -->
<span>Cart (#session.cart_count#)</span>
<!-- Sidebar -->
<p>You have #session.cart_count# items in your cart.</p>
<!-- Both update when cart_count changes -->
<button w-set="session.cart_count += 1">Add to Cart</button>
what.js client script. It is included automatically by the framework.
Session Configuration
Configure sessions in what.toml:
[session]
enabled = true # default: true
store = "sqlite" # "sqlite" (default) or "cloudflare-kv"
cookie_name = "w_session" # default: "w_session"
max_age = 604800 # seconds, default: 7 days
secure = true # Secure flag on cookie, default: true
database = "data/sessions.db" # SQLite file path
| Key | Default | Description |
|---|---|---|
enabled | true | Enable or disable the session system |
store | "sqlite" | Storage backend (sqlite or cloudflare-kv) |
cookie_name | "w_session" | Name of the session cookie |
max_age | 604800 | Session lifetime in seconds (7 days) |
secure | true | Set the Secure flag on the cookie (auto-disabled in dev mode) |
database | "data/sessions.db" | Path to the SQLite database file |
run-what dev), the Secure flag is automatically disabled so cookies work on localhost without HTTPS.
Clearing Session Data
Two built-in POST endpoints let users clear their session:
Clear data only
Removes all user-defined session data but keeps the session ID intact:
<form method="post" action="/w-session/clear-data">
<button type="submit">Clear My Data</button>
</form>
Full reset
Destroys the current session entirely and creates a new one:
<form method="post" action="/w-session/reset">
<button type="submit">Reset Session</button>
</form>
_ (underscore) are reserved by the framework and cannot be set via w-set.