History, errors, and enhancement

Test without JavaScript

Complete the core navigation and form flow using only the href, action, method, validation, and full server responses.

Progressive enhancement is not a slogan. Disable JavaScript and complete the core workflow as an ordinary website.

Links need real href values. Forms need action, method, named controls, and submit buttons. The server must return complete pages with preserved safe values and readable validation errors.

Native forms support GET and POST, not DELETE or PATCH. Give an enhanced destructive action a POST fallback route:

<form action="/tasks/42/delete" method="post"
  hx-delete="/tasks/42"
  hx-target="closest li"
  hx-swap="delete">
  <button>Delete</button>
</form>

The server supports both routes with the same authorization and deletion logic. Without JavaScript, the POST returns a redirect to /tasks or a full page with the updated list. With HTMX, the DELETE returns a fragment-compatible result and HTMX removes the row. DevTools with JS on shows DELETE /tasks/42. With JS off, the Network panel shows POST /tasks/42/delete followed by a document navigation.

Submit the new-task form with an empty title and no JS. You should land on a full page that still shows the form, the typed value if safe, and “Title is required.” If you get a blank list or a generic error page, the server contract is broken.

Active search can fall back to a normal GET submit. Inline completion can fall back to a small POST form and full-page response. The enhanced experience may be faster, but it should not be the only path to the essential task.

Also simulate a failed script load, not only a deliberate browser setting. Progressive enhancement protects the period before HTMX loads as well as users who disable it.

Bookmark /tasks?status=complete, open it in a fresh tab, and confirm the server renders the same filtered list without HTMX. That proves your pushed URLs and full-page routes agree.

Walk through your task interface with JS off: create a task, trigger validation, delete a row, follow a filter link. If any step dead-ends, fix the server response before adding more client attributes.

Lesson completed