Skip to content

Cohort Page: Email-only signup, consistent padding, themed form styles#70

Open
Suede0619 wants to merge 3 commits intodeployfrom
cohort1
Open

Cohort Page: Email-only signup, consistent padding, themed form styles#70
Suede0619 wants to merge 3 commits intodeployfrom
cohort1

Conversation

@Suede0619
Copy link
Member

@Suede0619 Suede0619 commented Feb 4, 2026

Replaced CohortHero buttons and JoinUs full application form with email-only signup forms, both POST to /api/cohort-signup (not yet implemented)

  • Standardized section padding to py-12 lg:py-24
  • Added background-aware form input/label styles for scroll-100, moloch-500, moloch-800, and scroll-700 sections
  • Moved Self-Assessment copy from CohortValueSection into JoinUs as final CTA
  • Reduced value card min-height, removed testimonial author placeholders, centered JoinUs grid vertically
  • Fathom events: cohort-hero-email-signup, `join-us-email-signup

Backend: New /api/cohort-signup endpoint

The old multi-field application form (/api/applications) is no longer used on the join page. It's been replaced by two email-only forms (hero and bottom of page) that both POST to /api/cohort-signup.

What's needed:

  1. Create src/app/api/cohort-signup/route.ts
  2. Accept { "email": "..." }, validate it
  3. Write the email to a new Airtable table (or new column in existing)
  4. Send a confirmation email with a link to the full application form
  5. Handle duplicates gracefully
  6. Return { "success": true } on 200 or { "success": false, "error": "..." } on failure

Open questions:

  • New Airtable table or add to existing?
  • What sends the follow-up email? (SendGrid, Resend, etc.)
  • What URL does the full application link point to?

Summary by CodeRabbit

Release Notes

  • New Features

    • Replaced multi-field forms with streamlined single-email signup flows across hero and join sections
    • Added event tracking for email signup submissions
  • Style

    • Enhanced contact form input styling with new color theme variants
    • Simplified component layouts by removing testimonial sections and self-assessment content
    • Updated UI spacing, padding, and container structure for improved layout

@vercel
Copy link

vercel bot commented Feb 4, 2026

Deployment failed with the following error:

You don't have permission to create a Preview Deployment for this Vercel project: website.

View Documentation: https://vercel.com/docs/accounts/team-members-and-roles

@coderabbitai
Copy link

coderabbitai bot commented Feb 4, 2026

📝 Walkthrough

Walkthrough

This pull request refactors form components to simplify signup flows from multi-field forms to email-only submissions, updates CSS with new theme variants for form inputs, and removes redundant UI sections including desktop navigation logic and self-assessment content.

Changes

Cohort / File(s) Summary
Form CSS Styling
src/app/globals.css
Adds 91 lines of new CSS variants for contact form inputs, including .contact-form-input-moloch-500, .contact-form-input-moloch-800, .contact-form-input-scroll-700, and .contact-form-input-scroll-100 with corresponding placeholder and label styles; consolidates related input styles under combined rules.
Email Signup Form Refactor
src/components/CohortHero.tsx, src/components/JoinUs.tsx
Replaces multi-field form submission with simplified email-only signup flow; removes desktop-conditional navigation logic from CohortHero; refactors JoinUs from form-library-driven (useForm, zodResolver) to local state management; changes API endpoint from /api/applications to /api/cohort-signup; updates event tracking from join-us-submission to join-us-email-signup.
Component UI Simplification
src/components/CohortValueSection.tsx
Reduces ValueCard minimum height from 280px to 200px; removes testimonial author and role rendering; deletes entire Self-Assessment section (18 lines removed).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • Suede4 #30 — Modifies src/components/JoinUs.tsx form layout and fields structure.
  • Deploy #67 — Overlaps on multiple files including src/app/globals.css, src/components/CohortHero.tsx, and CohortValueSection.tsx with changes to component implementation and theme tokens.
  • join us success state #35 — Alters src/components/JoinUs.tsx submission flow and success-state UI alongside API endpoint changes.

Poem

🐰 Hop hop hooray, the forms are sleek,
Email signup, simple and neat!
Old multi-fields fade away,
New theme variants dance and play,
One input field saves the day!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the three main changes: replacing multi-field forms with email-only signup, standardizing padding across sections, and adding themed form input styles.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cohort1

Important

Action Needed: IP Allowlist Update

If your organization protects your Git platform with IP whitelisting, please add the new CodeRabbit IP address to your allowlist:

  • 136.113.208.247/32 (new)
  • 34.170.211.100/32
  • 35.222.179.152/32

Reviews will stop working after February 8, 2026 if the new IP is not added to your allowlist.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Suede0619 Suede0619 changed the base branch from main to deploy February 4, 2026 02:46
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/components/CohortHero.tsx`:
- Around line 20-51: The handler handleSubmit currently treats any 2xx fetch as
success; change it to inspect the parsed response object (result) and require
result.success === true before setting submissionStatus("success"), calling
trackEvent("cohort-hero-email-signup"), or clearing email; otherwise set
submissionStatus("error") and setErrorMessage(result.error || "Failed to submit.
Please try again."). Ensure the JSON is parsed (const result = await
response.json()) before the success check and do not call trackEvent or clear
the email on failure.

