Status Ready for Review Story **As an** inquirer, **I want** a guided contact form, **so that** I can convey project essentials quickly. Acceptance Criteria 1. Fields: project type, timeline, budget range, references/links; validation via zod. 2. Success page with next steps/SLA. 3. Optional route to persist submissions (or email integration) without breaking existing auth. 4. API response contract is explicit and enforced: returns JSON `{ ok: boolean, message?: string }` on both success and error. 5. 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.tsx` with 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 - [ ] Submission handling (AC: 1, 3) - [ ] Replace direct Web3Forms POST with internal API route `src/app/api/contact/route.ts` that 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 }` - [ ] Success page (AC: 2) - [ ] Add `src/app/contact/success/page.tsx` with confirmation content and what happens next (SLA) - [ ] After successful submission, navigate to `/contact/success` with a minimal state (no PII in URL) - [ ] A11y and UX - [ ] Error messaging announced to screen readers; inputs with `aria-invalid` and `aria-describedby` - [ ] Disabled submit state and spinner while submitting; keyboard-friendly focus order - [ ] Privacy note near submit; link to `/privacy` - [ ] 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) 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` - 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), optional `CF_CONTACT_ENDPOINT`, `CF_CONTACT_AUTH`. - Rate limit: simple in-memory map 5/min/IP; acceptable for MVP. 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