* chore: move @types/canvas-confetti to devDependencies, remove unused get-tsconfig direct dep * chore: configure knip with workspace entry points for all packages * refactor(shared): split 1119-line types.ts into domain modules under types/ * refactor: remove llm-service.ts shim, migrate all import sites to llm/service directly * refactor(settings): migrate 4 manually-resolved settings into conversion registry * refactor: split gmail-sync.ts into gmail-api, email-router, and thin orchestrator * refactor(orchestrator): extract useKeyboardShortcuts and usePipelineControls from OrchestratorPage Splits the 840-line OrchestratorPage into a thin orchestration shell (~480 lines) by extracting keyboard shortcut handling into useKeyboardShortcuts.ts and pipeline control logic into usePipelineControls.ts. Net negative line count across all files. * feat: create settings registry (Step 1) Introduces a single source of truth for all settings, combining schema definitions, default logic, parsing, and serialization into a single configuration object. * feat: derive schema, keys, and types from settings registry (Step 2) Derives AppSettings nested shape, SettingKey DB union, and updateSettingsSchema Zod shape automatically from the settings registry. * refactor: gut envSettings and remove settings-conversion (Step 3) Replaces manual env arrays with registry-driven maps in envSettings.ts. Deletes settings-conversion.ts since all parsing/defaults now live in the registry. * refactor: simplify getEffectiveSettings with generic loop (Step 4) Replaces ~334 lines of manual key-by-key unpacking with a generic registry-driven iteration loop (~40 lines). Models, typed, string, and virtual kinds are automatically derived. * refactor: simplify settingsUpdateRegistry (Step 5) Replaces ~350 lines of explicit per-key update handlers with a dynamic generic loop over the settings registry, properly routing persistence and side effects. * refactor(settings): implement nested settings registry and clean up tests - Migrate settings system to use a centralized nested registry (`settings-schema.ts`, `registry.ts`) - Remove obsolete flat-to-nested conversion logic (`settings-conversion.ts`) - Address Biome warnings by explicitly ignoring intentional `any` usage in generic runtime schema builder and registry logic - Clean up unused variables in test files (`SettingsPage.test.tsx`) to achieve a 100% green CI pipeline * refactor(settings): address PR comments on env data and registry parsing - Narrow `getEnvSettingsData` return type to `Partial<AppSettings>` to satisfy strict typing and omit 'typed' registry entries - Introduce `parseNonEmptyStringOrNull` for typed string settings so empty-string overrides cleanly fall back to defaults (matching original `||` logic) - Add missing unit tests for registry parse/serialize helpers (JSON, bools, numeric clamping)
JobOps: Your Ironman Suit for Job Hunting
Automate the hunt. Scrapes major job boards (LinkedIn, Indeed, Glassdoor), AI-scores suitability, tailors resumes (RxResume), and tracks application emails automatically.
Self-hosted. Docker-based. Stop applying manually.
40s Demo: Crawl → Score → PDF → Track
Documentation (Start Here)
JobOps ships with full docs for setup, architecture, extractors, and troubleshooting.
If you want the serious view of the project, start here:
- Documentation Home
- Self-Hosting Guide
- Feature Overview
- Orchestrator Pipeline
- Extractor System
- Troubleshooting
Quick Start (10 Min)
Prefer guided setup? Follow the Self-Hosting Guide.
# 1. Download
git clone https://github.com/DaKheera47/job-ops.git
cd job-ops
# 2. Start (Pulls pre-built image)
docker compose up -d
# 3. Launch Dashboard
# Open http://localhost:3005 to start the onboarding wizard
Why JobOps?
- Universal Scraping: Supports LinkedIn, Indeed, Glassdoor, Adzuna + specialized boards (Gradcracker, UK Visa Jobs).
- AI Scoring: Ranks jobs by fit against your profile using your preferred LLM (OpenRouter/OpenAI/Gemini).
- Auto-Tailoring: Generates custom resumes (PDFs) for every application using RxResume v4.
- Email Tracking: Connect Gmail to auto-detect interviews, offers, and rejections.
- Self-Hosted: Your data stays with you. SQLite database. No SaaS fees.
Workflow
- Search: Scrapes job boards for roles matching your criteria.
- Score: AI ranks jobs (0-100) based on your resume/profile.
- Tailor: Generates a custom resume summary & keyword optimization for top matches.
- Export: Uses RxResume v4 to create tailored PDFs.
- Track: "Smart Router" AI watches your inbox for recruiter replies.
Supported Extractors
| Platform | Focus |
|---|---|
| Global / General | |
| Indeed | Global / General |
| Glassdoor | Global / General |
| Adzuna | Multi-country API source |
| Gradcracker | STEM / Grads (UK) |
| UK Visa Jobs | Sponsorship (UK) |
(More extractors can be added via TypeScript - see extractors documentation)
Post-App Tracking (Killer Feature)
Connect Gmail → AI routes emails to your applied jobs.
- "We'd like to interview you..." → Status: Interviewing (Auto-updated)
- "Unfortunately..." → Status: Rejected (Auto-updated)
See post-application tracking docs for setup.
Note on Analytics: The alpha version includes anonymous analytics (Umami) to help debug performance. To opt-out, block umami.dakheera47.com in your firewall/DNS.
Star History
License
AGPLv3 - Free to use and modify.