Skip to content

narminj/hirepath-api

Repository files navigation

HirePath — Job Aggregation & Multi-Channel Recruitment Bot (Laravel 13)

A backend that scrapes multiple job boards, classifies each posting by tech-stack relevance and remote eligibility, and broadcasts matches across Telegram, Email and WhatsApp — with an interactive Telegram bot, a scheduled scrape/notify pipeline and an admin dashboard. Built to surface remote PHP/Laravel roles open to candidates in Azerbaijan.

PHP Laravel Telegram WhatsApp Web Scraping Queue


The problem it solves

Relevant remote jobs are scattered across many boards, buried under on-site and off-stack noise, and gone by the time you check manually. HirePath automates the whole funnel: it harvests postings from several sources on a schedule, runs each through a relevance & remote-eligibility classifier (is it really PHP/Laravel? is it truly remote? can someone in Azerbaijan actually take it?), de-duplicates and persists them, then pushes only the qualifying roles to subscribers on their channel of choice. An admin dashboard tracks what was found, sent, viewed and applied to.

Senior backend skills demonstrated

  • Resilient web scraping — an abstract BaseScraper (Guzzle + browser-like headers, timeouts, graceful failure) with per-site implementations parsing real HTML via Symfony DomCrawler / CSS selectors. Dead/anti-bot sources are isolated so one broken board never breaks the run.
  • Domain classification engine — a single JobRelevanceFilter (one source of truth, reused by every scraper, the aggregator service and a bot:reclassify command) encoding non-trivial rules: PHP/Laravel signals, excluded stacks, remote vs hybrid vs on-site, worldwide / EMEA / Europe / country-restricted detection, Azerbaijan eligibility, a needs_review fallback for ambiguous geography, and a seniority-weighted priority score.
  • Multi-channel notification fan-out — Telegram (per-subscriber + channel broadcast), Email (queued Mailable) and WhatsApp, each with rate-limit-aware pacing and per-channel error isolation.
  • Interactive bot — a webhook-driven Telegram bot with a command router (/start, /stop, /help, /latest, /email, /whatsapp) that manages subscriptions and per-user delivery preferences.
  • Scheduled pipelines — Laravel scheduler runs bot:fetch every two hours and bot:send five minutes later; idempotent "unsent / viewed / applied" state prevents duplicate delivery.
  • Pragmatic data modelling — rich query scopes (featured, available, needsReview, seniority, unsent) and additive migrations that evolve the schema as classification logic grows.
  • Server-rendered admin UI — Blade + Tailwind (Vite) dashboard with view/applied tracking, plus correct CSRF exemption for the inbound Telegram webhook.

Tech stack

Layer Technology
Language / Framework PHP 8.3+, Laravel 13
Scraping guzzlehttp/guzzle, symfony/dom-crawler, symfony/css-selector
Messaging Telegram Bot API (irazasyed/telegram-bot-sdk + raw API), WhatsApp (kstmostofa/laravel-whatsapp), SMTP email
Queue & scheduler Laravel database queue + scheduler
Persistence SQLite (default) / MySQL
Frontend Blade + Tailwind CSS via Vite

Architecture

  Laravel Scheduler (every 2h)
        │
        ▼
  bot:fetch ─────────────► JobScraperService
                               │  iterates registered scrapers
        ┌──────────────────────┼───────────────────────────┐
        ▼                      ▼                            ▼
  JobsearchAzScraper     HelloJobScraper   LinkedInScraper / DjinniScraper …
        │  (extends BaseScraper: Guzzle + DomCrawler)
        ▼
  JobRelevanceFilter   ── stack relevance + remote eligibility + priority score
        │
        ▼
  Vacancy (DB)         ── de-duplicated, classified, scoped (unsent/featured/…)
        │
  bot:send (2h + 5m)   ── only unsent + qualifying
        │
        ├──► TelegramService  → subscribers + channel
        ├──► Mail (VacancyNotification)
        └──► WhatsApp

  Inbound:  POST /webhook/telegram → TelegramWebhookController → command router
  Admin:    /dashboard · /admin/vacancies · /admin/subscribers  (Blade + Tailwind)

The classifier is the architectural keystone: scrapers, the aggregator and the reclassify command all delegate to it, so relevance rules live in exactly one place.


