6.0 KiB
6.0 KiB
Status
Ready for Review
Story
As an inquirer, I want a guided contact form, so that I can convey project essentials quickly.
Acceptance Criteria
- Fields: project type, timeline, budget range, references/links; validation via zod.
- Success page with next steps/SLA.
- Optional route to persist submissions (or email integration) without breaking existing auth.
- API response contract is explicit and enforced: returns JSON
{ ok: boolean, message?: string }on both success and error. - Basic server-side abuse mitigation in place: rate limiting of 5 requests per minute per client IP with appropriate error messaging in the response shape.
Tasks / Subtasks
- Form fields and validation (AC: 1)
- Extend
src/app/contact/page.tsxwith fields:projectType(select),timeline(select or free text),budgetRange(select),references(textarea or list of URLs) - Convert to React Hook Form + Zod schema for client-side validation; enforce valid email and optional URL list parsing
- Keep existing first/last/subject/message fields; align labels and helper text with tokens
- Extend
- Submission handling (AC: 1, 3)
- Replace direct Web3Forms POST with internal API route
src/app/api/contact/route.tsthat forwards to: a) Web3Forms (current behavior) if configured, or b) Cloudflare Worker/D1 endpoint if env vars provided (optional persistence) - Sanitize inputs server-side; add basic rate limiting (IP-based, 5 requests/minute per IP)
- Return structured JSON
{ ok: boolean, message?: string }
- Replace direct Web3Forms POST with internal API route
- Success page (AC: 2)
- Add
src/app/contact/success/page.tsxwith confirmation content and what happens next (SLA) - After successful submission, navigate to
/contact/successwith a minimal state (no PII in URL)
- Add
- A11y and UX
- Error messaging announced to screen readers; inputs with
aria-invalidandaria-describedby - Disabled submit state and spinner while submitting; keyboard-friendly focus order
- Privacy note near submit; link to
/privacy
- Error messaging announced to screen readers; inputs with
- Quality and Integration Verification
- Lint/build pass:
npm run lint/npm run build - IV1: Rate limiting or basic abuse mitigation is active (manual check)
- IV2: Error states accessible and clear (screen reader test)
- IV3: No PII leakage in logs (log only metadata, never form body)
- Lint/build pass:
Dev Notes
- Context
- PRD Story 1.7. Contact page exists and posts to Web3Forms. This story moves submission to an internal API, adds guided fields, and adds a success page. Cloudflare D1 is optional and must not affect Prisma schema.
- Relevant Source Tree
- Contact page:
src/app/contact/page.tsx - New success page:
src/app/contact/success/page.tsx - New API:
src/app/api/contact/route.ts(POST) - Utilities:
src/components/Forms.tsx(reuse Input/Textarea components);src/lib/utils.ts
- Contact page:
- Implementation Guidance
- Zod schema example fields:
projectType: enum(['Commercial','Music Video','Narrative','Other']),timeline: string,budgetRange: enum(['<10k','10–50k','50–200k','200k+','TBD']),references: string(parse to URLs),firstName/lastName/email/subject/message. - API route: forward payload; for Cloudflare, use
fetch(CF_CONTACT_ENDPOINT, { method:'POST', headers: { Authorization: CF_CONTACT_AUTH, 'Content-Type': 'application/json' }, body }); do not include secrets in client bundle. - Environment variables:
NEXT_PUBLIC_WEB3FORMS_ACCESS_KEY(existing), optionalCF_CONTACT_ENDPOINT,CF_CONTACT_AUTH. - Rate limit: simple in-memory map 5/min/IP; acceptable for MVP.
- Zod schema example fields:
Testing
- Manual
- Validation: invalid email blocks submit; references accept comma/newline separated URLs
- After success, user lands on
/contact/success; browser back shows preserved inputs or reset as designed - Privacy and Terms links open and are accessible
- Regression
- Ensure no auth flows are affected; admin pages continue to work
- Logs contain no PII
Change Log
| Date | Version | Description | Author |
|---|---|---|---|
| 2025-09-24 | v1 | Initial draft from PRD Story 1.7 | Scrum Master |
Dev Agent Record
Agent Model Used
gpt-5.1-codex
Debug Log References
- 2025-09-24: Created API route for contact form submissions with Zod validation and rate limiting
- 2025-09-24: Created success page for contact form submissions
- 2025-09-24: Updated contact page with new guided fields and React Hook Form integration
Completion Notes List
- Implemented form fields: project type (select), timeline (input), budget range (select), references (textarea)
- Added Zod schema validation for all form fields with proper error messages
- Integrated React Hook Form with Zod resolver for client-side validation
- Created API route at /api/contact/route.ts that forwards to Web3Forms or Cloudflare endpoint
- Implemented rate limiting (5 requests/minute per IP) with appropriate error messaging
- Added success page at /contact/success with next steps information
- Maintained existing fields (firstName, lastName, email, subject, message) and added new guided fields
- Added privacy notice and consent checkboxes with proper accessibility
- API returns structured JSON { ok: boolean, message?: string } on success and error
- Form redirects to success page after successful submission
- All error states are accessible and announced to screen readers
- Form includes disabled state and spinner during submission
File List
- src/app/contact/page.tsx
- src/app/api/contact/route.ts
- src/app/contact/success/page.tsx
QA Results
- Form fields properly validated on client and server side
- Rate limiting active and properly reports when limit is exceeded
- All error messages are accessible and announced to screen readers
- Form submission redirects to success page after successful submission
- API returns proper JSON response format as required
- No PII leakage in logs (only metadata logged, not form body)
- Privacy notice and consent links are accessible
- Form maintains keyboard navigation and focus order
- Build passes successfully with all new functionality