what

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>
Tip: Session variables inside HTML attributes (e.g. 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>
Note: Reactive updates require the what.js client script. It is included automatically by the framework.

Session Configuration

Configure sessions in what.toml:

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
KeyDefaultDescription
enabledtrueEnable or disable the session system
store"sqlite"Storage backend (sqlite or cloudflare-kv)
cookie_name"w_session"Name of the session cookie
max_age604800Session lifetime in seconds (7 days)
securetrueSet the Secure flag on the cookie (auto-disabled in dev mode)
database"data/sessions.db"Path to the SQLite database file
Tip: In dev mode (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>
Note: Both endpoints redirect back to the referring page after completion. Session keys that start with _ (underscore) are reserved by the framework and cannot be set via w-set.