Key features

  • Multi-source scraping — pluggable scrapers for jobsearch.az, hellojob.az, LinkedIn and Djinni (boss.az / isbazar isolated when unavailable); add a board by extending BaseScraper.
  • Relevance & remote classification — keeps only PHP/Laravel + fully-remote + Azerbaijan-eligible roles; flags ambiguous geography for manual review; scores seniority/priority.
  • Telegram bot — subscribe/unsubscribe, browse latest roles, and opt into Email/WhatsApp delivery, all via chat commands; HTML-formatted job cards.
  • Channel broadcast — posts to a configured Telegram channel in addition to direct subscribers.
  • Email & WhatsApp — queued email Mailable and optional WhatsApp Web delivery, each independently toggleable.
  • Scheduled automation — hands-off fetch → classify → notify loop with duplicate-safe state.
  • Admin dashboard — vacancy list with source/seniority/remote metadata, open/applied/viewed tracking, and a subscriber view.

Routes overview

Method Route Description
GET / Landing page
GET /dashboard Stats dashboard
GET /admin/vacancies Admin vacancy list (featured/filtered)
GET /admin/vacancies/{vacancy}/open Open + mark viewed
PATCH /admin/vacancies/{vacancy}/applied Toggle applied status
GET /admin/subscribers Subscriber list
POST /webhook/telegram Inbound Telegram bot webhook (CSRF-exempt)

Artisan commands

php artisan bot:fetch            # scrape all sources, classify, persist new vacancies
php artisan bot:send             # broadcast unsent vacancies (Telegram + Email + WhatsApp)
php artisan bot:reclassify       # re-run the relevance/remote classifier over stored vacancies
php artisan bot:set-webhook      # register the Telegram webhook URL

Installation & setup

Requirements: PHP 8.3+, Composer 2, Node.js (Vite assets), and a Telegram bot token (from @BotFather).

composer install
cp .env.example .env
php artisan key:generate
php artisan migrate

npm install && npm run build      # or: npm run dev

# Run the scheduler + queue worker (or use `composer dev` for an all-in-one dev loop)
php artisan schedule:work
php artisan queue:work

# Register the Telegram webhook (public HTTPS URL required)
php artisan bot:set-webhook

In production the scheduler runs from cron (* * * * * php artisan schedule:run), driving bot:fetch / bot:send automatically.


Environment variables (.env.example)

Variable Description
DB_CONNECTION sqlite (default) or mysql
QUEUE_CONNECTION database — queued mail / async work
TELEGRAM_BOT_TOKEN Bot token from @BotFather
TELEGRAM_CHANNEL_ID Channel to broadcast vacancies to
MAIL_MAILER / MAIL_HOST / MAIL_PORT SMTP transport for email notifications
MAIL_USERNAME / MAIL_PASSWORD SMTP credentials (use an app password)
MAIL_FROM_ADDRESS / MAIL_FROM_NAME Email sender identity
WHATSAPP_WEB_ENABLED Toggle WhatsApp delivery on/off
WHATSAPP_WEB_HOST / _PORT / _TOKEN WhatsApp Web gateway connection
APP_URL Public URL — used to build the Telegram webhook endpoint

.env and *.log are git-ignored. The committed .env.example contains placeholders only — no real tokens or credentials.


Advanced concepts demonstrated

Web scraping (Guzzle + Symfony DomCrawler / CSS selectors) with an extensible BaseScraper abstraction · domain-driven relevance & remote-eligibility classification (single source of truth) · Telegram Bot API (webhook ingestion + command routing + channel broadcast) · multi-channel notification fan-out (Telegram / Email / WhatsApp) with rate-limit pacing and per-channel error isolation · Laravel scheduler & queues for an automated fetch→classify→notify pipeline · queued Mailables · idempotent delivery state · Eloquent query scopes & incremental migrations · Blade + Tailwind admin dashboard · secure webhook handling (targeted CSRF exemption).

License

MIT

About

Job-aggregation & recruitment automation on Laravel 13 — multi-board web scraping, a PHP/Laravel relevance + remote-eligibility classifier, and multi-channel broadcasting via Telegram bot, Email and WhatsApp.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages