Not just a CRUD app—an AI-augmented recruiting platform with enterprise-grade performance.
Job Pulse combines modern Laravel development with cutting-edge AI features to solve real recruiting problems. While traditional job boards fail on searches like "creative coding jobs" (returning 0 results), Job Pulse's Pixel AI understands that you're looking for WebGL, Canvas, or Three.js expertise.
| You Search For | Traditional Board | Job Pulse |
|---|---|---|
| "creative coding jobs" | ❌ 0 results | ✅ Finds WebGL, Canvas, Three.js roles |
| "work from anywhere" | ❌ Only matches "remote" | ✅ Understands distributed, async, location-independent |
| "roles for problem solvers" | ❌ No keyword match | ✅ Finds algorithmic, optimization, debugging roles |
| "highest paying Laravel jobs" | ❌ Text search only | ✅ Smart SQL sorting by salary value |
|
|
|
|
The standout feature of Job Pulse is Pixel AI, a context-aware recruiting assistant powered by a multi-layered architecture implemented in app/Http/Controllers/ChatController.php and app/Services/VectorService.php.
Unlike basic chatbots that send every message to an expensive LLM, Pixel AI uses a three-layer decision tree:
User Query → Layer 0 (Reflex) → Layer 1 (Router) → Layer 2 (Execution)
↓ ↓ ↓
Instant Reply Intent Analysis SQL or Vector Search
(0ms, $0) (Groq Llama 3) (Database or RAG)
A regex-based pattern matcher handles simple interactions instantly:
- Greetings: "Hi", "Hello" → Pre-written friendly response
- Help requests: "Help", "What can you do?" → Feature list
- Gratitude: "Thanks", "Thank you" → Acknowledgment
Performance: 0ms latency, $0 cost, handles ~40% of queries
For real questions, the router analyzes intent with a specialized system prompt:
"Analyze this job search query:
- If asking for salary sorting → return 'SQL_SALARY'
- If asking for recent jobs → return 'SQL_RECENT'
- If asking about skills/context → return 'VECTOR_SEARCH'"
Performance: ~100-200ms, minimal token usage, handles ~50% of queries
SQL Path - Direct database operations:
// For "highest paying jobs"
Job::orderByRaw('CAST(salary AS UNSIGNED) DESC')
->with('employer', 'tags')
->limit(5)
->get();Vector Path - RAG Pipeline for semantic queries:
- Embedding Generation: User query → Google Gemini → 768-dimensional vector
- Semantic Search: Vector → Pinecone similarity search → Top 5 job IDs
- Context Retrieval: IDs → Database → Full job descriptions
- Synthesis: Jobs + Original Query → Groq → Natural language response
Performance: ~1-2s for vector search, ~10% of queries, highest value queries
Implemented in ChartsController.php, this feature provides market insights through intelligent data processing.
-
Data Cleaning:
// Strip currency symbols and formatting $cleanSalary = preg_replace('/[^0-9.]/', '', $salary);
-
PHP-Side Calculations:
$statistics = [ 'average' => $salaries->avg(), 'min' => $salaries->min(), 'max' => $salaries->max() ];
-
Dynamic Bucketing:
- Automatically groups salaries into 10,000 EGP ranges
- Example: 10k-20k, 20k-30k, 30k-40k
- Generates clean JSON for Chart.js frontend
-
Visualization: Real-time histogram rendering showing salary distribution
Implemented in SearchController.php with multi-dimensional querying:
Job::where(function($query) use ($searchTerm) {
$query->where('title', 'LIKE', "%{$searchTerm}%")
->orWhere('description', 'LIKE', "%{$searchTerm}%")
->orWhere('location', 'LIKE', "%{$searchTerm}%")
->orWhereHas('tags', function($q) use ($searchTerm) {
$q->where('name', 'LIKE', "%{$searchTerm}%");
});
})
->with(['tags', 'employer']) // Prevent N+1 queries
->paginate(20);Performance: Single SQL query instead of 21+ without eager loading
Built with EmployerController.php and Dashboard.php:
- Live Company Search: AJAX-enabled endpoint for instant company filtering
- Optimized Selects: Only load necessary fields (
id,name,logo)Employer::select('id', 'name', 'logo') ->where('name', 'LIKE', "%{$search}%") ->get();
- Memory Efficiency: Excludes heavy
biotext from listing pages - Policy Gates:
JobPolicyensures strict ownership validation// Only owners can edit Gate::authorize('update', $job);
Comprehensive validation and security:
$validated = $request->validate([
'title' => 'required|max:255',
'salary' => 'required',
'closing_date' => 'required|date|after:posted_date',
'logo' => 'nullable|image|max:2048'
]);File Handling: Secure logo uploads to storage/public/logos with automatic linking
Smart Cache Invalidation:
// Only clear affected caches
Cache::forget("job_{$id}");
Cache::forget("employer_{$employerId}_jobs");
// Featured jobs cache remains intactJob Pulse implements multi-tiered caching for production-grade performance:
// Featured jobs cached for 1 hour
$featured = Cache::remember('jobs.featured', 3600, function() {
return Job::with('employer', 'tags')
->where('featured', true)
->get();
});
// Individual job pages cached by ID
$job = Cache::remember("job_{$id}", 3600, function() use ($id) {
return Job::with('employer', 'tags')->findOrFail($id);
});// ❌ BAD: 101 queries (1 + 100 N+1)
foreach(Job::all() as $job) {
echo $job->employer->name;
}
// ✅ GOOD: 2 queries total
foreach(Job::with('employer', 'tags')->get() as $job) {
echo $job->employer->name;
}Email notifications and heavy tasks run asynchronously:
// Don't wait for SMTP server
Mail::to($user)->queue(new JobPostedNotification($job));
// User sees instant confirmation, email sends in backgroundQueue Configuration:
- Driver:
database(no Redis dependency for basic setup) - Worker:
php artisan queue:work - Prevents UI freezing during email delivery
| Metric | Without Optimization | With Optimization |
|---|---|---|
| Home Page Load | ~3-5s | ~2-3s |
| Search Results | ~2-3s | ~1-2s |
| Job Details | ~1-2s | ~1-1.5s |
| AI Response Time | ~1.5-2.5s | ~0-2s |
The Mistake: Initially split App Server and Database Server across different cloud providers to use free tiers.
The Impact:
- Every SQL query crossed the internet
- Page loads: 3-5 seconds
- 10 queries per page = 10 network round trips
- Unacceptable user experience
The Solution: Co-located application and database on the same provider/network.
The Result:
- Page loads: ~2s
- Local network communication (no internet traversal)
Key Takeaway: Never separate your application from its database in production. Network latency is your enemy.
| Layer | Technology | Purpose |
|---|---|---|
| Backend | Laravel 11, PHP 8.2+ | Core MVC framework |
| Database | MySQL 8.0+ | Relational data storage |
| Frontend | Blade, Tailwind CSS v4, Alpine.js | Server-side rendering with reactive components |
| AI Router | Groq (Llama 3) | Intent detection & response generation |
| Embeddings | Google Gemini | 768-dimensional vector generation |
| Vector DB | Pinecone | Semantic similarity search |
| Cache | Redis/File | Performance optimization layer |
| Queue | Database Driver | Background job processing |
| Charts | Chart.js | Data visualization |
PHP >= 8.2
Composer
Node.js & NPM >= 18
MySQL >= 8.0Sign up at:
- Groq Console - AI routing & generation
- Google AI Studio - Gemini embeddings
- Pinecone - Vector database
git clone https://github.com/AboNady/Job_Pulse.git
cd Job_Pulse
composer install
npm install && npm run buildcp .env.example .env
php artisan key:generate# Database
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=job_pulse
DB_USERNAME=your_username
DB_PASSWORD=your_password
# AI Services
GROQ_API_KEY=gsk_xxxxxxxxxxxxx
GEMINI_API_KEY=AIzaSyxxxxxxxxxx
PINECONE_API_KEY=xxxxxxxxxxxxx
PINECONE_HOST=https://your-index.pinecone.io
# Caching (File by default, Redis for production)
CACHE_DRIVER=file
QUEUE_CONNECTION=database
# Mail (for notifications)
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525php artisan migrate --seedThe AI needs data to work. Run this custom command:
php artisan index:jobsNote: Processes jobs in batches of 50 to prevent memory leaks. For 1000+ jobs, this may take several minutes.
php artisan queue:workKeep this running in a separate terminal for background jobs.
php artisan serveVisit http://localhost:8000 🎉
Adjust similarity threshold in app/Services/VectorService.php:
'threshold' => 0.75 // Default
// Higher (0.8-0.9) = Stricter matches, fewer results
// Lower (0.5-0.7) = Broader matches, more results- Resume Parsing - Upload CV for automatic job matching
- Advanced Analytics - Employer insights (views, applications, conversion rates)
- Multi-language Support - Arabic, French, German
- Mobile App - Mobile apps
- Video Introductions - Employer video uploads
- Salary Negotiation Tool - Market rate recommendations
Contributions are welcome! Whether you're fixing bugs, adding features, or improving documentation.
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add AmazingFeature') - Push to branch (
git push origin feature/AmazingFeature) - Open a Pull Request
- Follow PSR-12 coding standards
- Write tests for new features (PHPUnit)
- Update documentation as needed
- Keep commits atomic and descriptive
- Comment complex logic in controllers
This project is open-source software licensed under the MIT License.
You are free to use, modify, and distribute this software for personal purposes.
- Jeffrey Way & Laracasts - Foundation curriculum and Laravel best practices
- Gemini, ChatGPT and Claude - Super helpful tools
- Groq - Lightning-fast LLM inference (Llama 3)
- Pinecone - Scalable vector database infrastructure
- Google - Gemini embedding models
- Tailwind Labs - Modern CSS framework
- 🚀 Live Demo: View Job Pulse
- 📂 Source Code: GitHub Repository
- 🐛 Bug Tracking: Submit an Issue
- 💼 Connect: Mahmoud Nady on LinkedIn
Built with ❤️, Laravel, and AI by AboNady
If this project helped you, consider giving it a ⭐
