Server-side safety

Build a complete feedback form

Combine accessible HTML, browser validation, FormData, HTTP handling, server validation, security controls, and useful result states.

8 minute lesson

~~~

Build a feedback form that works from the browser all the way to a server decision.

The form collects:

  • name
  • email address
  • category
  • message
  • optional screenshot

Start with native HTML

Give every control a visible label and stable name. Group related choices with fieldset and legend. Add concise help before the fields that need it.

Use /feedback as the action and POST as the method. Add multipart encoding for the screenshot. The form must work when JavaScript is unavailable.

Define the server contract

Write down the accepted fields before implementing the endpoint.

Validate required values, lengths, the category allowlist, and screenshot limits. Treat the original filename and media type as untrusted. Generate a storage name and keep the upload outside executable application files.

Return field errors without erasing valid values. After a successful native POST, redirect to a GET confirmation page.

Add CSRF protection if the form uses cookie authentication. Add request-size and rate limits. Do not log the message body, token, or uploaded bytes by default.

Add JavaScript as an enhancement

Intercept the form’s submit event and send FormData with fetch(). Show idle, pending, success, validation-error, and network-error states.

Disable the active submitter while the request is pending, but make the endpoint safe if the request arrives twice. Reset only after confirmed success.

If the script fails, the native submission path must still work.

Test the failures

Complete the form with only a keyboard. Then test:

  • empty and overlong values
  • a category not present in the page
  • a large file and a renamed non-image
  • a missing or invalid CSRF token when required
  • repeated submission
  • offline mode and a server error
  • refresh after success
  • 200% zoom and narrow screens

You are done when each failure produces an understandable result, preserves safe work, and leaves the form usable.

Lesson completed