{"id":44793862,"url":"https://github.com/fergus/job-tracker","last_synced_at":"2026-06-01T07:01:02.500Z","repository":{"id":338605475,"uuid":"1158431687","full_name":"fergus/job-tracker","owner":"fergus","description":"A single-page web app for tracking job applications through a pipeline — kanban board, table view, file uploads, per-stage notes, and PocketID auth.","archived":false,"fork":false,"pushed_at":"2026-05-22T21:03:11.000Z","size":2995,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-22T23:32:07.616Z","etag":null,"topics":["docker","express","job-tracker","sqlite","vue"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fergus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-02-15T11:10:48.000Z","updated_at":"2026-05-22T21:03:07.000Z","dependencies_parsed_at":"2026-03-30T03:04:04.957Z","dependency_job_id":"18d802ae-b2b7-4f4a-a810-10d4b8c3ec20","html_url":"https://github.com/fergus/job-tracker","commit_stats":null,"previous_names":["fergus/job-tracker"],"tags_count":76,"template":false,"template_full_name":null,"purl":"pkg:github/fergus/job-tracker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fergus%2Fjob-tracker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fergus%2Fjob-tracker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fergus%2Fjob-tracker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fergus%2Fjob-tracker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fergus","download_url":"https://codeload.github.com/fergus/job-tracker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fergus%2Fjob-tracker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33763655,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","express","job-tracker","sqlite","vue"],"created_at":"2026-02-16T12:07:21.431Z","updated_at":"2026-06-01T07:01:02.491Z","avatar_url":"https://github.com/fergus.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Job Application Tracker\n\n[![Build](https://github.com/fergus/job-tracker/actions/workflows/build.yml/badge.svg)](https://github.com/fergus/job-tracker/actions/workflows/build.yml)\n\nA multi-user web app for tracking job applications through a pipeline — from initial interest through to offer and acceptance. Kanban board with drag-and-drop, table view, timeline view, file attachments, notes, salary tracking, and date tracking per stage. Each user sees only their own applications; admins can view all.\n\n![Job Application Tracker kanban board with applications across all pipeline stages](docs/screenshot.png)\n\n## Quick Start\n\nRequirements: [Docker](https://docs.docker.com/get-docker/) and Docker Compose, and a [PocketID](https://github.com/pocket-id/pocket-id) instance for authentication.\n\n**1. Clone and configure:**\n\n```bash\nmkdir job-tracker \u0026\u0026 cd job-tracker\ncp .env.example .env\n```\n\nDownload the [`docker-compose.yml`](docker-compose.yml) and [`.env.example`](.env.example) files, or clone the repo.\n\n**2. Set up PocketID:**\n\nIn your PocketID admin panel, create a new OIDC client:\n- **Redirect URI:** `https://your-domain.com/oauth2/callback`\n- Note the **Client ID** and **Client Secret**\n\n**3. Edit `.env`** with your values:\n\n```env\nOIDC_ISSUER_URL=https://your-pocketid-instance.example.com\nOIDC_CLIENT_ID=your-client-id\nOIDC_CLIENT_SECRET=your-client-secret\nPUBLIC_URL=https://your-domain.com\nCOOKIE_SECRET=   # generate with: openssl rand -base64 32 | tr -- '+/' '-_'\nLISTEN_PORT=3000\n```\n\n**4. Update `docker-compose.yml`** to use the pre-built image:\n\n```yaml\nservices:\n  job-tracker:\n    image: ghcr.io/fergus/job-tracker:latest\n```\n\n**5. Start:**\n\n```bash\ndocker compose up -d\n```\n\nOpen your `PUBLIC_URL` in a browser. You'll be redirected to PocketID to log in.\n\n## Updating\n\nPull the latest image and restart:\n\n```bash\ndocker compose pull\ndocker compose up -d\n```\n\nYour data is safe — updates only replace the container, not the volume-mounted data directories.\n\n## Data Persistence\n\nAll data is stored in Docker volumes mapped to local directories:\n\n- `./data/` — SQLite database\n- `./uploads/` — uploaded attachment files\n\nThese directories are created automatically. Your data survives container restarts, rebuilds, and updates.\n\nTo back up:\n\n```bash\ncp -r data/ data-backup/\ncp -r uploads/ uploads-backup/\n```\n\n## Features\n\n- **Kanban board** — drag cards between columns: Interested → Applied → Screening → Interview → Offer → Accepted/Rejected\n- **Table view** — sortable columns, click any row for details\n- **Timeline view** — visual history of status changes per application\n- **Hamburger menu** — slide-in sidebar with the view switcher and account info; an \"Always use menu\" toggle (persisted per browser) controls whether the view switcher also appears inline in the header\n- **Settings panel** — manage API keys; admins can toggle between personal and all-users view\n- **API keys** — generate personal API keys for programmatic access without the browser OAuth flow; scoped to your account, shown once at creation\n- **File attachments** — upload PDF, DOC, DOCX, MD, or TXT files (up to 10MB each) as attachments; CV and cover letter can also be attached directly to an application\n- **Salary tracking** — min/max salary range and job location per application\n- **Date tracking** — timestamps auto-set when you move applications between stages; all dates are editable\n- **Stage notes** — per-stage timestamped notes with markdown rendering and colored stage badges\n- **Links** — store job posting and company website URLs\n- **Multi-user** — each user sees only their own applications, identified via PocketID `X-Forwarded-Email` header. Admins (configured via `ADMIN_EMAILS`) can view all users' applications but cannot edit or delete others' data\n\n## MCP Server (AI Integration)\n\nA Model Context Protocol (MCP) server is included for AI clients to interact with your job applications programmatically. It exposes tools for listing, creating, updating, and adding notes to applications.\n\n**Endpoint:** `https://your-domain.com/mcp`\n\n**Authentication:** Bearer API key (generate one in the Settings panel)\n\n**Tools exposed:**\n- `create_application` — create a new job application\n- `add_note` — append a stage note to an application\n- `list_applications` — list all applications (optionally filter by status)\n- `get_application` — get full details including notes and attachments\n- `update_application` — update fields on an existing application\n- `update_status` — change status (auto-sets the corresponding date)\n- `list_attachments` — list file attachments for an application\n- `upload_attachment` — upload a small file (\u003c~30KB) via base64-encoded content\n- `get_upload_url` — get a pre-signed upload URL for larger files (any size)\n\n### Connecting from Claude Code\n\nAdd this to your `~/.mcp.json`:\n\n```json\n{\n  \"job-tracker\": {\n    \"type\": \"http\",\n    \"url\": \"https://your-domain.com/mcp\",\n    \"headers\": {\n      \"Authorization\": \"Bearer YOUR_API_KEY\"\n    }\n  }\n}\n```\n\nGenerate `YOUR_API_KEY` from the app's Settings panel → API Keys.\n\n### Connecting from other MCP clients\n\nAny MCP client that supports the Streamable HTTP transport can connect using the same URL and Bearer token.\n\n## Configuration\n\nThe server runs on port 3000 by default. To change the exposed port, set `LISTEN_PORT` in your `.env`:\n\n```env\nLISTEN_PORT=8080\n```\n\nTo run without HTTPS (e.g. local dev), set:\n\n```env\nCOOKIE_SECURE=false\n```\n\nTo grant admin access (view all users' applications), set a comma-separated list of email addresses:\n\n```env\nADMIN_EMAILS=admin@example.com,boss@example.com\n```\n\n## Architecture\n\n```mermaid\ngraph LR\n  Browser --\u003e|HTTPS| Proxy[\"oauth2-proxy\"]\n  Proxy --\u003e|\"X-Forwarded-Email :3000\"| API[\"Express API\"]\n  API \u003c--\u003e DB[\"SQLite (WAL)\"]\n  API \u003c--\u003e FS[\"/app/uploads/\"]\n```\n\n- **Frontend** (`client/`): Vue 3 SPA, Vite, Tailwind CSS 4. State in `App.vue`, API calls in `client/src/api.js`\n- **Backend** (`server/`): Express 5, better-sqlite3. Routes in `server/routes/`\n- **Auth** (`server/middleware/auth.js`): oauth2-proxy headers (browser) or Bearer API key (programmatic)\n- **Database** (`server/db.js`): 5 tables (`users`, `applications`, `stage_notes`, `attachments`, `api_keys`) + `_migrations` tracking\n\n## Tech Stack\n\n- Vue 3 + Vite + Tailwind CSS (frontend)\n- Node.js + Express (backend)\n- SQLite via better-sqlite3 (database)\n- Single Docker container (multi-stage build)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffergus%2Fjob-tracker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffergus%2Fjob-tracker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffergus%2Fjob-tracker/lists"}