How to Build a Job Application Form
Every hire starts with an application. A good job application form collects what you need to evaluate candidates without making them jump through hoops. Too short and you waste time on unqualified applicants. Too long and good candidates abandon it.
This guide walks through building a complete job application form - from basic contact info to screening questions that help you filter candidates before the interview stage.
Personal Information
Start with the basics. Name, email, phone. You need these to contact the candidate regardless of the role.
const personalInfo = form.addSubform('personal', {
title: 'Personal Information'
});
personalInfo.addRow(row => {
row.addTextbox('firstName', {
label: 'First Name',
isRequired: true
});
row.addTextbox('lastName', {
label: 'Last Name',
isRequired: true
});
});
personalInfo.addRow(row => {
row.addEmail('email', {
label: 'Email Address',
isRequired: true
});
row.addTextbox('phone', {
label: 'Phone Number',
placeholder: '(555) 123-4567',
isRequired: true
});
});Use subforms to group related fields. "Personal Information" as a section title makes the form feel organized rather than like a wall of fields.
Position Selection
If you're hiring for multiple roles, let candidates specify which one they want. This also enables conditional logic - showing different questions for different positions.
form.addRow(row => {
row.addDropdown('position', {
label: 'Position Applied For',
options: [
{ id: 'frontend', name: 'Frontend Developer' },
{ id: 'backend', name: 'Backend Developer' },
{ id: 'fullstack', name: 'Full Stack Developer' },
{ id: 'designer', name: 'UI/UX Designer' },
{ id: 'pm', name: 'Project Manager' }
],
isRequired: true
});
});
form.addRow(row => {
row.addRadioButton('employmentType', {
label: 'Employment Type',
options: [
{ id: 'full-time', name: 'Full-time' },
{ id: 'part-time', name: 'Part-time' },
{ id: 'contract', name: 'Contract' }
],
defaultValue: 'full-time',
orientation: 'horizontal'
});
});The employment type question (full-time, part-time, contract) helps set expectations early. Some candidates only want certain arrangements.
Pro tip
Put position selection near the top. It affects which questions appear later, and candidates want to confirm they're applying for the right role before filling out details.
Work Experience
Experience is usually the most important section. Get enough detail to evaluate fit without asking candidates to retype their entire resume.
const experience = form.addSubform('experience', {
title: 'Work Experience'
});
experience.addRow(row => {
row.addDropdown('yearsExperience', {
label: 'Years of Experience',
options: [
{ id: '0-1', name: 'Less than 1 year' },
{ id: '1-3', name: '1-3 years' },
{ id: '3-5', name: '3-5 years' },
{ id: '5-10', name: '5-10 years' },
{ id: '10+', name: '10+ years' }
],
isRequired: true
});
});
experience.addRow(row => {
row.addTextbox('currentTitle', {
label: 'Current/Most Recent Job Title',
placeholder: 'e.g., Senior Software Engineer'
});
row.addTextbox('currentCompany', {
label: 'Current/Most Recent Company',
placeholder: 'e.g., Acme Corp'
});
});
experience.addRow(row => {
row.addTextarea('responsibilities', {
label: 'Key Responsibilities & Achievements',
placeholder: 'Describe your main responsibilities and notable achievements...',
rows: 4
});
});Years of experience as a dropdown is faster than a text field and gives you standardized data for filtering. The responsibilities field lets candidates highlight what's most relevant.
Skills & Qualifications
A skills checklist is faster for candidates than writing them out, and gives you structured data for filtering. Make it position-specific.
const skills = form.addSubform('skills', {
title: 'Skills & Qualifications'
});
skills.addRow(row => {
row.addCheckboxList('technicalSkills', {
label: 'Technical Skills (select all that apply)',
options: [
{ id: 'javascript', name: 'JavaScript/TypeScript' },
{ id: 'python', name: 'Python' },
{ id: 'java', name: 'Java' },
{ id: 'react', name: 'React' },
{ id: 'angular', name: 'Angular' },
{ id: 'node', name: 'Node.js' },
{ id: 'sql', name: 'SQL/Databases' },
{ id: 'cloud', name: 'Cloud (AWS/GCP/Azure)' }
],
isVisible: () => {
const pos = form.dropdown('position')?.value();
return pos === 'frontend' || pos === 'backend' || pos === 'fullstack';
}
});
});
skills.addRow(row => {
row.addTextarea('otherSkills', {
label: 'Other Relevant Skills',
placeholder: 'List any other skills, certifications, or tools...',
rows: 3
});
});The technical skills list only appears for developer positions. Designers and project managers would see different options - or none at all if skills are better captured elsewhere.
Education
For many roles, education matters less than experience. Keep this section brief unless you're hiring for positions where specific degrees are required.
const education = form.addSubform('education', {
title: 'Education'
});
education.addRow(row => {
row.addDropdown('degree', {
label: 'Highest Degree',
options: [
{ id: 'high-school', name: 'High School' },
{ id: 'associate', name: 'Associate Degree' },
{ id: 'bachelor', name: 'Bachelor\'s Degree' },
{ id: 'master', name: 'Master\'s Degree' },
{ id: 'phd', name: 'PhD' },
{ id: 'other', name: 'Other' }
]
});
row.addTextbox('fieldOfStudy', {
label: 'Field of Study',
placeholder: 'e.g., Computer Science'
});
});
education.addRow(row => {
row.addTextbox('university', {
label: 'University/Institution',
placeholder: 'e.g., MIT'
});
row.addTextbox('graduationYear', {
label: 'Graduation Year',
placeholder: 'e.g., 2020'
});
});Dropdowns for degree level standardize the data. Free text for field of study and institution accommodates the variety of backgrounds.
See form templates for different industries.
Screening Questions
Screening questions filter out candidates who don't meet basic requirements. Better to know upfront than discover it during the interview.
const screening = form.addSubform('screening', {
title: 'Screening Questions'
});
screening.addRow(row => {
row.addRadioButton('authorized', {
label: 'Are you legally authorized to work in this country?',
options: [
{ id: 'yes', name: 'Yes' },
{ id: 'no', name: 'No' }
],
isRequired: true
});
});
screening.addRow(row => {
row.addRadioButton('sponsorship', {
label: 'Will you now or in the future require sponsorship?',
options: [
{ id: 'yes', name: 'Yes' },
{ id: 'no', name: 'No' }
],
isRequired: true
});
});
screening.addRow(row => {
row.addDatepicker('startDate', {
label: 'Earliest Available Start Date',
minDate: new Date().toISOString().split('T')[0]
});
});
screening.addRow(row => {
row.addMoney('salaryExpectation', {
label: 'Salary Expectation (Annual)',
currency: '$',
placeholder: 'e.g., 75000'
});
});Work authorization and sponsorship questions are legally important in many countries. Start date availability helps with planning. Salary expectations prevent wasted interviews when there's a mismatch.
Resume Link
Since FormTs doesn't include file uploads, use a link field. Candidates can share their resume via Google Drive, Dropbox, or LinkedIn.
// Since FormTs doesn't have file upload, use a link field
form.addRow(row => {
row.addTextbox('resumeLink', {
label: 'Link to Resume/CV',
placeholder: 'https://drive.google.com/... or LinkedIn URL',
tooltip: 'Upload your resume to Google Drive, Dropbox, or use your LinkedIn profile URL'
});
});
form.addRow(row => {
row.addTextbox('portfolioLink', {
label: 'Portfolio/GitHub (optional)',
placeholder: 'https://github.com/username',
isVisible: () => {
const pos = form.dropdown('position')?.value();
return pos === 'frontend' || pos === 'backend' || pos === 'fullstack' || pos === 'designer';
}
});
});The portfolio/GitHub field appears only for technical and design roles. It's optional but valuable - candidates who include it are often more serious about the application.
Additional Questions
Open-ended questions reveal motivation and communication skills. "Why are you interested?" is classic for a reason - it shows whether they researched your company or are just mass-applying.
form.addRow(row => {
row.addTextarea('whyInterested', {
label: 'Why are you interested in this position?',
placeholder: 'Tell us what attracts you to this role and our company...',
rows: 4,
isRequired: true
});
});
form.addRow(row => {
row.addTextarea('additionalInfo', {
label: 'Anything else you\'d like us to know?',
placeholder: 'Optional - share any additional information...',
rows: 3
});
});Referral Source
Tracking where candidates come from helps you optimize recruiting spend. If referrals consistently produce better hires, invest more in your referral program.
form.addRow(row => {
row.addDropdown('referralSource', {
label: 'How did you hear about this position?',
options: [
{ id: 'linkedin', name: 'LinkedIn' },
{ id: 'indeed', name: 'Indeed' },
{ id: 'glassdoor', name: 'Glassdoor' },
{ id: 'referral', name: 'Employee Referral' },
{ id: 'website', name: 'Company Website' },
{ id: 'other', name: 'Other' }
]
});
});
form.addRow(row => {
row.addTextbox('referralName', {
label: 'If referred, who referred you?',
placeholder: 'Employee name',
isVisible: () => form.dropdown('referralSource')?.value() === 'referral'
});
});The referral name field only appears when "Employee Referral" is selected. No point showing it for LinkedIn applicants.
Complete Example
Here's a streamlined job application form with the essential sections:
export function jobApplication(form: FormTs) {
form.setTitle(() => 'Job Application');
// Position
form.addRow(row => {
row.addDropdown('position', {
label: 'Position',
options: [
{ id: 'developer', name: 'Software Developer' },
{ id: 'designer', name: 'Designer' },
{ id: 'manager', name: 'Project Manager' }
],
isRequired: true
});
});
// Personal Info
const personal = form.addSubform('personal', { title: 'Personal Information' });
personal.addRow(row => {
row.addTextbox('name', { label: 'Full Name', isRequired: true });
row.addEmail('email', { label: 'Email', isRequired: true });
});
personal.addRow(row => {
row.addTextbox('phone', { label: 'Phone', isRequired: true });
});
// Experience
const exp = form.addSubform('experience', { title: 'Experience' });
exp.addRow(row => {
row.addDropdown('years', {
label: 'Years of Experience',
options: [
{ id: '0-2', name: '0-2 years' },
{ id: '3-5', name: '3-5 years' },
{ id: '5+', name: '5+ years' }
],
isRequired: true
});
});
exp.addRow(row => {
row.addTextarea('background', {
label: 'Relevant Experience',
rows: 4,
isRequired: true
});
});
// Links
form.addRow(row => {
row.addTextbox('resumeLink', {
label: 'Resume Link',
placeholder: 'Google Drive, Dropbox, or LinkedIn URL',
isRequired: true
});
});
// Screening
form.addRow(row => {
row.addRadioButton('authorized', {
label: 'Authorized to work here?',
options: [{ id: 'yes', name: 'Yes' }, { id: 'no', name: 'No' }],
isRequired: true
});
});
form.configureSubmitButton({ label: 'Submit Application' });
}Best Practices
Keep It Focused
Only ask for what you'll actually use in the screening process. Every unnecessary field increases abandonment. If you can get information from their resume or LinkedIn, don't make them type it again.
Mobile-Friendly
Many candidates apply from phones. Test your form on mobile. Avoid wide tables and tiny touch targets.
Clear Instructions
Use placeholders and tooltips to guide candidates. "Link to Resume/CV" with a tooltip explaining accepted formats prevents confusion.
Respect Time
Top candidates have options. A 30-minute application form loses good people. Aim for 10-15 minutes max. Save detailed questions for later interview stages.
Common Questions
Should I require a cover letter?
For most roles, no. Cover letters have low signal-to-noise ratio and add friction. If writing skills matter, ask a specific question ('Why are you interested in this role?') instead. You'll get better, more relevant responses.
How do I handle file uploads for resumes?
FormTs uses link fields instead of file uploads. Ask candidates to share a Google Drive/Dropbox link or their LinkedIn profile URL. This is often more convenient for candidates anyway - no file size limits or format issues.
Should salary expectations be required?
It depends on your hiring philosophy. Required: saves time by filtering mismatches early. Optional: gets more applicants but may lead to awkward conversations later. Consider making it optional with a note that it helps ensure alignment.
How do I comply with equal opportunity laws?
Don't ask about age, race, religion, marital status, or other protected characteristics. Focus on qualifications, experience, and job-related factors. If you need demographic data for compliance reporting, collect it separately and keep it disconnected from hiring decisions.
Should I send confirmation emails?
Yes, always. Candidates want to know their application was received. Use FormTs webhooks to trigger a confirmation email through your email service. Include expected timeline for next steps if possible.