In `@src/components/JoinUs.tsx`:
- Around line 21-52: The submit flow in handleSubmit currently treats any 2xx
response as success; change the post-response logic to require both response.ok
and result.success === true before calling trackEvent, setting
submissionStatus("success"), and clearing email (setEmail("")). If response.ok
is true but result.success is false, set submissionStatus("error"),
setErrorMessage(result.error || a fallback message), and do NOT call trackEvent
or clear the email; ensure isSubmitting is still reset appropriately after both
branches. Use the existing variables/functions (handleSubmit, response, result,
setSubmissionStatus, setErrorMessage, setEmail, trackEvent) to implement this
conditional check.

Comment on lines +20 to +51
const [email, setEmail] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false);
const [submissionStatus, setSubmissionStatus] = useState<
"idle" | "success" | "error"
>("idle");
const [errorMessage, setErrorMessage] = useState("");

const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (isSubmitting || !email) return;

setIsSubmitting(true);
setSubmissionStatus("idle");
setErrorMessage("");

try {
const response = await fetch("/api/cohort-signup", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email }),
});

const result = await response.json();

if (response.ok) {
setSubmissionStatus("success");
trackEvent("cohort-hero-email-signup");
setEmail("");
} else {
setSubmissionStatus("error");
setErrorMessage(result.error || "Failed to submit. Please try again.");
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Check result.success before treating the signup as successful.

The API contract returns { success: false, error } on failure; treating any 2xx as success can show a success state and fire analytics incorrectly.

🛠️ Suggested fix
-      if (response.ok) {
+      if (response.ok && result?.success) {
         setSubmissionStatus("success");
         trackEvent("cohort-hero-email-signup");
         setEmail("");
       } else {
         setSubmissionStatus("error");
-        setErrorMessage(result.error || "Failed to submit. Please try again.");
+        setErrorMessage(result?.error || "Failed to submit. Please try again.");
       }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const [email, setEmail] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false);
const [submissionStatus, setSubmissionStatus] = useState<
"idle" | "success" | "error"
>("idle");
const [errorMessage, setErrorMessage] = useState("");
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (isSubmitting || !email) return;
setIsSubmitting(true);
setSubmissionStatus("idle");
setErrorMessage("");
try {
const response = await fetch("/api/cohort-signup", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email }),
});
const result = await response.json();
if (response.ok) {
setSubmissionStatus("success");
trackEvent("cohort-hero-email-signup");
setEmail("");
} else {
setSubmissionStatus("error");
setErrorMessage(result.error || "Failed to submit. Please try again.");
}
const [email, setEmail] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false);
const [submissionStatus, setSubmissionStatus] = useState<
"idle" | "success" | "error"
>("idle");
const [errorMessage, setErrorMessage] = useState("");
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (isSubmitting || !email) return;
setIsSubmitting(true);
setSubmissionStatus("idle");
setErrorMessage("");
try {
const response = await fetch("/api/cohort-signup", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email }),
});
const result = await response.json();
if (response.ok && result?.success) {
setSubmissionStatus("success");
trackEvent("cohort-hero-email-signup");
setEmail("");
} else {
setSubmissionStatus("error");
setErrorMessage(result?.error || "Failed to submit. Please try again.");
}
🤖 Prompt for AI Agents
In `@src/components/CohortHero.tsx` around lines 20 - 51, The handler handleSubmit
currently treats any 2xx fetch as success; change it to inspect the parsed
response object (result) and require result.success === true before setting
submissionStatus("success"), calling trackEvent("cohort-hero-email-signup"), or
clearing email; otherwise set submissionStatus("error") and
setErrorMessage(result.error || "Failed to submit. Please try again."). Ensure
the JSON is parsed (const result = await response.json()) before the success
check and do not call trackEvent or clear the email on failure.

Comment on lines +21 to 52
const [email, setEmail] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false);
const [submissionStatus, setSubmissionStatus] = useState<
"idle" | "success" | "error"
>("idle");
const [errorMessage, setErrorMessage] = useState<string>("");

