A modern, serverless job application system built with React and Cloudflare Pages. The system handles job postings, applications, file uploads, and automated notifications.
- View job postings with detailed information
- Submit applications with required information
- Upload resumes (PDF, DOC, DOCX formats supported)
- Instant feedback on submission status
- File size validation (max 5MB)
- Instant notifications via Google Chat for new applications
- Direct access to candidate information
- Secure resume download links
- Organized application tracking
- Links back to original job postings
- React-based SPA
- Modern form handling and validation
- File upload with client-side validation
- Toast notifications for user feedback
- Clean and responsive UI
- Serverless architecture
- Multipart form data handling
- File storage in Cloudflare R2
- Application data in Cloudflare KV
- Google Chat webhook integration
- Dynamic URL generation based on request origin
- Cloudflare KV: Application data and job-application relationships
- Cloudflare R2: Resume file storage
- Proper indexing for efficient retrieval
- Node.js (v22.15.1 or later)
- Wrangler CLI
- Cloudflare account
Create a .dev.vars file for local development:
GOOGLE_CHAT_WEBHOOK=your-google-chat-webhook-url
R2_PUBLIC_URL=your-r2-public-urlUpdate wrangler.toml with your production values:
[vars]
GOOGLE_CHAT_WEBHOOK = "your-google-chat-webhook-url"
R2_PUBLIC_URL = "your-r2-public-url"
[[kv_namespaces]]
binding = "KV"
id = "your-kv-namespace-id"
[[r2_buckets]]
binding = "R2"
bucket_name = "resumes"- Clone the repository
git clone <repository-url>
cd recruit- Install dependencies
npm install- Start development server
npm run devPOST /submit
- Handles job application submissions
- Processes multipart form data
- Stores application data and resume
- Sends notification to Google Chat
- Automatically generates URLs based on request origin
GET /getResume
- Secure resume file retrieval
- Requires exact filename
- Returns file with proper content type
- Supports PDF, DOC, DOCX formats
interface ApplicationRecord {
id: string;
jobId: string;
title: string;
type: string;
location: string;
answers: ApplicationAnswer[];
resumeFileName: string;
resumeType: string;
resumeUrl: string;
jobUrl: string;
submittedAt: string;
status: string;
}
interface ApplicationAnswer {
questionId: string;
question: string;
answer: string;
}- Secure file handling with type and size validation
- No direct R2 URL exposure
- Environment-based configuration
- Proper error handling and validation
- Dynamic URL generation for security
npm run devnpm run deploy- Fork the repository
- Create your feature branch
- Commit your changes
- Push to the branch
- Create a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.