A modern, professional web application for managing job application submissions. CandForm streamlines the candidate experience by providing a clean interface for submitting applications, automatic email confirmations, and secure CV storage.
- Simple Application Form — Collect essential candidate information: name, email, address, and CV upload
- Automatic Email Confirmation — Candidates receive instant email confirmations with their submission details
- Secure CV Storage — PDFs are validated and stored securely on the server (max 10 MB)
- Real-time Validation — Client-side and server-side validation for robust data integrity
- Professional UI — Built with TailwindCSS for a modern, responsive design
- Dark Mode Support — Seamless dark theme for user comfort
- Database Storage — All submissions are persisted in the database for future reference
- Framework — Laravel 12
- Frontend — Blade templates, TailwindCSS, JavaScript
- Database — MySQL (configurable)
- Email — Laravel Mail with SMTP configuration
- File Storage — Laravel Storage (Public disk for CV uploads)
- PHP 8.2+
- Composer
- MySQL or PostgreSQL
- Node.js & npm (for asset compilation)
-
Clone the repository
git clone <repository-url> cd candform
-
Install dependencies
composer install npm install
-
Environment setup
cp .env.example .env php artisan key:generate
-
Configure database (in
.env)DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=candform DB_USERNAME=root DB_PASSWORD= -
Configure email (in
.env)MAIL_MAILER=smtp MAIL_HOST=smtp.mailtrap.io_OR_smtp.gmail.com MAIL_PORT=2525_OR_587 MAIL_USERNAME=your_username MAIL_PASSWORD=your_password MAIL_FROM_ADDRESS=noreply@candform.local -
Run migrations
php artisan migrate
-
Create storage symlink
php artisan storage:link
-
Build assets
npm run build
-
Start the server
php artisan serve
The application will be available at
http://localhost:8000
- Visit the home page at
/ - Click "Apply Now" to access the application form
- Fill in your information: name, email, address, and upload your CV (PDF, max 10 MB)
- Submit the form
- You'll receive a confirmation notification and an email with your submission details
- Access submitted applications through the database
- Download candidate CVs from
/storage/cvs/ - Customize email templates in
resources/emails/confirmation-candidature.blade.php - Modify form fields in
resources/views/form.blade.php
- Accepted format — PDF only
- Maximum size — 10 MB
- Storage location —
storage/app/public/cvs/ - Access URL —
/storage/cvs/{filename}
| Method | Route | Description |
|---|---|---|
| GET | / |
Home page |
| GET | /form |
Application form page |
| POST | /form |
Submit application (validation & email) |
candform/
├── app/
│ ├── Http/
│ │ └── Controllers/
│ │ └── CandidatureController.php
│ ├── Mail/
│ │ └── ConfirmationCandidatureMail.php
│ └── Models/
│ └── Candidature.php
├── resources/
│ ├── views/
│ │ ├── form.blade.php
│ │ ├── home.blade.php
│ │ ├── components/
│ │ └── emails/
│ ├── css/
│ └── js/
├── storage/
│ └── app/
│ └── public/
│ └── cvs/
├── routes/
│ └── web.php
└── database/
└── migrations/
CREATE TABLE candidatures (
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
last_name VARCHAR(255) NOT NULL,
first_name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
address TEXT NULLABLE,
cv_path VARCHAR(255) NULLABLE,
created_at TIMESTAMP,
updated_at TIMESTAMP
);Edit app/Mail/ConfirmationCandidatureMail.php to customize the confirmation email template.
Modify validation rules in app/Http/Controllers/CandidatureController.php:
$validated = $request->validate([
'last_name' => 'required|string|max:255',
'first_name' => 'required|string|max:255',
'email' => 'required|email|max:255',
'address' => 'nullable|string|max:255',
'cv' => 'required|file|mimes:pdf|max:10240', // 10 MB in KB
]);Update php.ini if needed:
upload_max_filesize = 10M
post_max_size = 10M
- ✅ CSRF protection on all forms
- ✅ Server-side file type validation (PDF only)
- ✅ File size limit enforcement (10 MB max)
- ✅ Email validation using Laravel's email rule
- ✅ Automatic cleanup of CVs on submission deletion (via Model observer)
- ✅ Input sanitization & XSS prevention via Blade escaping
- Static assets are minified and versioned via Laravel Mix
- Database queries are optimized
- Consider adding pagination for large submission lists
- Use a queue driver (Redis, database) for email sending in production
- Verify SMTP credentials in
.env - Check
MAIL_FROM_ADDRESSis set - Test with Laravel Tinker:
Mail::raw('test', fn($m) => $m->to('test@example.com'));
- Run
php artisan storage:linkif symlink is missing - Check directory permissions:
chmod -R 775 storage bootstrap/cache - Verify
upload_max_filesizeandpost_max_sizeinphp.ini
- Clear config cache:
php artisan config:cache - Verify locale is set to 'en' or 'fr' in
config/app.php
This project is licensed under the MIT License — see the LICENSE file for details.
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
For questions or issues, please open an issue on the repository or contact the development team.
Hermas Francisco — Initial development and maintenance
Last Updated: November 2025