Open-source · github.com/YuZh98/academic-application-tracker
A local Streamlit dashboard that answers one question every morning: “What do I do today?”
Track dozens of postdoc, PhD, faculty, and fellowship applications in parallel — deadlines, recommendation letters, materials checklists, interview rounds — without a single missed follow-up.
![]()
Who is this for?
Anyone juggling academic job applications at scale — postdocs, PhD candidates approaching graduation, faculty applicants, fellowship seekers. If you’re tracking 5–100+ positions with overlapping deadlines, different document requirements, and multiple recommenders, this replaces the spreadsheet you’ve outgrown.
Why not a spreadsheet?
| Problem | Spreadsheet | This tool |
|---|---|---|
| Deadline urgency | Manual sorting, easy to miss | Auto-computed, color-coded red/yellow by proximity, surfaced every session |
| Recommender tracking | One row per person, no per-position state | One recommender × seven positions = seven independent states; flags overdue, offers one-click mailto |
| Materials readiness | Scattered notes | Per-position checklist (CV, cover letter, research statement, …); dashboard shows ready-to-submit count at a glance |
| Daily action items | You figure it out | Dashboard tells you |
Quick start
| |
Python ≥ 3.11. Open the URL Streamlit prints (default http://localhost:8501).
The SQLite database is created on first run — the empty-state screen walks you through adding your first position.
Your data lives in a postdoc.db file that appears in the project folder after your first save — copy that file to back it up (stop the app first to avoid a torn copy). To update later, git pull && pip install -r requirements.txt. See docs/dev-notes/self-host-setup.md for backup, troubleshooting, and update details.
Features
Dashboard
KPI grid (Tracked / Applied / Interview / Next Interview), application funnel, materials readiness panel, upcoming deadlines, and recommender alerts — one screen, one daily answer.
Opportunities
Quick-add a position in under 30 seconds. Full edit panel with four tabs (Overview / Requirements / Materials / Notes). Filter by status, priority, field, or full-text search. Urgency-banded deadline column.
![]()
Applications
Per-position card: applied date, confirmation, response, result, outcome. Inline multi-round interview log. Pipeline cascades automatically: saved → applied → interview → offer.
![]()
Recommenders
Pending-alert cards with mailto and LLM-prompt helpers to draft a follow-up. Full (position × recommender) matrix with inline edit. Flags anyone asked more than 7 days ago who hasn’t confirmed.
![]()
Export
Every database write auto-regenerates plaintext markdown files (OPPORTUNITIES.md, PROGRESS.md, RECOMMENDERS.md) in the exports/ folder — always a fresh, portable backup of your entire job-search state. Manual regenerate + per-file download also available.
Built to last
800+ tests · 97% coverage · strict four-layer architecture · CI on every PR · spec-first development. This is a production-grade tool, not a weekend script.
Engineering deep-dive
Architecture — four strict layers
| |
Layer contracts are enforced by cohesion tests that fail CI if any rule drifts.
Testing
Integration tests use the official streamlit.testing.v1.AppTest harness against real page files; unit tests run against per-test temp SQLite files via a db fixture. A second test pass with -W error::DeprecationWarning catches Streamlit-API drift before it surfaces on upgrades.
CI pipeline (every PR)
- ruff lint (zero warnings)
- pyright strict-basic (zero errors)
- pytest (two passes: normal + deprecation-as-error)
- Status-literal grep — no hardcoded status strings in page code; all vocabulary routed through
config.py
Config-driven schema
Adding a new required document type (e.g. “Portfolio”) = one tuple appended to config.REQUIREMENT_DOCS. init_db() adds the columns automatically on next start. No other file changes needed.
Import-time invariants
config.py asserts structural integrity at module load — every status has a color and a label, urgency thresholds are ordered, funnel buckets cover all statuses exactly once. Misconfiguration aborts startup with a clear traceback before any page renders.
Spec-first development
DESIGN.md is the authoritative spec for the schema, page contracts, cascade rules, and export format. Implementation tracks the spec; deviations land as spec amendments with commit references.
Stack
| Layer | Technology |
|---|---|
| UI | Streamlit 1.57 · Plotly |
| Data | SQLite · pandas |
| Language | Python 3.11+ |
| Dev tooling | pytest · ruff · pyright |
Project structure
| |
Roadmap
- AI auto-fill — paste a job listing URL, get position details pre-populated
- Calendar integration (
.icsexport for deadlines and interviews) - Email notifications for approaching deadlines
- Bulk import from CSV / existing spreadsheets
- Analytics — time-to-response trends, success rates by field
Contributing
Contributions welcome! Read GUIDELINES.md for coding conventions and TDD workflow, then check the issue tracker for open tasks. Every PR runs the full CI pipeline — lint, type-check, and all tests must pass.
Documentation
| Doc | Start here if… |
|---|---|
DESIGN.md | You want to understand the schema, page contracts, cascade rules, or export format |
GUIDELINES.md | You want to contribute or understand the coding conventions |
CHANGELOG.md | You want the per-release development narrative |
docs/dev-notes/ | You hit a Streamlit-specific gotcha or need dev setup details |