Cross-user search across every resume / cover-letter PDF the platform has ever generated — hot, trashed, archived, and policy-purged. Downloads + restores write to the impersonation audit log.
This UI is grounded in the visual language of Luc Besson's The Fifth Element (1997) — specifically Jean-Paul Gaultier's costume design and the film's retro-futurist world-building. The goal is a lived-in, high-density future: not sterile sci-fi white, but layered, tactile, and slightly worn.
Core Palette
Components
Typography
Space Grotesk — angular, geometric letterforms for all UI chrome, headings, labels, and badge text. Draws from the film's utilitarian industrial stencil language.
IBM Plex Mono — all data output, terminal logs, scores, paths, and thinking traces. The machine's voice.
Structural Language
Panels use clip-path chamfered corners — the same angular, armor-panel geometry seen in Gaultier's bandage-wrap costumes and the film's industrial hardware. Every surface suggests function over decoration.
Scanline overlay references the film's omnipresent screen culture — the city is surveilled, everything is displayed, nothing is private.
Reference Material
Design Rules
- Orange (#FF6B1A) is active / interactive. Use sparingly — primary actions only. When it appears, it commands.
- Green (#39FF14) is success / confirmed / safe. Terminal log text, pipeline completion, submitted state.
- Yellow (#FFD700) is pending / requires review. Awaiting human action.
- Red (#C0392B) is error / blocked / rejected. Quieter than magenta — deliberate, not panicked.
- No rounded corners on structural elements — chamfered only. Softness contradicts the aesthetic.
- All UI chrome uppercase or small-caps. Mixed case only in user-generated content (job titles, descriptions).
- Glow effects are sparse — used to signal state (online, active, hover), never decoration.
- Dense information layout — the city never has empty space. Panels should feel like instrument clusters.
- Borders are structural, not decorative. They define the shape, like Gaultier's bandages define the body.
Job Gobbler is a self-hosted job application automation service running on port 7432.
It is orchestrated by n8n (4 workflows) and surfaces results via Telegram.
The pipeline discovers LinkedIn job postings, scores them with a local LLM, and prepares tailored
resumes — all without sharing data with third parties (except OpenRouter for resume writing).
Starting the service:
npm run dev
Listens on http://localhost:7432. n8n reaches it via host.docker.internal:7432.
-
Search
n8n workflow 01 fires every 15 minutes and POSTs each search URL to
/jobs/searchsequentially. Playwright opens LinkedIn with your saved profile, scrolls the job list to hydrate all cards, and stores up to 50 new job IDs in SQLite. -
Describe
/jobs/describefetches each job's detail page via plain HTTPS (no browser, no auth needed). Parses title, company, salary, location, description text, applicant count, Easy Apply flag. Stored indescription_text. -
Grade
/jobs/grade-allscores all described jobs via a single-shot call to Qwen3-Coder-30B (local, ~800ms/job). ProducesfitScore,scoreCause,riskFlags, and per-dimension scores. -
Telegram
Graded results are formatted and sent to your Telegram chat. Approval buttons let you reject, prep resume, or proceed to apply.
All inference is local except resume/cover letter writing.
| Task | Model | Location |
|---|---|---|
| job_ranking · fit_scoring · risk_flags | Qwen3-Coder-30B | LOCAL |
| form_extraction · structured_output | Qwen3-Coder-30B | LOCAL |
| visual_qa · screenshot_verification | Gemma 4 27B | LOCAL |
| resume_generation · cover_letter | Gemini 2.5 Flash → DeepSeek fallback | REMOTE |
LM Studio endpoint: http://192.168.0.14:1234/v1
| ID | Name | Trigger |
|---|---|---|
| 01 | Discovery Scheduler | Every 15 min → search → describe → grade |
| 02 | Telegram Approval Router | Telegram callback_data → status/apply/build |
| 03 | Direct Job Intake | Telegram URL drop → scrape → grade → notify |
| 04 | Health Monitor | Periodic → GET /health → alert if down |
Push changes: cd n8n-workflows && ./sync.sh push
| Method | Path | Description |
|---|---|---|
| GET | /health |
Service status, policy list, routing stats, audit summary |
| GET | /pool |
Browser profile pool — free/busy/queued |
| GET | /audit |
Recent LLM call log (filter by model, task, jobId) |
| GET | /current-tab?url= |
Firefox bridge — scrape + grade the active tab URL |
| POST | /jobs/search |
LinkedIn discovery — returns new job IDs stored in DB |
| POST | /jobs/describe |
Headless fetch of job description pages (no auth) |
| POST | /jobs/grade-all |
Single-shot 6-dim scoring (~800ms/job) via Qwen3-Coder-30B |
| POST | /jobs/scrape |
Scrape any job URL via browser |
| POST | /jobs/notify |
Format graded jobs into Telegram message payloads |
| POST | /jobs/build |
Generate tailored resume + cover letter (PDF) |
| POST | /jobs/apply |
Initiate apply pipeline — routes by detected platform |
| POST | /jobs/fill |
LinkedIn Easy Apply form-filler (returns plan for approval) |
| POST | /jobs/fill/approve |
Execute approved fill plan (submit button) |
| POST | /jobs/status |
Update job status (rejected / approved / applied) |
SQLite at data/jobs.db. Key columns:
posted_at, applicant_count, status, pre_rank, fit_score,
score_cause, risk_flags, thinking_trace, description_text,
screenshot_path, created_at, updated_at
Status flow: new → described → graded → approved / rejected / applied