Accessible Clients and Offline State
Prerequisites: S3 contracts; S5 HTTP; S6 consistency; elementary HTML, JavaScript, and forms. Budget: 30-45 hours. Outcome: build a user-visible state machine whose failure and accessibility behavior can be tested.
Diagnostic and entry bridge
Build a labeled form that submits a value and displays a server error without losing the input. Operate it using only a keyboard. If this is unfamiliar, complete the relevant HTML/forms and asynchronous-programming material from the frontend library or Eloquent JavaScript before scheduling this studio. That preparation is additional to its budget.
State is part of the user contract
A save operation has more states than “loading” and “done”: clean, locally edited, saving, saved, failed, and conflicting are useful distinctions. Offline support adds a locally persisted change that has not yet been accepted remotely. Calling that state “saved to server” gives a false guarantee.
Separate durable local intent from transient rendering state. Give an operation a stable identity and a resource version. On retry, preserve the logical identity rather than creating a new operation. A server can reject an update whose expected version no longer matches, making the conflict explicit.
Worked example: stale response overwrites new intent
The user searches for “ca,” then “cat.” The cat request finishes first, then the older ca response arrives and overwrites the results. Both responses are individually valid, but the final UI violates the user's latest intent.
Tag requests with a monotonically increasing local generation. Update the visible results only if the response belongs to the current generation. Cancellation can save work, but correctness should not depend on cancellation always succeeding. Include a real empty-results state distinct from an error or unfinished request.
Worked example: offline conflict
Two clients read document version 7. Client A saves a new title, producing version 8. Offline client B later sends a replacement title with expected version 7. Blind replacement loses A's edit.
Reject the stale version and present both values with a resolution path. For a single title field, a conflict UI may be simpler and more honest than introducing a general-purpose CRDT. A merge algorithm must follow domain semantics; “last timestamp wins” additionally needs assumptions about clocks and acceptable lost edits.
Guided assignment
Build a small editable note client with a fake server supporting read, conditional update, and injected latency/failure. Include local persistence, retry, stale-response protection, and an explicit conflict state. Provide a “discard local change” action whose consequence is clear.
Use actual labels, visible focus, keyboard-operable controls, and programmatically associated validation messages. Preserve input after failed submission and manage notifications so a screen-reader user can learn the result. Follow the W3C forms tutorials for concrete implementation guidance. Automated checks supplement, rather than replace, manual keyboard and assistive-technology testing.
Acceptance: an older search response cannot overwrite newer results; offline edits survive reload; conflicts preserve both versions until resolution; a keyboard-only user can edit, encounter an error, repair it, and save. Record each state transition, manual test steps, environment, and any assistive technology actually used. Do not claim testing you could not perform.
Independent transfer
The user switches accounts while an old request is pending. Is a search-generation counter alone enough? Check: response acceptance must also respect the active identity or context; cached and local data need an explicit ownership policy.
For deeper study, use the local frontend security text, Eloquent JavaScript, and the existing modern paradigms guide. Defend your conflict policy and accessibility evidence using the rubric. This studio introduces client-system engineering; it does not claim complete frontend-specialization coverage.