Contact Form API
Relevant source files
The following files were used as context for generating this wiki page:
Introduction
The Contact Form API system provides the functionality for users to submit inquiries to Grapevine, primarily to "Book a discovery call". This feature is a critical lead-generation tool for the business. It is composed of a frontend React component for user interaction and a backend Next.js API route that processes and forwards the submission to an external service.
The system is implemented across the /contact page, which presents the form to the user. The frontend handles user input, validation, and state management, while the backend API route provides a secure proxy to a third-party form handling service. Data handling practices for information collected through this form are outlined in the Privacy Notice.
Sources: components/contact-form.tsx, app/api/contact/route.ts, app/contact/page.tsx
System Architecture
The contact form system follows a client-server architecture common in Next.js applications. The user interacts with a form on the client-side, which upon submission, sends a request to a dedicated API route within the same Next.js application. This API route then acts as a backend-for-frontend (BFF), validating the data and securely forwarding it to an external form processing service.
End-to-End Data Flow
The following sequence diagram illustrates the complete process from a user filling out the form to the data being stored in the external backend.
This diagram shows the client-side validation, the API call to the Next.js backend, the server-side validation, and the subsequent call to the external FormBackend service.
Sources: components/contact-form.tsx:90-130, app/api/contact/route.ts:12-68
Frontend: ContactForm Component
The user-facing part of the system is the ContactForm component, a client-side React component responsible for rendering the form, managing its state, and handling user interactions.
Sources: components/contact-form.tsx
State Management
The component uses useState hooks to manage the form's state:
formData: Stores the values of the input fields.errors: Holds validation error messages for each field.isSubmitted: A boolean flag to control the display of the success message.isLoading: A boolean flag to show a loading state on the submit button during API calls.charCount: Tracks the number of characters in the messageTextarea.
Sources: components/contact-form.tsx:38-48
Form Data Structure
The data collected from the form is defined by the FormData interface.
| Field | Type | Description | Constraints |
|---|---|---|---|
fullName | string | The user's full name. | Required |
workEmail | string | The user's work email address. | Required, must be a valid email format. |
iAmA | string | User's self-identified role (TMC, Corporate, etc.). | Required |
companyName | string | The user's company name. | Required |
role | string | The user's job title. | Required |
message | string | An optional message from the user. | Max 250 characters. |
Sources: components/contact-form.tsx:18-26, components/contact-form.tsx:165-168
Validation Logic
Client-side validation is performed by the validateForm function before the form is submitted.
- It checks that
fullName,workEmail,companyName,iAmA, androleare not empty. - It uses a regular expression in the
validateEmailutility function to ensure theworkEmailfield is a valid email address. - If any validation fails, the
errorsstate is updated, and the form submission is prevented.
The flow of client-side validation and submission is as follows:
UI Feedback
The component provides clear feedback to the user:
- Loading State: When
isLoadingis true, the submit button is disabled, its text changes to "Submitting...", and a spinning loader icon appears. - Success State: When
isSubmittedis true, a success message is displayed usingframer-motionfor a smooth animation. The user can dismiss this message. - Error State: Validation errors are displayed as helper text below each respective input field.
Sources: components/contact-form.tsx:173-195, components/contact-form.tsx:294-306
Backend: /api/contact Route
The backend is a Next.js API route that handles POST requests to /api/contact. Its primary role is to validate the incoming data and forward it to an external form processing service.
Sources: app/api/contact/route.ts
Endpoint Definition
| Property | Value |
|---|---|
| Path | /api/contact |
| Method | POST |
| Request Body | ContactFormData (JSON) |
| Success Response | 200 OK with { success: true, ... } |
| Error Responses | 400 Bad Request, 500 Internal Server Error |
Request Processing
- Data Parsing: The handler first parses the JSON body from the incoming
NextRequest. - Server-Side Validation: It performs its own validation to ensure all required fields (
fullName,workEmail,companyName,iAmA,role) are present and that the email format is valid. This duplicates the client-side validation for security. - Environment Variable Check: It checks for the
FORMBACKEND_URLenvironment variable. If this is not set, it returns a500server configuration error. - Proxy to External Service: It sends a
POSTrequest to the URL specified inFORMBACKEND_URL. The body of this request is a slightly remapped version of the form data. - Response Handling:
- If the external service responds successfully, the API route returns a
200 OKwith a success message. - If the external service returns an error, the API route logs the error and forwards a corresponding error response to the client.
- If the external service responds successfully, the API route returns a
Sources: app/api/contact/route.ts:12-68
Data Mapping
The data received from the client is mapped before being sent to the external FormBackend.
Client Field (formData) | Backend Field (sent to FormBackend) |
|---|---|
fullName | name |
workEmail | email |
companyName | companyName |
role | role |
iAmA | iAmA |
message | message |
Sources: app/api/contact/route.ts:46-54
Integration and Usage
The ContactForm component is integrated into the /contact page.
// app/contact/page.tsx
import ContactForm from "@/components/contact-form";
// ...
export default function Contact() {
// ...
return (
<>
{/* ... */}
<ContactForm />
</>
);
}
The page also includes JSON-LD schema for SEO purposes, generated by generateContactPageSchema and generateBreadcrumbSchema. The contact page schema specifies the contact type as "sales" and links to the /contact URL.
Sources: app/contact/page.tsx:29, lib/seo.ts:192-207
Data Privacy and Handling
According to the Privacy Notice, personal data collected through website forms is processed to fulfill services. The company, Your Grapevine Ltd, acts as the data controller.
- Purpose of Collection: Data is collected to communicate with potential clients and provide services.
- Data Collected: Information includes full names, email addresses, and other details provided in the form.
- Third-Party Sharing: The privacy policy states that data may be shared with selected third parties for service performance. The API route's use of
FORMBACKEND_URLis an example of this. Other mentioned third parties include Rocket Science Group (Mailchimp) and Amazon Web Services (AWS) for hosting. - User Rights: Users have rights regarding their data, including access, correction, and erasure, which can be exercised by contacting
info@grapevine.travel.
Sources: app/policy/privacy/page.tsx:18-24, app/policy/privacy/page.tsx:55-63, app/policy/privacy/page.tsx:210-225, app/policy/terms/page.tsx:32-38