| Component | Technology | Rationale |
|---|---|---|
| Frontend/Backend | Next.js 16 (App Router) | Full-stack capability with API Routes for rapid development. |
| Styling/UI | Shadcn UI + Tailwind CSS 4 | Provides accessible, well-designed components and utility-first styling for speed. |
| Internationalization | next-intl | Robust routing and component-level translation support for en and pt. |
| Database | MongoDB (via Mongoose) | Flexible, scalable NoSQL store for quick schema iteration. |
| Email Service | AWS SES | Reliable, cost-effective transactional email for verification and assignments. |
| Session Management | Encrypted Cookies (iron-session) | Simple, stateless session management tied to the verification code flow. |
Purpose: Stores the single user/email who is allowed to "Get Started" and create the first group.
| Field | Type | Description |
|---|---|---|
email |
String |
The email of the first-ever user (unique). |
name |
String |
The name of the first-ever user. |
is_registered |
Boolean |
Always true after the first user signs up. Used to guard the /get-started route. |
Purpose: Defines a Secret Santa event.
| Field | Type | Description |
|---|---|---|
_id |
ObjectId |
Unique identifier. |
name |
String |
Event name (e.g., "Family Christmas 2025"). |
budget |
String |
Suggested gift budget. |
date |
Date |
Date of the gift exchange. |
place |
String |
Location/place of the event. |
owner_email |
String |
The email of the user who created the group. |
participants |
Array<ObjectId> |
References to Participant documents. |
invite_id |
String |
Unique, unguessable ID for invitation links. |
is_drawn |
Boolean |
True if the lottery has been executed. |
invitations_sent |
Array<{email: String, sent_at: Date}> |
Tracks which emails the owner has sent invitations to (prevents duplicate sends). |
Purpose: Stores individual user details, their assignment, and the login token.
| Field | Type | Description |
|---|---|---|
_id |
ObjectId |
Unique identifier. |
group_id |
ObjectId |
Reference to the parent Group. |
name |
String |
Participant's display name (single name field). |
email |
String |
Participant's email. |
recipient_id |
ObjectId |
The ID of the person they drew. |
verification_code |
String |
Unique code for password-less login/verification. |
code_expires_at |
Date |
Timestamp for code expiration (e.g., 30 minutes). |
code_sent_at |
Date |
Timestamp of when the last verification code was sent (for resend cooldown). |
assignment_email_status |
String |
Status of assignment email: pending, sent, delivered, bounced, failed. |
assignment_email_sent_at |
Date |
Timestamp of when assignment email was sent. |
- Route:
/get-started(Guarded on the server) - Logic:
- If
AdminUserdocument exists andis_registeredistrue, redirect to login page - If no
AdminUserexists, display a form for Name and Email - On submit:
- Create the
AdminUserdocument - Generate a
verification_code - Send a login link via AWS SES
- Redirect to:
/verify?email=[...]&code=[...]
- Create the
- If
-
Invitation Link Generation:
- When a group is created, the owner receives a sharable link:
/[locale]/join?inviteId=[Group.invite_id]
- When a group is created, the owner receives a sharable link:
-
/[locale]/joinPage Logic:- Accepts
inviteIdfrom the URL query - Fetches the
Groupand displays its details (e.g., "You are invited to join 'Family Christmas 2025'") - Form requests the user's Name (single field) and Email
- On submit, an API route:
- Checks if a
Participantwith that email already exists in thatGroup - Creates a new
Participantdocument, linking them to theGroup - Generates a new
verification_codeand setscode_sent_at - Sends the login link via AWS SES:
/[locale]/verify?email=[...]&code=[...]
- Checks if a
- Accepts
-
Route:
/[locale]/verify -
Verification Page UX:
- Displays the email address being verified
- Shows input field for verification code
- Allows user to edit/fix their email if it was entered incorrectly
- "Resend Code" button (disabled for 30 seconds after last send, uses
code_sent_atfor validation) - If email is edited, a new verification code is sent to the new address
-
API Endpoint (
/api/verify):- Accepts
emailandcodeas query parameters - Looks up the
Participantwhereemail,verification_codematch andcode_expires_at≥ current time - If valid:
- Generates an encrypted, short-lived session cookie containing the
Participant._id - Clears the used
verification_codeandcode_expires_atin the database - Returns a success state
- Generates an encrypted, short-lived session cookie containing the
- If invalid/expired, returns an error
- Accepts
-
API Endpoint (
/api/resend-code):- Accepts
emailas parameter - Checks
code_sent_atto enforce 30-second cooldown - Generates new
verification_codeand updatescode_sent_at - Sends new verification email via AWS SES
- Accepts
-
Client-side:
- On successful API response, the client sets the cookie
- Redirects to the appropriate dashboard (e.g.,
/[locale]/group/[groupId]/dashboard)
-
Owner Dashboard Features:
- View list of all participants who have successfully signed up
- Display group metadata (name, date, place, budget)
- Show invitation link with copy button
- WhatsApp share button: generates
https://wa.me/?text=[encoded invitation link] - Email invitation form: owner can send invitation directly via email
- Input field for recipient email
- Button to send invitation email
- Display list of emails already sent (from
invitations_sentarray) to prevent duplicates
- "Run Lottery" button (enabled only when participants > 2)
- After lottery is run: display email delivery status for each participant
-
API Endpoint (
/api/group/send-invitation):- Accepts
groupIdandrecipientEmail - Validates that requester is the group owner (session check)
- Checks if email was already sent (in
invitations_sentarray) - Sends invitation email with the join link via AWS SES
- Adds entry to
Group.invitations_sentarray
- Accepts
-
API Endpoint (
/api/lottery/run):- Validates group owner permission
- Runs no-self-draw algorithm
- Updates all
Participant.recipient_idfields - Sends assignment emails to all participants via AWS SES
- Sets
Participant.assignment_email_statustosent - Sets
Participant.assignment_email_sent_attimestamp
-
AWS SNS/SQS Integration for Email Tracking:
- Configure AWS SES to publish notifications to SNS topic
- SNS topic triggers SQS queue
- API endpoint
/api/webhooks/ses-notificationsprocesses SQS messages - Updates
Participant.assignment_email_statusbased on notification type:Delivery: Update todeliveredBounce: Update tobouncedComplaint: Update tofailed
-
Owner View:
- After lottery, dashboard shows table of participants with email delivery status
- Color-coded status indicators (delivered: green, sent: yellow, bounced/failed: red)
- Library: next-intl
- Locales:
en(English US),pt(Portuguese BR) - Implementation: All user-facing text strings (labels, errors, emails) must be accessed via the
t()function to support dynamic language switching based on the URL or user preference