Forms that work before JS lands
A form with action={serverAction} works as a native HTML POST before any JavaScript runs. When JS hydrates, it enhances submission to be no-refresh. If JS fails entirely, the form still works.
Three layers, top down
| Layer | Behavior |
|---|---|
| HTML only | Native POST → server processes → full reload to the rendered result. |
| + JS | Submission via fetch, no reload, layout state preserved. |
| + React | Optimistic UI, pending states, transitions. |
Why this is a real win
Slow networks, old browsers, JS errors, ad-blockers that nuke the framework — the form keeps working. Server Actions buy you progressive enhancement that traditional React + custom fetch() never had.
Build the HTML submission first, including success, validation failure, expired authentication, and a redirect that does not repeat the POST on refresh. Add pending and optimistic layers only after the non-JavaScript path preserves data and a clear next action. Progressive enhancement does not require recreating every rich interaction without JavaScript. It means the essential transaction survives. A collaborative canvas may require JavaScript; saving an account setting should not lose the user's work because hydration failed. Disable JavaScript and complete the form under a slow connection, then repeat after hydration. Compare network behavior, layout state, focus, and refresh. The enhanced route should improve the experience without becoming the only route that works.