Symptom
On desktop, browser Back does not walk back through visited settings tabs. Reproduced 2026-07-28 on staging (:rc-0.9):
- Open Settings, click through Context → Profile → Telegram → Support.
- Press Back → lands on Context, not Telegram.
- Press Back again → leaves Settings entirely (back to the chat).
Four tab visits produced exactly one history entry.
Cause — deliberate, with an unconsidered desktop consequence
packages/web/src/hooks/use-tab-param.ts:
if (pushOnEnter && !isExplicit) {
router.push(url, { scroll: false });
} else {
router.replace(url, { scroll: false });
}
pushOnEnter pushes only on the transition from "no explicit ?tab=" to the first selected tab. Its doc-comment states the intent plainly: "Switching between tabs afterwards still uses replace to avoid piling up one history entry per tab click." use-tab-param.test.ts:164 pins that behaviour ("replaces (no history spam) when switching tabs while already explicit").
Traced against the report:
| Action |
isExplicit |
Navigation |
History |
Arrive at /settings |
false |
— |
[chat, /settings] |
| Click Profile |
false |
push |
[chat, /settings, ?tab=profile] |
| Click Telegram |
true |
replace |
[chat, /settings, ?tab=telegram] |
| Click Support |
true |
replace |
[chat, /settings, ?tab=support] |
| Back |
|
|
/settings → renders Context ✓ |
| Back |
|
|
chat ✓ |
pushOnEnter was added for the mobile drill-down, where there is a real menu level to return to. On desktop there is no menu level — every click is a lateral switch between addressable locations, so replace means Back can never reach them.
The underlying inconsistency
The tab lives in the URL. Something that lives in the URL is a location, and users expect Back to return to a location. Writing it to the URL and then replacing it is the contradiction — it looks addressable (copyable link, works on reload) while behaving like view state.
The "history spam" concern behind the current choice is real but is the normal cost of URL-addressable tabs across the web, and the way out of Settings is the sidebar or the logo, not repeated Back presses.
Options
A — push on every user-initiated tab switch (recommended). Keep replace only for programmatic normalisation (writing the default ?tab= on load), which is what replace is for. Back then walks the tabs on desktop and still returns to the menu on mobile, since entering from the menu is itself a user-initiated switch.
Cost: leaving Settings after many clicks takes many Back presses.
B — treat the tab as pure view state, never push. Mobile then relies solely on the "‹ Settings" control, and a gesture-Back leaves Settings — which is precisely what pushOnEnter was introduced to fix. Not recommended.
Whichever is chosen, use-tab-param.test.ts:164 changes with it. Making the change without updating that test is impossible by construction, which is the right kind of friction here.
Second location, same class
packages/web/src/components/agent-settings-page-content.tsx:128 calls useTabParam("general", visibleTabs, initialTab) with no options, so pushOnEnter is false and every agent-settings tab switch replaces — including the first. Back never walks those tabs either. Whatever is decided for settings should be applied there too, or the two pages will behave differently for no reason a user can perceive.
Impact
Minor and non-blocking: no data loss, no broken state, the tabs themselves work and remain deep-linkable. It is a navigation-expectation mismatch that becomes noticeable exactly when someone explores several tabs and tries to step back.
Found during 0.9.0 Flow-4 testing.
Symptom
On desktop, browser Back does not walk back through visited settings tabs. Reproduced 2026-07-28 on staging (
:rc-0.9):Four tab visits produced exactly one history entry.
Cause — deliberate, with an unconsidered desktop consequence
packages/web/src/hooks/use-tab-param.ts:pushOnEnterpushes only on the transition from "no explicit?tab=" to the first selected tab. Its doc-comment states the intent plainly: "Switching between tabs afterwards still usesreplaceto avoid piling up one history entry per tab click."use-tab-param.test.ts:164pins that behaviour ("replaces (no history spam) when switching tabs while already explicit").Traced against the report:
isExplicit/settings[chat, /settings][chat, /settings, ?tab=profile][chat, /settings, ?tab=telegram][chat, /settings, ?tab=support]/settings→ renders Context ✓pushOnEnterwas added for the mobile drill-down, where there is a real menu level to return to. On desktop there is no menu level — every click is a lateral switch between addressable locations, soreplacemeans Back can never reach them.The underlying inconsistency
The tab lives in the URL. Something that lives in the URL is a location, and users expect Back to return to a location. Writing it to the URL and then replacing it is the contradiction — it looks addressable (copyable link, works on reload) while behaving like view state.
The "history spam" concern behind the current choice is real but is the normal cost of URL-addressable tabs across the web, and the way out of Settings is the sidebar or the logo, not repeated Back presses.
Options
A — push on every user-initiated tab switch (recommended). Keep
replaceonly for programmatic normalisation (writing the default?tab=on load), which is whatreplaceis for. Back then walks the tabs on desktop and still returns to the menu on mobile, since entering from the menu is itself a user-initiated switch.Cost: leaving Settings after many clicks takes many Back presses.
B — treat the tab as pure view state, never push. Mobile then relies solely on the "‹ Settings" control, and a gesture-Back leaves Settings — which is precisely what
pushOnEnterwas introduced to fix. Not recommended.Whichever is chosen,
use-tab-param.test.ts:164changes with it. Making the change without updating that test is impossible by construction, which is the right kind of friction here.Second location, same class
packages/web/src/components/agent-settings-page-content.tsx:128callsuseTabParam("general", visibleTabs, initialTab)with no options, sopushOnEnteris false and every agent-settings tab switch replaces — including the first. Back never walks those tabs either. Whatever is decided for settings should be applied there too, or the two pages will behave differently for no reason a user can perceive.Impact
Minor and non-blocking: no data loss, no broken state, the tabs themselves work and remain deep-linkable. It is a navigation-expectation mismatch that becomes noticeable exactly when someone explores several tabs and tries to step back.
Found during 0.9.0 Flow-4 testing.