A full-stack job aggregator built for international students and visa seekers. Scrapes remote job listings, flags roles that mention visa sponsorship, and presents them in a searchable, filterable UI.
- Backend: Ruby on Rails 8 (API mode), PostgreSQL
- Frontend: React + Vite
- Scraper: HTTParty hitting the RemoteOK public API
- Deployment: Render (API), Vercel (Frontend)
- One-click job scraping from RemoteOK
- Automatic visa-friendly detection via keyword matching (
sponsor,visa,work rights,international students,relocation) - Search by title, company, or location
- Clean descriptions — HTML tags, encoding artifacts, and spam text stripped on ingestion
- Duplicate prevention via unique index on
source_url
- Ruby 3.x
- Rails 8.x
- PostgreSQL
- Node.js + npm
git clone https://github.com/your-username/job-aggregator.git
cd job-aggregator
bundle install
rails db:create db:migrate
rails serverThe API will be available at http://localhost:3000.
cd job-aggregator-frontend
npm install
npm run devThe frontend will be available at http://localhost:5173.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/jobs |
List all scraped jobs |
| GET | /api/v1/jobs/:id |
Get a single job |
| PATCH | /api/v1/jobs/:id |
Update a job (e.g. visa_friendly flag) |
| POST | /api/v1/scrape |
Trigger a fresh scrape |
Hitting POST /api/v1/scrape calls JobScraper, which:
- Fetches job listings from the RemoteOK API
- Cleans each description (strips HTML, fixes encoding, removes spam)
- Detects visa-friendliness via keyword matching on the description
- Uses
find_or_create_by(source_url:)to avoid duplicates
job-aggregator/
├── app/
│ ├── controllers/api/v1/jobs_controller.rb
│ ├── models/job.rb
│ └── services/job_scraper.rb
├── config/
│ ├── routes.rb
│ └── initializers/cors.rb
└── db/
└── migrate/
job-aggregator-frontend/
└── src/
└── App.jsx
- Add more job sources (Seek, LinkedIn, Indeed)
- Filter by location (Australia-specific roles)
- User accounts with saved jobs and application tracking
- Email alerts for new visa-friendly listings
- Scheduled scraping with cron/Sidekiq
MIT