Skip to main content
Every published form gets a unique, shareable URL where users can submit responses. The system handles validation, data collection, and success messaging automatically.

Public Form URLs

When you publish a form, it becomes accessible at a slug-based URL:

Slug Generation

Each form is assigned a unique slug on creation:
  • Auto-generated by Prisma
  • URL-safe characters only
  • Guaranteed unique across all forms
  • Persists for the lifetime of the form
Slugs are stored in the database with a unique constraint, preventing collisions even at scale.

Form Rendering

The public form page dynamically renders fields based on the stored schema.

Page Load Flow

1

Extract slug from URL

Next.js dynamic routing captures the slug from the URL path.
2

Fetch form data

The component fetches form configuration from the API using the slug.
3

Render form fields

Fields are dynamically rendered based on their type using the renderField function.

Field Rendering

Each field type has specialized rendering logic:

Form State Management

Form values are tracked in React state:

Value Updates

Each field change updates the centralized state object:
Using a single state object with field IDs as keys makes it easy to construct the submission payload.

Form Submission

When the user clicks Submit, the form data is validated and sent to the API.
1

User clicks Submit

The form’s onSubmit handler is triggered.
2

Browser validation

HTML5 validation runs automatically for required fields and input types (email, number, etc.).
3

Prevent default & submit

The handler prevents default form behavior and sends an API request.
4

Server-side validation

The API validates the submission (see next section).
5

Success message

On success, a thank you message is displayed.

Validation

Multiple layers of validation ensure data integrity.

Client-Side Validation

HTML5 validation runs automatically:
  • required attribute for mandatory fields
  • type="email" for email format
  • type="number" for numeric values

Server-Side Validation

The API performs comprehensive validation before storing responses.
1

Check form ID

2

Validate data object

3

Verify form exists

4

Validate required fields

5

Store response

The API returns specific error messages for validation failures, helping users understand what went wrong.

Response Storage

Responses are stored in the FormsResponses table:

Key Features

The data field stores the entire submission as JSON, allowing flexible schemas without migrations.Example stored data:
When a form is deleted, all its responses are automatically removed via onDelete: Cascade.
createdAt automatically records when each response was submitted for analytics and exports.

Error States

The public form page handles various error scenarios:

UX Features

Loading States

The submit button shows loading state during submission:

Required Field Indicators

Required fields are clearly marked with a red asterisk:
The combination of visual indicators and browser validation provides clear feedback before users submit.

API Endpoint

POST /api/forms/submit Request Body:
Success Response:
Error Response:
Implementation: app/api/forms/submit/route.ts