Conversation
Template and template image pending change
A per-person pipeline with two independent concurrency-limited pools where each person moves from Tito to email on their own as soon as a slot is free, with no batch boundaries.
A per-person pipeline with two independent concurrency-limited pools where each person moves from Tito to email on their own as soon as a slot is free, with no batch boundaries.
…is/hackdavis-hub into 376-mentor-email-invites
…/HackDavis/hackdavis-hub into 376-mentor-email-invites" This reverts commit 458d2db, reversing changes made to fd85880.
Judge still uses sendSingleJudgeInvite.ts to send email
…o 376-mentor-email-invites
…o 376-mentor-email-invites
…is/hackdavis-hub into 376-mentor-email-invites
There was a problem hiding this comment.
Pull request overview
Adds mentor invite emailing backed by Tito invitation links, refactors bulk invite processing to a reusable concurrency-limited “queue” model, and consolidates the admin invites UI into a single tabbed page.
Changes:
- Implement Tito API client + actions to list releases/RSVP lists and create/recover invitations, then send mentor invite emails via Nodemailer.
- Introduce shared bulk-invite processing utilities (
processBulkInvites,createLimiter) and refactor judge bulk invites to use them. - Replace
/admin/invite-judgeswith a consolidated/admin/invitespage (Judges/Mentors tabs) and add result CSV generation for mentor bulk sends.
Reviewed changes
Copilot reviewed 30 out of 32 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| public/email/2026_footer.png | Adds 2026 email footer asset used by templates. |
| app/_types/tito.ts | Adds Tito API response/request typings. |
| app/_types/emails.ts | Generalizes invite types (shared base + mentor-specific result types). |
| app/(pages)/admin/page.tsx | Updates admin navigation link to consolidated invites page. |
| app/(pages)/admin/invites/page.tsx | New tabbed Invites UI (Judges/Mentors). |
| app/(pages)/admin/invite-judges/page.tsx | Removes legacy judges-only invites page. |
| app/(pages)/admin/_utils/generateInviteResultsCSV.ts | Adds CSV generator for bulk invite result downloads. |
| app/(pages)/admin/_components/MentorInvites/MentorSingleInviteForm.tsx | Adds single-mentor Tito invite + email form UI. |
| app/(pages)/admin/_components/MentorInvites/MentorInvitesPanel.tsx | Adds mentor invites panel with single/bulk toggle and Tito config loading. |
| app/(pages)/admin/_components/MentorInvites/MentorBulkInviteForm.tsx | Adds bulk mentor CSV upload/preview, send, and results download UI. |
| app/(api)/_actions/tito/titoClient.ts | Adds Tito API client wrapper (auth + error handling). |
| app/(api)/_actions/tito/getRsvpLists.ts | Fetches RSVP lists from Tito. |
| app/(api)/_actions/tito/getRsvpInvitationByEmail.ts | Looks up an existing invite by email (paged). |
| app/(api)/_actions/tito/getReleases.ts | Fetches releases from Tito. |
| app/(api)/_actions/tito/getOrCreateTitoInvitation.ts | Adds duplicate-handling wrapper (reuse URL or delete+recreate). |
| app/(api)/_actions/tito/deleteRsvpInvitationByEmail.ts | Deletes an existing invite by email (paged lookup). |
| app/(api)/_actions/tito/createRsvpInvitation.ts | Creates Tito invite with 429 retry/backoff. |
| app/(api)/_actions/emails/sendSingleMentorInvite.ts | Sends a single mentor email using Tito URL + Nodemailer. |
| app/(api)/_actions/emails/sendSingleJudgeHubInvite.ts | Refactors to use exported subject constant and simplifies logging. |
| app/(api)/_actions/emails/sendBulkMentorInvites.ts | Sends mentor bulk invites with separate Tito/email concurrency pools. |
| app/(api)/_actions/emails/sendBulkJudgeHubInvites.ts | Refactors judge bulk invites to use the shared bulk processor. |
| app/(api)/_actions/emails/processBulkInvites.ts | Introduces generic bulk CSV parsing + concurrency + error aggregation. |
| app/(api)/_actions/emails/parseInviteCSV.ts | Generalizes CSV parsing output type to shared InviteData. |
| app/(api)/_actions/emails/emailTemplates/2026MentorInviteTemplate.ts | Adds 2026 mentor email template + subject constant. |
| app/(api)/_actions/emails/emailTemplates/2026JudgeHubInviteTemplate.ts | Updates judge email template styling/assets and exports subject constant. |
| app/(api)/_actions/emails/createLimiter.ts | Adds a queue-based concurrency limiter (no batch idle time). |
| tests/processBulkInvites.test.ts | Adds unit tests for the new bulk invite processor. |
| tests/parseInviteCSV.test.ts | Adds unit tests for CSV parsing/validation. |
| tests/createLimiter.test.ts | Adds unit tests for concurrency limiter behavior. |
| .github/workflows/staging.yaml | Adds Vercel env sync for Tito token + slugs. |
| .github/workflows/production.yaml | Adds Vercel env sync for Tito token + slugs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
app/(api)/_actions/emails/emailTemplates/2026JudgeHubInviteTemplate.ts
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…is/hackdavis-hub into 376-mentor-email-invites
There was a problem hiding this comment.
Pull request overview
Adds mentor invite support by integrating Tito RSVP invitation creation with Nodemailer delivery, and consolidates the admin invite UI into a single tabbed “Invites” page. Also refactors bulk invite processing into a shared, concurrency-limited queue-based helper with accompanying tests.
Changes:
- Implement Tito API client/actions and mentor invite (single + bulk) flows that generate/reuse Tito invitation URLs and send emails.
- Consolidate admin invites UI into
/admin/inviteswith tabs (Judges, Mentors) and add mentor invite forms + results CSV export. - Introduce
processBulkInvites+createLimiterutilities, refactor judge bulk invites to use them, and add unit tests.
Reviewed changes
Copilot reviewed 31 out of 33 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| public/email/2026_footer.png | Adds 2026 email footer asset used by updated templates. |
| app/_types/tito.ts | Introduces Tito types used across Tito actions and mentor invite UI. |
| app/_types/emails.ts | Generalizes invite types and adds mentor-specific response/result types. |
| app/(pages)/admin/page.tsx | Updates admin navigation to point to consolidated invites page. |
| app/(pages)/admin/invites/page.tsx | New tabbed admin invites page (Judges / Mentors). |
| app/(pages)/admin/invite-judges/page.tsx | Removes legacy standalone judge invites page. |
| app/(pages)/admin/_utils/generateInviteResultsCSV.ts | Adds CSV generator for exporting bulk invite outcomes. |
| app/(pages)/admin/_components/MentorInvites/MentorSingleInviteForm.tsx | UI for sending a single mentor invite (select RSVP list + releases). |
| app/(pages)/admin/_components/MentorInvites/MentorInvitesPanel.tsx | Loads Tito config and toggles between single/bulk mentor invite modes. |
| app/(pages)/admin/_components/MentorInvites/MentorBulkInviteForm.tsx | Bulk mentor invites via CSV upload + preview + results export. |
| app/(pages)/admin/_components/JudgeInvites/JudgeBulkInviteForm.tsx | Displays batch-level error message in judge bulk results. |
| app/(api)/_actions/tito/titoClient.ts | Adds Tito API request wrapper (auth, error handling). |
| app/(api)/_actions/tito/getRsvpLists.ts | Fetches Tito RSVP lists for mentor invite configuration. |
| app/(api)/_actions/tito/getRsvpInvitationByEmail.ts | Looks up an existing Tito invitation by email (paged). |
| app/(api)/_actions/tito/getReleases.ts | Fetches Tito releases for mentor invite configuration. |
| app/(api)/_actions/tito/getOrCreateTitoInvitation.ts | Creates Tito invite with duplicate recovery (reuse or delete+recreate). |
| app/(api)/_actions/tito/deleteRsvpInvitationByEmail.ts | Deletes an existing Tito invitation by email (paged). |
| app/(api)/_actions/tito/createRsvpInvitation.ts | Creates Tito invitation with 429 retry/backoff logic. |
| app/(api)/_actions/emails/sendSingleMentorInvite.ts | Single mentor flow: create/reuse Tito URL then send email. |
| app/(api)/_actions/emails/sendSingleJudgeHubInvite.ts | Uses exported subject constant; simplifies failure logging. |
| app/(api)/_actions/emails/sendBulkMentorInvites.ts | Bulk mentor flow with separate Tito/email concurrency pools. |
| app/(api)/_actions/emails/sendBulkJudgeHubInvites.ts | Refactors judge bulk invites to shared bulk processor with preprocess step. |
| app/(api)/_actions/emails/processBulkInvites.ts | New shared bulk CSV parse + preprocess + concurrency processing helper. |
| app/(api)/_actions/emails/parseInviteCSV.ts | Generalizes CSV parsing output type to InviteData. |
| app/(api)/_actions/emails/emailTemplates/2026MentorInviteTemplate.ts | Adds 2026 mentor invite email HTML + subject constant. |
| app/(api)/_actions/emails/emailTemplates/2026JudgeHubInviteTemplate.ts | Updates judge invite template assets/content + exports subject constant. |
| app/(api)/_actions/emails/createLimiter.ts | Adds queue-based concurrency limiter (keeps pool full). |
| tests/processBulkInvites.test.ts | Unit tests for bulk processing helper (preprocess, errors, concurrency). |
| tests/parseInviteCSV.test.ts | Unit tests for CSV parsing/validation behavior. |
| tests/createLimiter.test.ts | Unit tests for limiter concurrency and slot release behavior. |
| .github/workflows/staging.yaml | Adds Tito env vars to Vercel env provisioning for staging workflow. |
| .github/workflows/production.yaml | Adds Tito env vars to Vercel env provisioning for production workflow. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Use Nodemailer + Tito to send mentors invites
Modified the admissions portal code to make it even faster. Rather than having it be batches of 10/20 people processed in parallel, I made it a queue based system where there are always 20 people processing for Tito invites, and always 10 people's whose emails are being sent in parallel. I.e. if 20 people are processing for Tito invites right now, if one finishes, their place in the queue is immediately taken up by another person in waiting.
This will be very easy to modify in my next PR for sending hacker emails.
The UI for invites is being consolidated into 1 page with sub tabs for Judges, Mentors and Hackers (future).
Each one will also allow sending invites to either a single person or a CSV uploaded list of people.
Closes #376