Skip to content
TsakmakTsakmak

Product

Job Tracker

The recruiter calls. The application, the emails and the CV you sent are on screen.

Live
Status
Live
Platforms
Web
Hosting
Self-hosted in Greece (EU)

The problem

The phone rings and a recruiter says "about the position you applied for". After a few weeks of applying to many roles, that sentence is hard to answer. Which company was it, what did the posting say, which CV version went with it, and who did I speak to last time? Spreadsheets and generic boards hold part of the answer, and the emails, notes and files sit somewhere else. I build tools for my own use first, and this was a job I wanted to make easier every time it came back.

What it does

Job Tracker is a private CRM for a job search. Every application, company, recruiter, pasted email, call, interview and CV version sits in one searchable place, on a server in Greece. When someone calls, a few keystrokes bring up the company, the job description, the current stage and the full history. Reminders, follow-ups and "no reply" flags keep the rest of the search moving without any outside service.

How it works

  1. Add an application: paste the job link and description, pick the company, stage, source, work mode and salary. Duplicate and same-company warnings appear while you type.

  2. Attach what you sent: upload or choose the CV and cover letter version, so each application records which file went where.

  3. Log what happens: paste emails, log calls and interviews, and move the card along the board. Interview reminders and follow-ups are created for you.

  4. When a recruiter calls, press Ctrl+K (or open search on the phone), type the company or the caller's number, and read the application and its history.

  5. Review the week on the dashboard: what needs attention, the response rate and the stage funnel.

Key features

Global search (Ctrl+K) covers companies, job titles, people, emails and phone numbers. A caller's number matches with or without the country code and spaces, so you can type what you see on the screen.

The recruiter who calls, with every interaction in one place (demo data)

One timeline per application

Pasted emails sent and received, calls, interviews (future ones marked Upcoming) and notes, mixed with stage changes, newest first. Pasted text is shown as plain text, never as HTML. CVs, cover letters and other files (PDF, Word .docx, plain text) link to the applications they went with, so you can see where each version was sent.

One application with its description, contacts, next interview and the CV sent (demo data)
Which CV version went to which application (demo data)

Board, list and editable stages

A kanban board with one column per stage: drag cards with mouse, touch or keyboard, or use a "move to" menu. A list view adds filters and sorting. Stages can be renamed, recoloured, reordered, added or removed, and each has a type such as in progress, offer or closed.

Board view in the dark theme (demo data)
List view with stage filters and follow-up signals (demo data)

Reminders, follow-ups and "no reply" flags

A future interview gets a reminder one day before, which moves if the interview moves. After a quiet period (7 days by default) an active application gets a "Follow up" reminder, and after a longer one (21 days by default) it is flagged as "no reply" until something new happens. Notifications stay inside the app: nothing is emailed or pushed.

Reminders, follow-ups and automatic interview reminders (demo data)
Editable stages and follow-up timing

Dashboard

Active applications, interviews this week, offers, response rate, applications per week, a "needs attention" view (interviews in the next 7 days, follow-ups due, no reply) and a stage funnel. The charts are drawn by the app itself, with no chart service.

Dashboard with the needs attention lanes and the stage funnel (demo data)
  • Duplicate warnings

    The same posting needs an explicit confirmation before it is saved again, whether the link is a LinkedIn or Indeed link in any form, with or without tracking parameters. Other applications at the same company show up while you type, and "Acme, Inc.", "ACME" and "acme ltd" count as one company, including Greek legal suffixes.

  • Passkey and authenticator sign-in

    Sign in with a passkey (fingerprint, face, device PIN or security key), or with a password plus an authenticator app code. Ten one-time recovery codes cover a lost device. The settings list active sessions with remote sign-out and keep a security activity log.

Security and privacy

  • Where data lives: applications, contacts, notes and uploaded files are stored in PostgreSQL and on disk on Mikael's own server at his home in Greece (EU), on his own hardware and under his own management.
  • How traffic reaches it: the app is reachable only through Cloudflare, which handles TLS and the tunnel, then a reverse proxy on the server. The app's own login page is the gate; there is no extra access layer in front of it.
  • Who can see it: it is a single-user app. Registration closes after the first account, and every query is filtered by its owner.
  • Sign-in: passwords are hashed with argon2id (12 characters minimum). Passkeys use WebAuthn. Authenticator codes are protected against replay, their secrets are encrypted at rest with AES-256-GCM, and recovery codes are stored hashed. Mikael's own account uses a passkey and an authenticator app.
  • Sessions: random session tokens are stored only as hashes, in secure, HttpOnly cookies, and expire after 30 days of inactivity. Changing the password signs out other sessions. Failed sign-ins are limited to 10 per 15 minutes per address, and an unknown email and a wrong password get the same answer.
  • In the browser: a strict nonce-based Content Security Policy with no inline styles and no third-party sources, plus HSTS, frame blocking and the other standard security headers. Every state-changing request is checked against cross-site forgery.
  • Uploads: the file type is decided from the file's bytes (PDF, DOCX or plain text only), files get random storage names and are always served as downloads, never rendered in the page.
  • Containers: the app and the worker run as non-root users on read-only file systems with all capabilities dropped; the database runs read-only with only the few capabilities PostgreSQL needs. The database and the worker sit on an internal network with no internet access and no open ports.
  • No outbound calls: the app does not fetch job links, has no telemetry, no ads and no third-party scripts or fonts. Emails are pasted by hand; there is no mailbox connection.
  • Your data, your exit: a one-click JSON export of everything (without password hashes, secrets, recovery codes, passkey keys or session tokens), and account deletion that removes every record and uploaded file.

Under the hood

A Next.js web app with a PostgreSQL database, a separate worker container for reminders, follow-ups and "no reply" detection, and a one-shot migration step, all run with Docker Compose. Drag and drop uses dnd-kit. The interface has light and dark themes, self-hosted fonts with Greek glyphs, works at phone width and can be installed to the home screen. Unit, integration and end-to-end tests run in CI together with lint, type checks and a dependency audit.

Job Tracker was built with AI agents, reviewed by a security professional. AI agents, both local models and third party ones, made it fast to plan, build and iterate, from a written design brief to a phase-by-phase architecture plan with its own security review phase. Mikael set the requirements, reviewed the result and owns the security. There is no AI inside the product.

Stack

  • Next.js
  • React
  • TypeScript
  • Tailwind CSS
  • PostgreSQL
  • Drizzle ORM
  • Docker

Status and roadmap

Live

Live at jobs.tsakmak.com and in use for Mikael's own job search. All planned build phases of version 1 are done. It is a personal tool: single user, English interface only, web only. Visitors see only the sign-in page, and there are no accounts for others.

Planned:

  • Open source release of the code (planned).

Ideas, not scheduled: a Greek interface and a native Android app.

Not built today: email or push notifications, mailbox sync, CSV import, integrations with job sites, or any AI helpers.

Who it is for

  • Mikael, today

    one private place for a job search, so a recruiter's call never starts with "which one was that?".

  • People who self-host, later

    once the code is open sourced, anyone applying to many roles can run their own copy and keep their search on a server they control. Until then there are no accounts for others.

Interested in Job Tracker?

A self-hosted CRM for a job search: applications, recruiters, pasted emails, CV versions and interviews in one place, behind passkey sign-in.