C.W.K.
Stream
Lesson 05 of 08 · published

Progressive Enhancement

~20 min · progressive enhancement, no-JS, forms

Level 0Curious
0 XP0/68 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

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

LayerBehavior
HTML onlyNative POST → server processes → full reload to the rendered result.
+ JSSubmission via fetch, no reload, layout state preserved.
+ ReactOptimistic 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.

Code

A form that survives without JS·tsx
import { redirect } from 'next/navigation';

export default function ContactForm() {
  async function submit(formData: FormData) {
    'use server';
    await saveMessage({
      name: formData.get('name') as string,
      email: formData.get('email') as string,
      message: formData.get('message') as string,
    });
    redirect('/thank-you');
  }

  return (
    <form action={submit} className="space-y-2">
      <input name="name" required />
      <input name="email" type="email" required />
      <textarea name="message" required />
      <button>Send</button>
    </form>
  );
}

External links

Exercise

Disable JavaScript in your browser and submit a Server Action form. Confirm the submission lands and the redirect works. Re-enable JS and watch the same form behave seamlessly.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.