hiring-stack
What's the market actually paying to hire for this month? Stop guessing — look at the hiring thread.
A live, public, monthly tech-stack demand index built from every Ask HN: Who Is Hiring? thread.
For each tool / framework / library / cloud / model / language, see how many jobs ask for it this month, the month-over-month trend, the companies hiring for it, and the geo / remote split. Real Hacker News Algolia data, classified by Claude Haiku — refreshed every 30 minutes, zero auth, no mocks.
Live
- App: https://holyai.me/hiring-stack/
- Health: https://holyai.me/hiring-stack/api/health
- API: https://holyai.me/hiring-stack/api/{stats,tools,trending,declining,postings,companies,months}
Why this exists
The canonical monthly Ask HN: Who is hiring? thread is the cleanest public-job source on the internet. Strict format, engineering-heavy, ~300–700 top-level comments per month, 11 years of archives, free to read via the Hacker News Algolia API. But the thread is unsearchable: try answering "is LangGraph hiring demand up or down vs. April?" from the HN UI — impossible without 30 minutes of Ctrl+F.
hiring-stack parses the thread, classifies every posting with Claude Haiku, surfaces trends.
Data sources (real, no mocks)
| Source | URL | Refresh | Auth |
|---|---|---|---|
| HN Algolia search for hiring threads | https://hn.algolia.com/api/v1/search_by_date?query=Ask+HN+Who+is+hiring&tags=story | every 6 h | none |
| HN Algolia item (full comment tree) | https://hn.algolia.com/api/v1/items/<story_id> | every 30 min (current); every 6 h (recent 6 mo) | none |
| OpenRouter → anthropic/claude-haiku-4.5 for classification | https://openrouter.ai/api/v1/chat/completions | per new posting, cached forever | OPENROUTER_API_KEY |
Every posting in the DB is traceable to a real hn_comment_id reachable at https://news.ycombinator.com/item?id=<id>. No seed array of fake jobs. No Math.random() jitter. If Algolia returns 0 hits, the page shows "no postings yet" — never fabricated. If OPENROUTER_API_KEY is missing, raw comments still ingest but classification stays pending and the UI shows an honesty banner.
Stack
- Node.js 20+, Express 4
better-sqlite3(WAL mode, single file at./data/hiring-stack.db)node-cronfor scheduled fetches and classifier batcheshelmet,compression- Vanilla JS SPA, dark theme, English UI, Chart.js (CDN) for sparklines
Run locally
npm install
cp .env.example .env # add real OPENROUTER_API_KEY (optional)
node server.js
# open http://127.0.0.1:4870/hiring-stack/
On first boot with an empty DB, the server bootstraps the last 6 months of hiring threads + comments. With a key, the first 50 classifications run synchronously; the rest catch up via the /5 * cron.
Env
| Key | Required | Default | Meaning |
|---|---|---|---|
| PORT | no | 4870 | HTTP port |
| OPENROUTER_API_KEY | classifier-only | — | If missing, postings ingest but stay unclassified |
| CLASSIFY_BATCH_SIZE | no | 20 | postings per classifier batch |
| SKIP_BOOTSTRAP | no | 0 | set to 1 to skip cold-start ingest |
Cron schedule
| Cron | Job |
|---|---|
| /30 | refresh current month thread |
| 0 /6 | discover new threads + refresh recent 6 months |
| /5 | classify a batch of pending postings (cheap, idempotent) |
| 0 | rebuild monthly_tool_counts aggregate |
License
MIT.