Forms are the primary mechanism for interactivity on the web.
But for all of their importance, forms can be incredibly frustrating for developers and users alike.
There are a lot of moving parts to consider:
You need to validate user input and handle complex data structures, while being secure from bots and data-stealing attacks. The UI should inform users of any issues as quickly as possible, and be accessible for all.
The Professional Web Forms Workshop will equip you with the tools to handle all of these challenges and more.
Form Validation
HTML has several attributes built-in that help with form element validation. Unfortunately, they're not enough on their own. On the client-side, bad actors can bypass checks by manually adding the novalidate
attribute or making requests directly. On the server side, there's no standard way to respond to validation errors other than a generic 400 status code.
In this section, you'll implement a base level of form validation:
- Essential HTML attributes for validation
- Server-side validation with JSON responses
- Displaying errors with the
useActionData
hook - Disabling default browser validation messages with
useHydrated
Accessibility
Accessibility is often an afterthought, but should be a priority. While forms are just one part of the accessibility equation, they're a big one. In this section, you'll learn how to make sure your forms accessible and usable by all of your application's users:
- Properly associating labels with input fields
- Adding appropriate ARIA attributes when necessary
- Manage keyboard focus in response to errors and user interactions
- Creating and using a
useFocus
hook to direct the user’s focus - Considerations for accessibility testing
Schema-Based Validation
Manually writing conditional checks for every field in every form is tedious and error-prone: Is there content in the field? Is it the right type? Is it within the acceptable range? There must be a better way!
Fortunately, the combination of the Zod and Conform libraries makes it easy to define reusable declarative schemas to validate form data on the client and server:
- Safely replace HTML validation attributes with schemas
- Zod error handling & message customization
- Progressively enhanced validation with Conform
- Share type-safe validation logic between client and server
File Uploads
Forms need to support more than just text. Images, videos, audio files, and other documents need a different type of input. Depending on the size of the file, you'll have considerations for how and where it is uploaded. In this section, you'll learn how to handle file uploads in a secure and efficient way:
- Uploading images from an
ImageChooser
component - Handling file uploads on the server
- Schema validation for file uploads with Zod
Complex Data Structures
The FormData
API does not support representing objects or arrays– only key/value pairs. It also won't allow you to nest forms within each other. This makes representing complex data structures difficult without jumping through some hoops. Luckily for us, Conform has a great solution when your forms get complex. Here you'll practice:
- Infer field types with Zod
- Nesting objects as a form
- Represent arrays of fields with the
useFieldList
utility - Add and remove items with Conform's
intent
buttons
Spam Prevention with Honeypots
Spam bots are constantly crawling the web, looking for forms to submit junk data to boost their client’s search engine rankings and find holes in your security. This can strain server resources, contaminate databases, and cause other unforeseen consequences. One way to combat this is by using a "honeypot", which will prevent a form from being submitted by a bot. This section will teach you how to:
- Create a simple hidden-field validation
- Add a configurable honeypot instance to an action
- Prevent form submissions that are too fast
- Use environment variables for encryption seeds
CSRF Protection
Cross-Site Request Forgery (CSRF) attacks are a type of malicious exploit where a user is tricked into performing an action they did not intend to. This is usually done by embedding a link or form in a page that the user is already authenticated to. Think of a user logged into their bank account clicking a link that transfers money from their bank account to the attacker's. To prevent this type of attack, you'll want to:
- Create a signed cookie in the user's browser
- Include unique user tokens in forms
- Validate tokens on the server via request headers
Rate Limiting
You definitely want to prevent bad actors from making tons of requests to try to brute-force their way into your app or cause general chaos. However, malicious intent and spam aren't the only reasons you need to protect your site. Even too many legitimate requests can cause problems. Rate limiting is a way to prevent users from overloading your server with requests. Here you'll learn:
- Considerations for different limits for
GET
vs.POST
requests - Implementing basic rate limiting with Express middleware
- Tiered rate limiting depending on which form is being submitted