The goal
Israeli hi-tech job seekers have to browse dozens of ATSs and company career pages. HiTakeJob unifies them into a single Hebrew-first platform with a paying agency tier and admin tools that keep the data clean at scale.
The solution
A three-service product - Python crawler, Node.js/Express + MongoDB backend, Vue 3 + Pinia frontend - orchestrated with docker-compose, provisioned on AWS via Terraform, configured with Ansible, and featuring multi-ATS crawlers, public/agency/admin APIs, real-time chat over Socket.IO, GTM-tracked analytics, CV-package billing, and a GDPR-compliant data model.
Highlights
- Four ATS integrations unified under a single MongoDB jobs schema
- Three-service docker-compose deploy provisioned end-to-end with Terraform + Ansible
- Dedicated agency API layer with Gmail OAuth and role-scoped endpoints
- Real-time chat with unread counts and typing indicators on Socket.IO + MongoDB
The challenge
Workday, Comeet, Greenhouse and Lever each expose jobs through completely different shapes, pagination and cadences.
Per-ATS Python crawlers that share URL normalization and cache-busting helpers, feeding a single MongoDB jobs collection so the API stays source-agnostic.
Hebrew-first UX with many English tech terms and inconsistent city spellings.
RTL-aware Tailwind UI with a language store, plus city-name normalization utilities (cityNames.js, generate-reverse-city-names.js) so searches match regardless of spelling.
Recruiting agencies needed multiple seats, scoped access and their own data surface separate from the admin panel.
Dedicated agency API layer (agencyPortalApi, agencyGmailApi, agencyHttp, agencyJobsApi, agencyMatchesApi) with its own Gmail OAuth and role-scoped endpoints, documented in docs/agency-multi-user.md.
Production deploys had to stop being tied to my laptop and survive host reprovisioning.
Terraform (main.tf) provisions the AWS stack (VPC, subnet, SG, EC2 from Amazon Linux 2023 SSM AMI) in one apply, Ansible (infra/ansible/playbook.yml) installs Docker and brings up docker-compose with crawler/backend/frontend.
Live chat needed persistence, unread counts, typing and read indicators across user and admin surfaces.
Express + Socket.IO with dedicated chatThreads and chatMessages MongoDB collections, Pinia store on the frontend, and an AdminChats triage UI with filters, statuses and live badges.
What was delivered
- Python crawler with per-ATS modules (Workday, Comeet, Greenhouse, Lever)
- Node.js/Express + MongoDB API with Socket.IO chat server
- Vue 3 + Pinia + Tailwind RTL frontend
- Admin suite (advanced search, GTM audit, DevOps tools, agency tools)
- Terraform IaC + Ansible playbook + docker-compose
- Documentation: PROJECT.md, PRE_DEPLOYMENT_CHECKLIST.md, docs/ (GDPR, GTM, agency, city data, devops, chat)
Results
4
ATS integrations
3 + chat
Services
Terraform + Ansible
Infra
AWS eu-central-1
Region
What it taught me
- Shared crawler helpers (URL normalization, cache-busting) paid back with every new ATS added
- A dedicated agency API surface kept admin/agency permissions clean as the product grew
- Terraform + Ansible from day one kept deploys reproducible through host changes
