Webform integration
Webform Integration
When to Use
Submit webforms from Next.js to Drupal using the Webform REST module. Supports client-side and server-side (API route) submission.
Steps
1. Install Webform REST module
composer require drupal/webform_rest
Enable: Webform, Webform REST, REST UI
2. Configure REST resource
Visit /admin/config/services/rest:
- Enable "Webform Submit" resource
- Methods: POST
- Accepted request formats: json
- Authentication providers: cookie (or oauth2 if needed)
- Save
3. Set permissions
Visit /admin/people/permissions:
- Grant anonymous users: "Access POST on Webform Submit resource"
4. Server-side submission (recommended)
// app/api/contact/route.ts
import { NextRequest, NextResponse } from "next/server"
import { drupal } from "@/lib/drupal"
export async function POST(request: NextRequest) {
try {
const body = await request.json()
const url = drupal.buildUrl("/webform_rest/submit")
const result = await drupal.fetch(url.toString(), {
method: "POST",
body: JSON.stringify({
webform_id: "contact",
name: body.name,
email: body.email,
message: body.message,
}),
headers: {
"Content-Type": "application/json",
},
})
if (!result.ok) {
throw new Error("Submission failed")
}
return NextResponse.json({ success: true })
} catch (error) {
return NextResponse.json(
{ error: (error as Error).message },
{ status: 400 }
)
}
}
5. Frontend form submission
const handleSubmit = async (event: FormEvent) => {
event.preventDefault()
const response = await fetch("/api/contact", {
method: "POST",
body: JSON.stringify({
name: formData.name,
email: formData.email,
message: formData.message,
}),
})
if (response.ok) {
// Show success message
}
}
6. Client-side submission (not recommended)
// Exposes Drupal URL and webform_id
const response = await fetch(
`${process.env.NEXT_PUBLIC_DRUPAL_BASE_URL}/webform_rest/submit`,
{
method: "POST",
body: JSON.stringify({
webform_id: "contact",
name: formData.name,
email: formData.email,
}),
headers: { "Content-Type": "application/json" },
}
)
Decision Points
| Approach | Pros | Cons |
|---|---|---|
| Server-side (API route) | Hides Drupal URL, adds validation layer | Extra route to maintain |
| Client-side | Simpler, direct | Exposes Drupal URL and form IDs |
Common Mistakes
- Client-side submission in production — Security exposure. WHY: Drupal URL and webform IDs are visible.
- Missing CORS configuration — Client-side submission fails. WHY: Drupal needs CORS headers for cross-origin requests.
- Not validating server-side — Accept invalid data. WHY: Client validation can be bypassed.
- Hardcoding webform_id — Brittle integration. WHY: Use environment variables or Drupal JSON:API to fetch form config.
See Also
- Security Best Practices
- Fetching Content (for dynamic form fetching)
- Environment Variables