Why did my filters reset when I returned to the list?
Opening a course detail should not mean starting the search again. Separate applied filters from reading position, then connect missing items, failed queries and new tabs to a specification and an engineering/QA handoff.
Split the request before deciding where to save filters
Imagine someone browsing Design courses in the North district on page 2. They open Poster Making, read the details, then return to page 1 for every district. Saving a filter value is only part of this fictional problem. The applied conditions, the place they were reading and the results currently on screen must agree.
A single last-used value sounds sufficient until another tab starts browsing cooking classes. One shared value can overwrite the Design visit. It also cannot reproduce the conditions from a shared address. Separate committed public filters, unapplied edits and the position within this particular list visit before choosing storage.
Use that distinction as the first planning deliverable. Each category needs a lifetime and a fallback when its state is missing. Otherwise engineering may preserve a control while the actual results reset, leaving a screen that looks correct but behaves incorrectly.
Example contract for a public course catalogue.
| State | Example | Storage and scope |
|---|---|---|
| Applied conditions | Design / North / start date / page 2 | URL; sharing, reload and history traversal |
| Unapplied edits | A different district before Apply | Current screen; reset from the traversed entry |
| Reading position | Poster Making link and relative position | Per-list-visit context; return to that visit only |
| Result data | Courses, order and count | Revalidate; historical results are not promised |
Share the conditions, keep position with the visit
MDN distinguishes adding an entry with pushState from replacing one with replaceState. URLSearchParams handles query-string values. These are browser primitives, not a product policy. Planning still has to decide which action deserves an entry.
For this example, category, district, sort and page are public applied conditions in the URL. Personal queries and authentication information are excluded. Associate the remembered course and position with that specific list visit, not a global last position. A new tab can then open the conditions without needing the original tab’s position.
The same address does not promise an identical list forever. Courses close or disappear. The commitment is current results under the same conditions. A service that needs a historical view must separately preserve its observation time and result set; that is a different requirement.
This case is about browsing current public results.
| Option | What it offers | Decision |
|---|---|---|
| One global last-used state | Simple continuation on one device | Reject: tab interference and weak sharing |
| Put every state in the URL | Share filters and position | Reject: draft edits and visit position do not need sharing |
| Public filters in URL; position per visit | Separate sharing from returning | Choose; no promise of a historical result set |
Specify how many history entries Apply creates
Adding an entry for every edit makes Back retrace unfinished filter work. Here, controls edit a draft until Apply is pressed. Applying a changed category, district or sort resets to page 1 and adds one entry. Applying a state identical to the current committed state adds none.
Pagination preserves filters and sort. Back and Forward read existing entries and must not add another. Restore both committed and draft controls from the entry URL before querying. An unfinished draft must not leak into an older list visit.
Defaults are all categories, all districts, start-date order and page 1. An unknown district, a negative page or a duplicate condition key uses the documented default for that field. Explain the correction and replace the current entry. A previously valid page that disappears because results shrink is handled separately.
Editing a draft is not navigation.
| Action | Conditions and screen | History |
|---|---|---|
| Edit a filter | Draft only; committed results remain | No change |
| Apply changed filters or sort | Page 1; query committed conditions | Add one entry |
| Apply identical conditions | Keep current state | No additional entry |
| Change page | Keep filters and sort | Add one entry |
| Back or Forward | Synchronize controls and results from that entry | No additional entry |
| Malformed URL value | Use field default and explain | Replace current entry |
A return does not make an old response current
Before opening details, associate the list address, course identity, position and input method with that visit. Use Back only when the immediate predecessor is a verified same-tab list visit. Otherwise navigate to a validated list address. With no return context, offer the default catalogue link, not blind navigation to a previous external website.
Query current results after returning. Comparing filters alone cannot distinguish an older retry for the same conditions. Check both the current visit and newest request sequence before applying a response. Cancelling a previous request is useful, but does not replace the final eligibility check.
Restore position after current results render. If the course remains on that page, reveal it; for keyboard entry, focus its link. If absent, return to the results heading and explain the changed list. Cancel a delayed automatic move if the reader has already started another interaction. Give restoration one owner so browser restoration and application code do not compete.
Discard an old response, then check the current request when it arrives.
Read the flow
- Current visit and newest request both match?
- Yes: Render results for the current conditions → After render, return to item/heading unless another interaction has started
- No: Discard old response; await the current request → Check again
Include the cases where the old item is gone
Page 2 may survive while the remembered course moves elsewhere. Searching every page automatically can delay return while results keep changing. This case looks only within the current page. If the item is absent, retain the filters and use the results heading instead of resetting the catalogue.
A failed query keeps the URL and applied conditions and offers Retry. Hide previous results so they cannot look like the new query’s output. A successful zero-result response is a different state. If the requested page exceeds the current last page, retain filters and sort, move to the last valid page and explain why. Zero matches uses page 1. Replace the current entry for this correction.
The buttons below compare fixed example messages; they do not query a course server. Opening a shared list address in a new tab starts at the results heading for those conditions. It must not inherit another person’s scroll or focus.
Fictional courses and responses; these are fixed message examples.
Open the example
Design / North / start date / page 2. Poster Making remains in current results. Reveal it and, for keyboard entry, focus its link.
Keep filters and page 2. The remembered course is not on this page. Continue from the results heading.
Keep Design / North / start date / page 2. Hide previous results and offer a retry for these conditions.
Page 2 no longer exists for these conditions. Use the last valid page, page 1 in this example, and replace the current entry.
Ask AI to find missing transitions before storage code
A request for filter-saving code can jump straight to implementation. First give the entry route, the moment conditions become committed, the return target and the failure policy. Ask for missing transitions within that scope.
If a proposal saves only the last scroll position, ask whose position it is after another tab, a deleted item or a late response. If it puts everything in the URL, ask it to separate shareable public conditions from visit-specific context. Adopt a suggestion only after comparing its behavior against the decision table and expected results.
The prompt below is an unexecuted example. A follow-up can add a retry under identical conditions, direct detail entry and another filter action during loading. For every new condition, identify the corresponding transition in the specification and acceptance case in QA. A longer answer is not evidence that these links are correct.
Example prompt: We are designing a public course catalogue. A reader views Design / North / start-date order / page 2, opens details and returns. Applied filters go in the URL; return position belongs to the specific list visit. Find missing conditions for draft versus applied filters, Back, new tabs, item deletion and retries with identical conditions. For each, provide the screen message, state change, engineering handoff and QA expectation. Exclude personal queries and infinite scrolling.
Connect the planning decision to screens and responses
The planning document records the restoration commitment and exclusions. The specification maps Apply, loading, failure and return to messages and actions. Naming a storage mechanism alone leaves room for implementations with identical screens and contradictory Back behavior.
Agree on sorting with engineering. Use a stable course-identity order to break equal start dates. That prevents ties from being arbitrarily reordered, but additions and deletions can still change pagination. The response contract should expose the applied conditions, count and page range; it must not be described as preserving the old order.
W3C’s focus-order guidance emphasizes meaningful, operable keyboard navigation. Returning to a surviving course link or the results heading is the policy selected here with that principle in mind, not a specific target required by WCAG. Check visible focus and the next Tab destination in the actual interface.
Name the document and the behavior it must settle.
| Owner | Record | Check against |
|---|---|---|
| Planning | Restoration scope, alternatives and exceptions | Defaults, sharing, direct entry and deletion |
| Engineering | URL validation, history, request sequence and sorting contract | Applied conditions match current response |
| Design | Loading, failure, changed-list messages and focus | Desktop, mobile and keyboard flow |
| QA | Input, transition sequence, expected and observed results | Twelve cases below and actual responses |
| Operations | Closing, deletion and shrinking-result fixtures | Old results are not mistaken for current ones |
One successful Back click is not the whole check
Record the URL, applied-filter display and actual results together. Restored controls with results from another query are a failure. The table below is an acceptance plan for implementation, not a claim that a real course service has already passed integration testing.
Repeat the same sequence on desktop and mobile, including keyboard entry into details. Slow the query and apply another filter while waiting. Old results and delayed focus must not take over. Reproducible handoff needs the same conditions and failure policy across input methods.
Attach observed results, screens and request evidence to each row.
| Input or transition | Expected result |
|---|---|
| Edit without Apply | Committed conditions/results remain; no entry |
| Apply changed category, district or sort | Page 1; one new entry |
| Apply identical committed conditions | No duplicate entry |
| Page 2 → details → Back | Restore conditions; validate results; return to surviving item |
| Back → Forward | Restore each entry without creating another |
| Open URL in another tab | Current results for same conditions; start at heading |
| Direct detail entry → catalogue link | Default list if no context; no external detour |
| Remembered item deleted or moved to another page | Keep conditions; results heading and change notice |
| Failed query → Retry | Keep conditions; hide old results; new request sequence |
| Old response with identical filters arrives late | Discard unless current visit and newest request match |
| Page range shrinks or becomes empty | Last valid page or page-1 empty state; replace entry |
| Keyboard return; another action during loading | Visible link/heading focus; cancel delayed movement |
Adapt the list commitment before reusing the handoff
This handoff assumes a public catalogue with numbered pages. Infinite scrolling, personalized recommendations or an audit view need a different restoration contract. In particular, do not apply a current-results policy to a screen that must preserve transactions or work records as observed at a specific time.
Before implementation, planning, engineering and design should walk the same fixture. Agree where conditions commit, what survives failure and where a missing item sends the reader. Update the specification and QA together. Different defaults in different documents are unfinished handoff.
For first release, prioritize disagreement between conditions, URL and response. Block release, fix the transition and repeat the same sequence. After deployment, review closing and deletion cases with operations. Any newly discovered exception should update the decision table, message and QA case together.
Public catalogue example. Adapt the scope and defaults to your service.
Public course catalogue — filter state and return handoff Scope: public category, district, sort and numbered pages. Excludes personal queries, login, personalized recommendations and infinite scrolling. Fixture: Design / North / start-date order / page 2 / 20 per page. Open Poster Making in the same tab, then return. Storage: applied public filters belong in the URL. Unapplied edits stay in the screen. Store item identity, position and input method against that particular list visit, never in a shared URL. Ignore absent or mismatched return context. Apply: applying filters or sort resets to page 1 and adds one history entry. Applying the same committed state adds none. Pagination preserves filters and sort. Defaults: all categories, all districts, start-date order, page 1. History traversal: restore the entry URL into both applied and draft controls, then query without adding an entry. Normalize malformed values to documented defaults, explain the change and replace the current entry. Duplicate filter keys take the corresponding default. Return action: use Back only for a verified same-tab immediate list predecessor. Otherwise navigate to a validated list URL. With no list context, offer the default catalogue link. Never use an arbitrary external return URL or blind history.back(). Responses: apply only a response matching the current visit and newest request sequence. A retry for the same conditions has a new sequence. On failure retain conditions and URL, hide previous results and offer Retry. Zero matches is a successful empty result. Position: after rendering current results, reveal the remembered item if it still belongs to that page. For keyboard entry, focus its link. If missing or without return context, use the results heading. Cancel delayed automatic movement if the reader has started another interaction. Browser and app restoration must have one owner. Shrunken page range: retain filters and sort, use the last valid page and replace the current entry. For zero matches use page 1 and the empty state. Explain the change; do not scan every page to chase the old item. Sharing: a new tab opens current results for those conditions from the results heading. Old order, counts and scroll are not guaranteed. Break equal start dates with a stable course-identity order. Ownership: planning decides restoration and exceptions; engineering handles URL validation, history, request sequences and a single restoration owner; design covers state messages and focus; QA uses the 12 acceptance cases; operations checks deletion, closing and reduced-page cases. Release: align the decision sheet, screen transitions and wording, API sort/count contract and QA inputs/expected results. Block release if URL, applied controls and the current response disagree. Verification boundary: a design example based on public browser references and fictional conditions, not a completed integration test of a course service.
Download the engineering and QA handoff
Sources and example conditions
This is a fictional public course catalogue design. Browser references support capabilities and accessibility principles; return behavior, defaults and failure handling are choices for this case. This is not a live course-service integration test or a user-outcome report. AI prompts are unexecuted examples. English and Chinese localize the same Korean case.