Skip to main content

Resume Upload & Talent Pool Form

A modern talent community and general application intake form styled with Tailwind CSS. Allows prospective candidates to submit their CV/resume directly into your hiring database, selecting their preferred department and seniority level. Pre-wired for Backforms with S3 file uploads and ATS webhook alerts.

Prominent resume & CV file upload dropzone
Department & area of interest categorization
Seniority and years of experience selection
Invisible honeypot (_gotcha) spam trap
Automated S3 file storage & recruiter notifications
Live Form PreviewComponent Sandbox

Talent Pool & Resume Submission

Submit your resume to our general talent network. Our recruiters review profiles weekly for matching opportunities.

Pre-configured for Backforms endpoint with automated S3 file attachments & ATS webhooks
Honeypot anti-spam active
Zero backend needed
style="color:#9ece6a;">"use client";

import { useState } from style="color:#9ece6a;">"react";
import { UploadCloud, Check, AlertCircle, FileText, ArrowRight, UserCheck } from style="color:#9ece6a;">"lucide-react";

export default function ResumeUploadTalentForm() {
  const [formData, setFormData] = useState({
    name: style="color:#9ece6a;">"",
    email: style="color:#9ece6a;">"",
    phone: style="color:#9ece6a;">"",
    roleInterest: style="color:#9ece6a;">"Software Engineering",
    experienceLevel: style="color:#9ece6a;">"Senior (5+ yrs)",
    portfolio: style="color:#9ece6a;">"",
    fileName: style="color:#9ece6a;">"",
  });
  const [status, setStatus] = useState<style="color:#9ece6a;">"idle" | style="color:#9ece6a;">"loading" | style="color:#9ece6a;">"success" | style="color:#9ece6a;">"error">(style="color:#9ece6a;">"idle");
  const [errorMessage, setErrorMessage] = useState(style="color:#9ece6a;">"");

  const roles = [
    style="color:#9ece6a;">"Software Engineering",
    style="color:#9ece6a;">"Product & Design",
    style="color:#9ece6a;">"Data & AI",
    style="color:#9ece6a;">"Marketing & Growth",
    style="color:#9ece6a;">"Operations & Sales",
  ];

  const experienceLevels = [style="color:#9ece6a;">"Entry (0-2 yrs)", style="color:#9ece6a;">"Mid-Level (2-5 yrs)", style="color:#9ece6a;">"Senior (5+ yrs)", style="color:#9ece6a;">"Lead / Director"];

  const handleFileChange = (e: React.ChangeEvent<style="color:#f7768e;font-weight:600;">HTMLInputElement>) => {
    if (e.target.files && e.target.files[0]) {
      setFormData({ ...formData, fileName: e.target.files[0].name });
    }
  };

  async function handleSubmit(e: React.FormEvent<style="color:#f7768e;font-weight:600;">HTMLFormElement>) {
    e.preventDefault();
    setStatus(style="color:#9ece6a;">"loading");
    setErrorMessage(style="color:#9ece6a;">"");

    const form = e.currentTarget;
    const body = new FormData(form);

    try {
      style=style="color:#9ece6a;">"color:#565f89;font-style:italic;">// Replace YOUR_FORM_ID with your actual endpoint ID from https://app.backforms.com
      const res = await fetch(style="color:#9ece6a;">"https:style="color:#565f89;font-style:italic;style="color:#9ece6a;">">//backforms.com/f/YOUR_FORM_ID", {
        method: style="color:#9ece6a;">"POST",
        headers: { Accept: style="color:#9ece6a;">"application/json" },
        body,
      });

      if (res.ok) {
        setStatus(style="color:#9ece6a;">"success");
      } else {
        const data = await res.json().catch(() => ({}));
        setErrorMessage(data.error || style="color:#9ece6a;">"Failed to submit resume. Please try again.");
        setStatus(style="color:#9ece6a;">"error");
      }
    } catch {
      setErrorMessage(style="color:#9ece6a;">"Network error occurred. Please check your connection.");
      setStatus(style="color:#9ece6a;">"error");
    }
  }

  if (status === style="color:#9ece6a;">"success") {
    return (
      <style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"max-w-xl mx-auto p-8 bg-[#0b0d12] border border-zinc-800 rounded-2xl text-center space-y-3">
        <style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"size-10 mx-auto rounded-full bg-sky-950/60 border border-sky-500/30 flex items-center justify-center text-sky-400">
          <style="color:#f7768e;font-weight:600;">Check className=style="color:#9ece6a;">"size-5 stroke-[2.5]" />
        </style="color:#f7768e;font-weight:600;">div>
        <style="color:#f7768e;font-weight:600;">h3 className=style="color:#9ece6a;">"text-xl font-bold text-white">Resume Received</style="color:#f7768e;font-weight:600;">h3>
        <style="color:#f7768e;font-weight:600;">p className=style="color:#9ece6a;">"text-xs text-zinc-400 max-w-sm mx-auto">
          Thank you, {formData.name || style="color:#9ece6a;">"Candidate"}. Your profile has been added to our talent network for {formData.roleInterest}.
        </style="color:#f7768e;font-weight:600;">p>
        <style="color:#f7768e;font-weight:600;">button
          onClick={() => {
            setFormData({ name: style="color:#9ece6a;">"", email: style="color:#9ece6a;">"", phone: style="color:#9ece6a;">"", roleInterest: roles[0], experienceLevel: experienceLevels[0], portfolio: style="color:#9ece6a;">"", fileName: style="color:#9ece6a;">"" });
            setStatus(style="color:#9ece6a;">"idle");
          }}
          className=style="color:#9ece6a;">"mt-3 px-4 py-2 bg-zinc-800 hover:bg-zinc-700 text-white text-xs font-medium rounded-lg"
        >
          Submit Another Profile
        </style="color:#f7768e;font-weight:600;">button>
      </style="color:#f7768e;font-weight:600;">div>
    );
  }

  return (
    <style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"max-w-xl mx-auto p-6 sm:p-8 bg-[#0b0d12] border border-zinc-800 rounded-2xl text-zinc-200">
      <style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"mb-6">
        <style="color:#f7768e;font-weight:600;">h2 className=style="color:#9ece6a;">"text-2xl font-bold text-white tracking-tight">Join Our Talent Network</style="color:#f7768e;font-weight:600;">h2>
        <style="color:#f7768e;font-weight:600;">p className=style="color:#9ece6a;">"text-xs text-zinc-400 mt-1">Submit your resume for consideration across upcoming department openings.</style="color:#f7768e;font-weight:600;">p>
      </style="color:#f7768e;font-weight:600;">div>

      <style="color:#f7768e;font-weight:600;">form onSubmit={handleSubmit} className=style="color:#9ece6a;">"space-y-4">
        {style=style="color:#9ece6a;">"color:#565f89;font-style:italic;">/* Invisible Honeypot Spam Trap */}
        <style="color:#f7768e;font-weight:600;">input type=style="color:#9ece6a;">"text" name=style="color:#9ece6a;">"_gotcha" style={{ display: style="color:#9ece6a;">"none" }} tabIndex={-1} autoComplete=style="color:#9ece6a;">"off" />

        {style=style="color:#9ece6a;">"color:#565f89;font-style:italic;">/* Dropzone */}
        <style="color:#f7768e;font-weight:600;">div>
          <style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-xs font-medium text-zinc-300 mb-1.5">Resume / CV File</style="color:#f7768e;font-weight:600;">label>
          <style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"flex flex-col items-center justify-center p-6 bg-[#131720] border-2 border-dashed border-zinc-700 hover:border-sky-500 rounded-xl cursor-pointer transition-colors group">
            <style="color:#f7768e;font-weight:600;">UploadCloud className=style="color:#9ece6a;">"size-8 text-zinc-400 group-hover:text-sky-400 transition-colors mb-2" />
            <style="color:#f7768e;font-weight:600;">span className=style="color:#9ece6a;">"text-xs font-semibold text-white">
              {formData.fileName ? formData.fileName : style="color:#9ece6a;">"Click to select or drag and drop your resume"}
            </style="color:#f7768e;font-weight:600;">span>
            <style="color:#f7768e;font-weight:600;">span className=style="color:#9ece6a;">"text-[11px] text-zinc-500 mt-1">PDF, DOCX up to 10MB</style="color:#f7768e;font-weight:600;">span>
            <style="color:#f7768e;font-weight:600;">input
              type=style="color:#9ece6a;">"file"
              name=style="color:#9ece6a;">"resume"
              required={!formData.fileName}
              accept=style="color:#9ece6a;">".pdf,.doc,.docx"
              onChange={handleFileChange}
              className=style="color:#9ece6a;">"hidden"
            />
          </style="color:#f7768e;font-weight:600;">label>
        </style="color:#f7768e;font-weight:600;">div>

        <style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"grid grid-cols-1 sm:grid-cols-2 gap-3.5">
          <style="color:#f7768e;font-weight:600;">div>
            <style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-xs font-medium text-zinc-300 mb-1">Department of Interest</style="color:#f7768e;font-weight:600;">label>
            <style="color:#f7768e;font-weight:600;">select
              name=style="color:#9ece6a;">"roleInterest"
              value={formData.roleInterest}
              onChange={(e) => setFormData({ ...formData, roleInterest: e.target.value })}
              className=style="color:#9ece6a;">"w-full bg-[#131720] text-zinc-100 border border-zinc-800 rounded-lg px-3 py-2 text-xs focus:outline-none focus:border-sky-500 transition-colors"
            >
              {roles.map((r) => (
                <style="color:#f7768e;font-weight:600;">option key={r} value={r}>{r}</style="color:#f7768e;font-weight:600;">option>
              ))}
            </style="color:#f7768e;font-weight:600;">select>
          </style="color:#f7768e;font-weight:600;">div>

          <style="color:#f7768e;font-weight:600;">div>
            <style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-xs font-medium text-zinc-300 mb-1">Seniority Level</style="color:#f7768e;font-weight:600;">label>
            <style="color:#f7768e;font-weight:600;">select
              name=style="color:#9ece6a;">"experienceLevel"
              value={formData.experienceLevel}
              onChange={(e) => setFormData({ ...formData, experienceLevel: e.target.value })}
              className=style="color:#9ece6a;">"w-full bg-[#131720] text-zinc-100 border border-zinc-800 rounded-lg px-3 py-2 text-xs focus:outline-none focus:border-sky-500 transition-colors"
            >
              {experienceLevels.map((lvl) => (
                <style="color:#f7768e;font-weight:600;">option key={lvl} value={lvl}>{lvl}</style="color:#f7768e;font-weight:600;">option>
              ))}
            </style="color:#f7768e;font-weight:600;">select>
          </style="color:#f7768e;font-weight:600;">div>
        </style="color:#f7768e;font-weight:600;">div>

        <style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"grid grid-cols-1 sm:grid-cols-2 gap-3.5">
          <style="color:#f7768e;font-weight:600;">div>
            <style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-xs font-medium text-zinc-300 mb-1">Full Name</style="color:#f7768e;font-weight:600;">label>
            <style="color:#f7768e;font-weight:600;">input
              type=style="color:#9ece6a;">"text"
              name=style="color:#9ece6a;">"name"
              required
              placeholder=style="color:#9ece6a;">"Alex Rivera"
              value={formData.name}
              onChange={(e) => setFormData({ ...formData, name: e.target.value })}
              className=style="color:#9ece6a;">"w-full bg-[#131720] text-zinc-100 border border-zinc-800 rounded-lg px-3 py-2 text-xs placeholder:text-zinc-500 focus:outline-none focus:border-sky-500 transition-colors"
            />
          </style="color:#f7768e;font-weight:600;">div>

          <style="color:#f7768e;font-weight:600;">div>
            <style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-xs font-medium text-zinc-300 mb-1">Email Address</style="color:#f7768e;font-weight:600;">label>
            <style="color:#f7768e;font-weight:600;">input
              type=style="color:#9ece6a;">"email"
              name=style="color:#9ece6a;">"email"
              required
              placeholder=style="color:#9ece6a;">"alex@example.com"
              value={formData.email}
              onChange={(e) => setFormData({ ...formData, email: e.target.value })}
              className=style="color:#9ece6a;">"w-full bg-[#131720] text-zinc-100 border border-zinc-800 rounded-lg px-3 py-2 text-xs placeholder:text-zinc-500 focus:outline-none focus:border-sky-500 transition-colors"
            />
          </style="color:#f7768e;font-weight:600;">div>
        </style="color:#f7768e;font-weight:600;">div>

        <style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"grid grid-cols-1 sm:grid-cols-2 gap-3.5">
          <style="color:#f7768e;font-weight:600;">div>
            <style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-xs font-medium text-zinc-300 mb-1">Phone Number (Optional)</style="color:#f7768e;font-weight:600;">label>
            <style="color:#f7768e;font-weight:600;">input
              type=style="color:#9ece6a;">"tel"
              name=style="color:#9ece6a;">"phone"
              placeholder=style="color:#9ece6a;">"+1 (555) 019-2834"
              value={formData.phone}
              onChange={(e) => setFormData({ ...formData, phone: e.target.value })}
              className=style="color:#9ece6a;">"w-full bg-[#131720] text-zinc-100 border border-zinc-800 rounded-lg px-3 py-2 text-xs placeholder:text-zinc-500 focus:outline-none focus:border-sky-500 transition-colors"
            />
          </style="color:#f7768e;font-weight:600;">div>

          <style="color:#f7768e;font-weight:600;">div>
            <style="color:#f7768e;font-weight:600;">label className=style="color:#9ece6a;">"block text-xs font-medium text-zinc-300 mb-1">LinkedIn / Portfolio URL</style="color:#f7768e;font-weight:600;">label>
            <style="color:#f7768e;font-weight:600;">input
              type=style="color:#9ece6a;">"url"
              name=style="color:#9ece6a;">"portfolio"
              placeholder=style="color:#9ece6a;">"https:style="color:#565f89;font-style:italic;style="color:#9ece6a;">">//linkedin.com/in/username"
              value={formData.portfolio}
              onChange={(e) => setFormData({ ...formData, portfolio: e.target.value })}
              className=style="color:#9ece6a;">"w-full bg-[#131720] text-zinc-100 border border-zinc-800 rounded-lg px-3 py-2 text-xs placeholder:text-zinc-500 focus:outline-none focus:border-sky-500 transition-colors"
            />
          </style="color:#f7768e;font-weight:600;">div>
        </style="color:#f7768e;font-weight:600;">div>

        {status === style="color:#9ece6a;">"error" && (
          <style="color:#f7768e;font-weight:600;">div className=style="color:#9ece6a;">"p-3 bg-red-950/40 border border-red-500/30 rounded-lg flex items-center gap-2 text-xs text-red-300">
            <style="color:#f7768e;font-weight:600;">AlertCircle className=style="color:#9ece6a;">"size-4 shrink-0" />
            <style="color:#f7768e;font-weight:600;">span>{errorMessage}</style="color:#f7768e;font-weight:600;">span>
          </style="color:#f7768e;font-weight:600;">div>
        )}

        <style="color:#f7768e;font-weight:600;">button
          type=style="color:#9ece6a;">"submit"
          disabled={status === style="color:#9ece6a;">"loading"}
          className=style="color:#9ece6a;">"w-full mt-2 bg-sky-500 hover:bg-sky-400 text-zinc-950 font-bold text-xs py-2.5 px-4 rounded-lg active:scale-[0.99] transition duration-150 cursor-pointer disabled:opacity-60 flex items-center justify-center gap-2"
        >
          <style="color:#f7768e;font-weight:600;">UserCheck className=style="color:#9ece6a;">"size-4 shrink-0" />
          <style="color:#f7768e;font-weight:600;">span>{status === style="color:#9ece6a;">"loading" ? style="color:#9ece6a;">"Uploading Resume..." : style="color:#9ece6a;">"Submit to Talent Pool"}</style="color:#f7768e;font-weight:600;">span>
          <style="color:#f7768e;font-weight:600;">ArrowRight className=style="color:#9ece6a;">"size-3.5" />
        </style="color:#f7768e;font-weight:600;">button>
      </style="color:#f7768e;font-weight:600;">form>
    </style="color:#f7768e;font-weight:600;">div>
  );
}
Replace YOUR_FORM_ID with your Backforms key

Connect this component to your Backforms endpoint

Create a free form endpoint in under 30 seconds. Zero backend servers or databases required.

Get Free Endpoint Key

Frequently Asked Questions & Technical Integration

How does Backforms store uploaded resume files?

Backforms automatically streams uploaded PDF and DOCX attachments into encrypted Amazon S3 storage and attaches secure, time-limited download links directly to your notification emails and webhooks.

Can this form route candidates to our Greenhouse or Ashby ATS?

Yes! Backforms webhooks contain the candidate's metadata and direct file URL, allowing direct ingestion into your applicant tracking system via webhooks or Zapier.

What file formats and sizes are supported?

Backforms supports PDF, DOC, DOCX, RTF, and TXT files up to 10MB per submission.