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.
Talent Pool & Resume Submission
Submit your resume to our general talent network. Our recruiters review profiles weekly for matching opportunities.
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>
);
}Connect this component to your Backforms endpoint
Create a free form endpoint in under 30 seconds. Zero backend servers or databases required.
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.