Defense Expat Job Tracker

Private · local-only · scored against your fixed criteria

Postings

More filters ▾
! Posting Location Comp (all-in) Score Status Seen

Networking — contacts

Every recruiter / hiring-manager / referral you log against a posting rolls up here, sorted so the people you haven't touched in the longest time surface first. Roles at your level move through people — keep these warm. Add contacts from a posting's details → Contacts.

ContactRole / channelPostingLast contactNext step

Add a Posting

Parsing is a best-effort helper. Always review the fields before saving.

The real age of the role — distinct from when you first saw it.

Watch List — saved searches

Click a link to check the source. Update "last checked" after you review it. Live scraping is intentionally avoided — this is a fast manual dashboard.


Config / Rubric editor

Tune weights, priority locations, employers, the comp bar and hard filters. Changes apply to future scores and to anything you re-score. Edit the JSON and Save, or use the field editors below.

Comp estimates — used when a posting doesn't state pay

When comp is blank, the score uses these all-in estimates (by role level × whether the role has an expat/SOFA package) instead of a flat mid-band. Tune to your market read.

Your profile — used by the "✉ Draft outreach" helper

This is dropped into the outreach prompt the tracker copies for you. Keep it current.

Advanced — raw config JSON (full weights object)

Edit weights here for fine control. Keys map to the rubric categories. Save JSON to apply.

Backup / Restore

All data lives in this browser's localStorage only. Nothing leaves your machine. Export regularly to back up or move between machines.


Merge monitor inbox

Import newly-found postings from the weekly job monitor (job-monitor/postings-inbox.json). Merge adds new postings and re-scores them, skips ones you already have (matched by URL or title+company), and never touches the status, notes, or dates on postings you're already tracking.

Accepts the monitor's inbox array, or a full tracker export (its postings are merged in).

Postings: 0
Watch sources: 0
Storage key: djt_state_v1

How it works (README)

Add a posting

Go to Add Posting. Paste the raw job text and click Parse text → fields to auto-extract title, company, location, comp, clearance, expat/SOFA flags, role level and domain tags. Or skip the paste and fill fields manually / from a URL. Review the fields (parsing is best-effort), watch the live score preview, then Save.

Finding things fast (v2 layout)

The dashboard opens with ⚡ Needs attention — one deduped list of everything that matters right now (priority-location hits, genuinely-new postings, overdue follow-ups), each row tagged with why it's there. Below it: a search box (press / anywhere to jump to it — searches title, company, location, tags, and notes) and quick-filter pills with live counts (Priority / New / Fit 70+ / Pipeline / BD / Local hire / Archived). The old dropdowns live under More filters ▾. Click any row to expand its detail (score breakdown · facts & actions · notes · contacts); the stat tiles up top are clickable filters too.

How scoring works

Hard filters run first. If any disqualifier fires the role is AUTO-REJECT (still stored, visually de-prioritized, with the reason shown). Otherwise the role earns 0–100 across five weighted categories:

  • A · Status & benefits (30): expat package +20, SOFA +10.
  • B · Compensation (20): ≥$244K +20 · $200–244K +14 · $180–200K +8 · below $180K w/ strong benefits or priority location +4. Unknown comp is scored as mid-band and flagged.
  • C · Location (20): Kyotango/Kyogamisaki or Komatsu +20 (PRIORITY) · Kansai/Hokuriku/western +15 · Tokyo/Kanto +12 · elsewhere Japan +8.
  • D · Role level & type (15): leadership +10 · defense/aerospace domain fit +5.
  • E · Employer & clearance (15): priority employer/integrator +8 · clearance ≤ TS/SCI +4 · skill-stack match +3.

Bands: 85–100 strong (act now) · 70–84 good (apply) · 50–69 marginal (review) · <50 or auto-reject (archive). Any Kyotango/Kyogamisaki/Komatsu hit, or any score ≥85, raises a PRIORITY ALERT pinned at the top.

Track applications

Each posting has a status (Watching → Applied → Under Consideration → Interview → Offer → Rejected → Archived), an applied date, and a free-text notes log. Set status from the dashboard row; expand a row for the score breakdown, notes and edit/delete.

First seen, posting age, expiry & what's new

Two different dates are tracked: Date posted (when the employer posted it — the real age of the opening) and First seen (when this tool first detected it). A 2-year-old req you just discovered has an old posted-date but a recent first-seen — so it won't masquerade as fresh. Postings older than the stale threshold (Config, default 60 days) get a STALE badge; ones you mark Posting expired/closed (auto-detected from "Job Expired" text when parsing) get an EXPIRED badge, are kept out of the priority & "new" panels, sorted to the bottom, and can be bulk-cleared with Archive expired or hidden with Hide expired/stale.

The "New since your last visit" panel and green NEW badge only fire for postings that are genuinely new and still live (not stale/expired) — that's your real "something new showed up" signal. Hit Mark all as seen to reset it. The Trends tab charts new postings per week (last 12 weeks) plus breakdowns by band, region, employer, and status, from your own data; the weekly monitor also writes a durable job-monitor/history.json so the trend record survives a browser wipe.