const form = useForm<JoinUsFormData>({
resolver: zodResolver(joinUsFormSchema),
defaultValues: {
name: "",
email: "",
discordHandle: "",
showcaseComments: "",
showcaseUrl: "",
introduction: "",
},
});
const [errorMessage, setErrorMessage] = useState("");

const onSubmit = async (data: JoinUsFormData) => {
if (isSubmitting) return; // Prevent multiple submissions
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (isSubmitting || !email) return;

console.log("Join Us form submitted:", data);

// Reset states
setIsSubmitting(true);
setSubmissionStatus("idle");
setErrorMessage("");

try {
const applicationData = transformApplicationDataToApiFormat(data);

const response = await fetch("/api/applications", {
const response = await fetch("/api/cohort-signup", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ applicationData }),
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email }),
});

const result = await response.json();

if (response.ok) {
console.log("Application submitted successfully:", result);
setSubmissionStatus("success");

//tracking
trackEvent("join-us-submission");
// Reset form after successful submission
form.reset();
trackEvent("join-us-email-signup");
setEmail("");
} else {
console.error("Failed to submit application:", result);
setSubmissionStatus("error");
setErrorMessage(
result.error || "Failed to submit application. Please try again.",
);
setErrorMessage(result.error || "Failed to submit. Please try again.");
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Honor result.success from /api/cohort-signup.

If the backend returns { success: false } with a 2xx status, the UI will incorrectly show success and log analytics.

🛠️ Suggested fix
-      if (response.ok) {
+      if (response.ok && result?.success) {
         setSubmissionStatus("success");
         trackEvent("join-us-email-signup");
         setEmail("");
       } else {
         setSubmissionStatus("error");
-        setErrorMessage(result.error || "Failed to submit. Please try again.");
+        setErrorMessage(result?.error || "Failed to submit. Please try again.");
       }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const [email, setEmail] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false);
const [submissionStatus, setSubmissionStatus] = useState<
"idle" | "success" | "error"
>("idle");
const [errorMessage, setErrorMessage] = useState<string>("");
const form = useForm<JoinUsFormData>({
resolver: zodResolver(joinUsFormSchema),
defaultValues: {
name: "",
email: "",
discordHandle: "",
showcaseComments: "",
showcaseUrl: "",
introduction: "",
},
});
const [errorMessage, setErrorMessage] = useState("");
const onSubmit = async (data: JoinUsFormData) => {
if (isSubmitting) return; // Prevent multiple submissions
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (isSubmitting || !email) return;
console.log("Join Us form submitted:", data);
// Reset states
setIsSubmitting(true);
setSubmissionStatus("idle");
setErrorMessage("");
try {
const applicationData = transformApplicationDataToApiFormat(data);
const response = await fetch("/api/applications", {
const response = await fetch("/api/cohort-signup", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ applicationData }),
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email }),
});
const result = await response.json();
if (response.ok) {
console.log("Application submitted successfully:", result);
setSubmissionStatus("success");
//tracking
trackEvent("join-us-submission");
// Reset form after successful submission
form.reset();
trackEvent("join-us-email-signup");
setEmail("");
} else {
console.error("Failed to submit application:", result);
setSubmissionStatus("error");
setErrorMessage(
result.error || "Failed to submit application. Please try again.",
);
setErrorMessage(result.error || "Failed to submit. Please try again.");
}
const [email, setEmail] = useState("");
const [isSubmitting, setIsSubmitting] = useState(false);
const [submissionStatus, setSubmissionStatus] = useState<
"idle" | "success" | "error"
>("idle");
const [errorMessage, setErrorMessage] = useState("");
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (isSubmitting || !email) return;
setIsSubmitting(true);
setSubmissionStatus("idle");
setErrorMessage("");
try {
const response = await fetch("/api/cohort-signup", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email }),
});
const result = await response.json();
if (response.ok && result?.success) {
setSubmissionStatus("success");
trackEvent("join-us-email-signup");
setEmail("");
} else {
setSubmissionStatus("error");
setErrorMessage(result?.error || "Failed to submit. Please try again.");
}
🤖 Prompt for AI Agents
In `@src/components/JoinUs.tsx` around lines 21 - 52, The submit flow in
handleSubmit currently treats any 2xx response as success; change the
post-response logic to require both response.ok and result.success === true
before calling trackEvent, setting submissionStatus("success"), and clearing
email (setEmail("")). If response.ok is true but result.success is false, set
submissionStatus("error"), setErrorMessage(result.error || a fallback message),
and do NOT call trackEvent or clear the email; ensure isSubmitting is still
reset appropriately after both branches. Use the existing variables/functions
(handleSubmit, response, result, setSubmissionStatus, setErrorMessage, setEmail,
trackEvent) to implement this conditional check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant