Agent Wranglers

Client and server state Required

Keep screen state in the address

Put every choice that changes what a screen shows in the address, such as filters, search, sort, page, tab and the open record. Reloading or sharing the link shows the same screen.

How to do it

Read the state from the query string when the screen loads, and write it back when it changes. Use replace for typing and push for steps people expect Back to undo, such as opening a record or moving to another page of results. Validate each parameter and fall back to a default for bad values. Leave defaults out, so links stay short. Never put personal data or tokens in the address.

Example

const SORTS = ['newest', 'oldest', 'amount'] as const;
type Sort = (typeof SORTS)[number];

export function readOrderFilters(url = new URL(location.href)) {
  const sort = url.searchParams.get('sort');
  return {
    status: url.searchParams.get('status') ?? 'any',
    sort: (SORTS as readonly string[]).includes(sort ?? '') ? (sort as Sort) : 'newest',
    cursor: url.searchParams.get('cursor'),
  };
}

export function writeOrderFilters(filters: Record<string, string | null>, mode: 'push' | 'replace') {
  const url = new URL(location.href);
  for (const [name, value] of Object.entries(filters)) value ? url.searchParams.set(name, value) : url.searchParams.delete(name);
  history[mode === 'push' ? 'pushState' : 'replaceState'](null, '', url);
}
SORTS = {"newest", "oldest", "amount"}

@app.get("/orders")
def order_list():
    sort = request.args.get("sort", "newest")
    filters = OrderFilters(
        status=request.args.get("status", "any"),
        sort=sort if sort in SORTS else "newest",
        cursor=request.args.get("cursor"),
    )
    return render_template("orders/list.html", page=orders.list(current_user().account_id, filters), filters=filters)

How to check

A browser test sets a filter, a sort and page 3, copies the address and opens it in a new context. The same rows show. Back returns to the previous page of results.

For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers app interface playbook: https://agentwranglers.se/playbook/app-ui/client-and-server-state/state-in-url.