I Built My Own Interview Command Center to Survive the UAE Job Market
Job hunting in the UAE right now is a numbers game played against software. Openings are scattered across LinkedIn, Indeed, Bayt, GulfTalent, Naukrigulf and hundreds of company career pages, each with its own login and its own form. Every job description is screened by an ATS that wants its own keywords, so the same experience has to be rewritten for every role. And when an interview finally lands, a new problem shows up.
Most of us now build with AI assistants. That's simply how software gets made in 2026. But in a system design round nobody asks what the AI suggested. They ask why: why a queue here, why this database, why this boundary. Explaining decisions out loud is a separate skill from shipping them, and generic "top 50 questions" lists don't train it.
So I built the tool I needed: Interview Command Center, a self-hosted platform that tracks the whole search, applies on my behalf within strict guardrails, tailors my CV per job, and turns every interview into preparation for the next one. It's open source under MIT, and this post is about the decisions behind it.
The loop it's built around
The core idea is that the questions you were asked, the answers you gave and the concepts you missed are the most valuable study material you have. They usually end up lost in a notes app. The platform is built around one loop:
Capture, journal, find gaps, build a targeted plan, practice, evaluate, improve, reuse.
Every feature hangs off that loop:
- ▸Application tracker: table, Kanban and timeline views, duplicate detection, contacts, follow-up reminders, and a record of which CV version went to which application.
- ▸Interview journal: each company gets its own sequence of rounds with the exact questions asked, your original answer, missed concepts, mistakes and code, then improved and approved answers.
- ▸Knowledge base: PostgreSQL full-text search across every interview. The same question asked at two companies links to one entry, and an SM-2 spaced-repetition queue brings it back before you forget it.
- ▸Round-specific crash courses: built from the job description, round type, deadline, your CV and your recorded weak spots. Prioritised topics with reasons, a time-boxed schedule, lessons, model answers, flashcards, mock interviews and readiness tracking.
- ▸Resume builder: unlimited job-specific copies with a live A4 preview and PDF export, plus AI tailoring per job.
- ▸Coding practice: multi-stage problems in Python or JavaScript, tests running in the browser, and an AI review that scores correctness, approach, verification, code quality and communication.
- ▸Auto Apply: job discovery through Google Jobs and Jooble plus ATS boards like Greenhouse, Lever and Ashby, fit scoring with reasons, an ATS keyword check, and applying through my own browser.
Honesty is a feature, not a disclaimer
The moment you put an LLM near a CV, you create a liar with good grammar. So the system enforces honesty in code, not in prompts.
- ▸Tailoring can only reword and reorder. The resume tailoring step is allowed to change phrasing and ordering, never facts. Numbers the model adds are rejected in code, and the master resume is never modified.
- ▸Original answers are locked. Once you save what you actually said in an interview, it can't be edited. Improved answers live next to it, so you can see the gap honestly instead of rewriting history.
- ▸Every question carries a label: actually asked, public report, AI prediction or practice. A predicted question never quietly passes as real interview data.
- ▸Facts extracted from your CV stay "AI-inferred" until you confirm them.
This matters because the whole point is preparing for a real conversation with a real interviewer. A tool that flatters you is worse than no tool.
Guardrails before automation
Auto Apply was the feature I was most nervous about building, because bad automation is how you get blacklisted by a recruiter. So the guardrails came first:
- ▸It stops on CAPTCHAs and login walls instead of trying to get around them.
- ▸It never guesses an answer. Every response comes from an apply kit of answers I saved myself, and anything unknown pauses the job for me.
- ▸It never applies to the same job twice, and every submission has to leave proof.
- ▸Before applying, it checks the CV's ATS keyword match and tailors a copy when the score is low.
- ▸It applies through my real, signed-in browser, because modern job forms reject headless automation, and a live Mission Control page shows the whole pipeline.
Scoring is explainable too. Every job gets a fit score with the reasons and hard blockers behind it, so "why did it skip this one?" always has an answer.
Architecture: boring on purpose
The stack is a modular monolith with three processes from one codebase:
- ▸Web: Next.js 16, talking to the API through a same-origin rewrite.
- ▸API: NestJS 11 with PostgreSQL 17 as the single source of truth.
- ▸Worker: Redis and BullMQ for background tasks and the scheduler.
Every AI job is a task row in PostgreSQL before it's a queue message. Redis can lose its data, a worker can crash mid-task, and nothing is lost: tasks have leases, retries and crash recovery, and the queue is rebuilt from the database. For a personal tool that runs on a home server, recoverability beats cleverness.
AI is optional and pluggable. Any OpenAI-compatible endpoint works, from Ollama on a laptop to a hosted provider. Alternatively, tasks can run through a Claude Code or Cursor subscription you already pay for, as exported task packages with JSON Schemas that are validated before anything is imported. And with no AI configured at all, tracking, journaling, search, revision and scheduling keep working. AI is an accelerator, not a dependency.
What building it taught me
- ▸Your own data beats generic data. The single most useful prep material has been my own journal of real questions and real mistakes.
- ▸Constrain the model with code, not adjectives. "Please don't invent facts" in a prompt is a wish. Rejecting added numbers in a validator is a guarantee.
- ▸Automation needs a stop button more than it needs speed. Every Auto Apply guardrail exists because the cost of one wrong submission is higher than the value of ten fast ones.
- ▸Design for the day the AI is down. A tool that only works when the model works isn't a tool you can rely on during a job search.
Try it, and tell me what's missing
It runs with one command:
git clone https://github.com/azadhmhd/interview-command-center.git
cd interview-command-center
cp .env.example .env # set APP_ENCRYPTION_KEY
docker compose up -d --buildThe project is actively developed. I built it for my own search, but I know I'm not the only one stuck in this loop. If you're job hunting in the UAE, the Gulf or anywhere else, use it, break it and open an issue with what would make your search easier. Feedback decides what gets built next. Let's get hired.