Japan / XPAT signals (don't trust the location field)

Defense primes post Japan billets under a US HQ city (Lockheed lists them under Orlando or Bethesda) and tag the title XPAT. So the location column can say "Bethesda" for a job that's actually in Japan. Each posting therefore shows independent signal chips derived from the whole posting text: a green Japan chip (mentions Japan / a base / JASDF / SOFA), a blue XPAT chip (expat package — relocation/housing/COLA/LQA), a purple OCONUS chip (uses "OCONUS" — an overseas billet, sometimes without even saying "Japan"; counts as an expat-equivalent allowance structure in scoring), and an amber ⚠ US-HQ listing when the stated location reads as US but the role is a Japan/overseas billet. The scorer already keys off these, not the HQ city, so these roles aren't wrongly auto-rejected as CONUS.

Role types: BD, local-hire & Japanese-fluency

Three more flags help you track roles beyond the standard expat billet:

  • BD (cyan badge) — Business Development / capture-management roles, recognized as a domain fit for your MBA + FMS program-execution background. Filter the table by Type → Business Development.
  • LOCAL HIRE (grey badge) — a Japan role with no expat package and no SOFA. Normally that's an auto-reject, but for the employers in Config → "Track local-hire at these employers" (default: Lockheed Martin) they're kept and tracked instead — they just score lower without the package. Filter by Type → Local hire.
  • 日本語 req (pink badge) — the posting needs business-level/native Japanese (JLPT N1/N2, "fluent", or kanji-heavy text). Since you're N3 this isn't a strong fit, so it takes a configurable points penalty (Config → "Japanese-fluency penalty").

Casting a wider net

The Watch List is seeded with ~30 saved searches — the six primes, the major integrators (Leidos, SAIC, Peraton, Amentum, V2X, GDIT, CACI, Booz Allen, ManTech), the cleared boards (ClearanceJobs, ClearedJobs, Indeed, ZipRecruiter, LinkedIn), and per-base Lockheed searches. Tip that finds the most: search by the Japan base name (Misawa, Iwakuni, Nyutabaru, Komatsu, Yokota…) and by XPAT rather than "Japan", because the HQ-city listing trick hides them from a plain "Japan" search. Click Restore seeded sources on the Watch List to pull in the expanded set. The weekly monitor runs all of these for you.

Contacts & networking

Roles at your level move through people, so each posting has a Contacts section (open a posting → details). Log the recruiter / hiring manager / referral with their channel, last-contacted date, and next step. The Networking tab rolls every contact up into one table, sorted so whoever you haven't touched in the longest (or never) surfaces first — overdue last-contacts and past-due next-steps are flagged red. A 👤 count shows on any posting that has contacts.

Follow-up nudges & freshness

An ⏰ Follow-ups due panel appears on the dashboard listing any application in an active stage (Applied / Under Consideration / Interview) that's had no status change in 14 days (configurable) — so warm leads don't go cold. Separately, when the weekly monitor stops re-seeing a posting for 21+ days (configurable), it gets a MAYBE CLOSED badge — this catches roles that quietly disappear without ever saying "expired." (Merging the inbox refreshes "last seen" on postings the monitor still finds, without touching your statuses or notes.)

Dead vs. live links

Career-site URLs die fast, so a "new" posting can already be gone. The weekly monitor now verifies each link before adding it and re-checks existing ones every run: confirmed-dead postings are marked EXPIRED (and drop out of "new" and the priority list). Links it can't auto-check — Workday, LinkedIn and Phenom pages render as apps or need a login — are kept but flagged ⚠ LINK? so you know to confirm them yourself; verified-open ones show ✓ LIVE. Bottom line: trust ✓ LIVE, sanity-check ⚠ LINK?, ignore EXPIRED.

Duplicates across boards

The same job often appears on the company site, LinkedIn, and ClearanceJobs as three different URLs. Near-duplicates (same core role + company) get a DUP? badge; Review duplicates on the dashboard groups them and archives the extras — keeping the best copy and all its notes/contacts, deleting nothing.

Comp estimates & outreach helper

Most defense postings hide pay. Instead of scoring those as a flat mid-band, the tracker now estimates all-in comp from the role level × whether the role carries a package (expat/SOFA) — so a no-comp expat leadership role scores like ~$245K while a local-hire role scores realistically lower. The breakdown shows "estimated $X" so it's never mistaken for stated pay. Tune the six numbers under Config → Comp estimates (or turn the feature off there).

Each posting's details has a ✉ Draft outreach button: it builds a tailored prompt from your profile + that role (title, fit reasons, posting notes, first contact) and copies it to your clipboard — paste into Claude to generate a recruiter-outreach message and a cover-note. Edit your profile under Config → Your profile. (Like "Run now with Claude," the page can't call Claude itself, so it hands you a ready prompt.)

Edit the rubric

In Config / Rubric tune the comp bar, priority locations, employer lists, hard-filter toggles, and (advanced) the full weights JSON. Use Re-score ALL to apply new weights to existing postings.

Export / import

In Data, export a JSON backup or import one. Storage is local-only (djt_state_v1); no server, no login, no analytics, no external calls. Because your data lives only in this browser, the dashboard shows a 💾 backup reminder if it's been 14+ days (configurable) since your last export — one click exports and clears it. The layout is also mobile-friendly (the postings table scrolls sideways on a phone; everything else stacks).

Optional automated monitoring (not built-in)

Live scraping of career sites is fragile and often against ToS, so this app is deliberately paste-to-score + a saved-search dashboard. If you later want scheduled checks, a small Node script + config + GitHub Actions cron can poll only permitted RSS/API feeds and write results into the same JSON this app imports. Keep it optional and clearly labeled.