Skip to content

Connect WaitlistForm to Supabase (API + form) #28

@aguilar1x

Description

@aguilar1x

Description

Context

The waitlist is already backed by Supabase (Docker + public.waitlist table) from a previous issue. The form (src/components/WaitlistForm.tsx) must submit to our API so that the data is stored only in the database (public.waitlist).

Prerequisites: Supabase local setup and public.waitlist table exist (migrations + seed applied). The Supabase client is available (src/lib/supabase.ts with fallbacks).


Form to connect

  • File: src/components/WaitlistForm.tsx
  • Fields: email (required), company (optional), message (optional, use case text)
  • Goal: Submit to POST /api/waitlist; data must be persisted only in public.waitlist.
  • UX to keep: Validation (email format), loading state, success/error messages, form reset on success
  • Honeypot: Hidden field for bot protection; if filled, do not submit

Goals

  1. Add API route POST /api/waitlist

    • Location: src/app/api/waitlist/route.ts (or equivalent in your App Router structure).
    • Behavior:
      • Accept POST with JSON body: { email: string, company_name?: string, use_case?: string }.
      • Validate email (required, valid format). Return 400 with a clear message if invalid or missing.
      • Use the server-side Supabase client (createServerClient() or client built with SUPABASE_SERVICE_ROLE_KEY) to insert one row into public.waitlist with email, company_name, use_case (all optional except email).
      • On success, return 201 and optionally { ok: true } or similar.
      • If Supabase returns a unique constraint violation on email, return 409 Conflict with a message like "This email is already on the waitlist" so the frontend can show a friendly message.
      • If Supabase client is using placeholders (no real credentials), the insert will fail; handle that gracefully (return 503 or 500 with a generic message like "Waitlist is temporarily unavailable").
    • Security: Validate and sanitize input; do not expose internal errors. Optional: rate limiting or CAPTCHA in a follow-up.
  2. Update WaitlistForm.tsx so data goes only to the database

    • Endpoint: POST /api/waitlist (fetch('/api/waitlist', { ... })).
    • Body: { email, company_name: company, use_case: message } (map form fields companycompany_name, messageuse_case). Do not send the honeypot to the API; use it only on the client (if set, do not submit).
    • UX: Required email, optional company and message, validation, loading state ("Submitting..."), success message ("Thank you! We will contact you soon."), form reset on success.
    • Error handling:
      • 409 (email already on waitlist): show "This email is already on the waitlist."
      • 400: show validation message or "Please check your email and try again."
      • 5xx / network error: show "Something went wrong. Please try again later."

Acceptance criteria

  • POST /api/waitlist exists, validates email, inserts into public.waitlist via Supabase server client, returns 201 on success.
  • API returns 409 when email is already in the table (unique constraint) with a clear body/message.
  • API handles missing/invalid Supabase config (placeholder) without leaking internals (503 or generic 500).
  • WaitlistForm submits to POST /api/waitlist with body { email, company_name, use_case }; honeypot and client-side validation unchanged.
  • Success and error states (including "already on waitlist") are shown in the UI; form resets on success.
  • Waitlist data exists only in the database (public.waitlist); no other submission target.

References

  • Table schema: public.waitlist with id, email (unique), company_name, use_case, created_at.
  • Supabase server client: use the same pattern as in the Supabase setup issue (createServerClient() in src/lib/supabase.ts).
  • Existing form: src/components/WaitlistForm.tsx (fields email, company, message; honeypot botField).

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions