biohazard-vfx/docs/stories/1.7.contact-smart-form.md
nicholai ed55376b9c
Some checks are pending
Build and Push to Docker Hub / Push Docker image to Docker Hub (push) Waiting to run
Build and Push Docker Image / build-and-push (push) Waiting to run
bmad-planning-complete
2025-09-24 10:54:01 -06:00

94 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Status
Approved
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','1050k','50200k','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
{{agent_model_name_version}}
Debug Log References
Completion Notes List
File List
QA Results