尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Picks up intern / fresher / junior web & software jobs in Bangladesh or remote the moment they're posted on 34 platforms. Every published job stays on the portal (newest first, paginated); "Today" and other dates are filters. Product spec: docs/PRD.md.
always-on worker (npm run worker) — one loop per platform
│
▼ last 7 days (Dhaka) → gate: dev role? junior? BD, or remote open to BD? → dedup → Postgres (Supabase)
Portal ◄── SSE /api/jobs/stream (new jobs appear within ~5 s) Admin ◄── live platform status
| Platform | How | Every | Cost |
|---|---|---|---|
| BDJobs | public JSON feed (IT category + keywords, every page) | 3 min | free |
| atB Jobs | public JSON API | 5 min | free |
| NextJobz | job list + each new job page (JSON-LD) | 5 min | free |
| Skill.jobs | public JSON API (salary, level) | 30 min | free |
| Himalayas | public API (says which countries a remote job is open to) | 10 min | free |
| Remote Rocketship | page data, all levels | 30 min | free |
| Arc.dev | page data (requiredCountries) | 30 min | free |
| Wellfound | page data | 30 min | free |
| Jobright AI | search page data (sometimes bot-checked; retries) | 30 min | free |
| Remotive | public API, software-dev (terms: a few calls a day, link back) | 6 h | free |
| Remote OK | public API (terms: link back, name the source) | 60 min | free |
| Jobicy | public API, dev industry (level, region, salary) | 60 min | free |
| Working Nomads | public feed, Development category | 60 min | free |
| We Work Remotely | RSS: full-stack, front-end, back-end | 30 min | free |
| Hacker News | "Who is hiring?" monthly thread, via the Algolia HN API | 3 h | free |
| Company career pages | Greenhouse board API (Canonical, GitLab, Automattic — editable) | 2 h | free |
| one combined RSS feed of r/forhire, remotejs, jobbit, hiring, WebDeveloperJobs, DeveloperJobs | 60 min | free | |
| LinkedIn jobs | Apify curious_coder/linkedin-jobs-scraper, Bangladesh | 15 min | ~$0.002/job |
| LinkedIn company pages | Apify harvestapi/linkedin-company-posts (Talent Mesh Tech) | 30 min | ~$0.002/post |
| Facebook groups (59) | Apify memo23/facebook-public-group-posts-scraper | 60 min | ~$0.0037/post (measured) |
| X (Twitter) | Apify memo23/x-twitter-search-scraper, hiring searches | 3 h | ~$0.0004/tweet |
| Indeed | Apify, remote entry-level role searches | 2 h | ~$0.005/job |
| Google Jobs | Apify johnvc/Google-Jobs-Scraper: remote searches across all job sites Google indexes (Glassdoor, ZipRecruiter, JobLeads, BeBee, Jooble, Built In, Jobgether, company career pages…) | 24 h | ~$0.09/page of 10 |
| Company career pages (Lever, Ashby) | free public APIs; company lists editable in Admin | 2 h | free |
| Built In, Remote-Work.app, Early Tech Roles, NewGrad.ai, YouHired, JobPilot, Remotely AI Jobs | list page / RSS → each matching job page’s schema.org JobPosting (who can apply, location, date) | 1–2 h | free |
| Glassdoor | Apify bebity/glassdoor-jobs-scraper, remote internship / entry-level | 12 h | ~$0.0004/job |
| Welcome to the Jungle | Apify shahidirfan/Jungle-Job-Scraper, fully remote only | 24 h | ~$0.001/job |
Free sources come first; Apify is used only where no free access exists (LinkedIn, Facebook, X, Indeed). Not added: X's own API (paid), LinkedIn groups (login only — ban risk), Arbeitnow (mostly Germany / EU-only remote roles), Chakri.com, Prothom Alo Jobs, Bayt, Careerjet BD (down, blocked or no usable feed when tested in Oct 2026). Facebook: 36 of the 59 groups returned posts in testing; the other 23 look private or inactive.
Several Apify tokens can be set (APIFY_TOKENS=a,b,c): runs use the first token with credit and
switch automatically when one runs out (Admin → Platforms shows each token's remaining credit).
npm install
npm run db # terminal 1 — local Postgres (no install needed)
npm run db:push # once (and after schema changes) — creates the tables
npm run dev # terminal 2 — website at http://localhost:3000
npm run worker # terminal 3 — the always-on scraper (keep it running)
.env.local needs APIFY_TOKEN (LinkedIn / Facebook / Indeed). BDJobs works without it.
Admin: /admin, password = ADMIN_TOKEN. One-off check without the worker: npm run check -- bdjobs.
Tables are defined in prisma/schema.prisma (Prisma + Postgres). To use Supabase:
.env.local (and in Vercel / your host):
DATABASE_URL = the Transaction pooler URL (port 6543, ends in ?pgbouncer=true)DIRECT_URL = the Session pooler / direct URL (port 5432)npm run db:push creates the tables in Supabase. If the database is shared with another app,
add schema=ph_jobs to both URLs first so this project gets its own schema.npm run copy-db -- <old postgres url> (e.g. the local one) or
npm run migrate:mongo (from the old MongoDB). Both are safe to re-run.The app only talks to Postgres through Prisma, so any Postgres host works the same way.
A job is published only if all of these hold (src/lib/pipeline/rules.ts):
INGEST_DAYS days (default 7, Bangladesh time) when first picked
up, so a worker that was off catches up. Once published, a job is never hidden automatically.JUNIOR_MAX_YEARS, default 2 years).
Senior / lead / manager / mid-level are filtered out.If the level isn't stated, the job goes to Admin → Review instead of the portal. With
ANTHROPIC_API_KEY set, Claude reads those posts (and Facebook posts) and decides automatically.
Every filtered job keeps its reason (Admin → Review → Filtered out).
remote: [] in its settings) —
they'd cost ~$20/day for about one genuine remote job.Only one worker can run at a time (a heartbeat lock in the Lock table): a second
npm run worker exits with "Another worker is already running", so checks — and Apify bills —
are never doubled. If a worker is killed, the next one can start after ~90 seconds.
npm run check -- linkedin # run one check now
npm run backfill -- 7 # collect the last 7 days on every platform (--free / --paid)
npm run retag # re-apply changed rules (tracks, stack, level) to stored jobs
npm run rescore # add jobs missing from stored raw data (no Apify cost)
npm run replay -- <source> <apifyDatasetId|file.json>
Only jobs that pass the filter are stored, and they stay — every stored job is on the portal.
A post that fails the filter leaves nothing in the database (not even its raw payload). Stored
jobs are never expired; retag removes one only if a rule change means it no longer passes.
Raw payloads of stored jobs (for rescore) are dropped after 14 days.
Platform settings (keywords, interval, groups) are edited live in Admin → Platforms; the worker picks up changes on its next round.
The website and the worker can live in different places — both only talk to the database.
vercel.com → Add New → Project → import this GitHub repo (Next.js is detected;
the build runs prisma generate && next build).
Environment Variables (Settings → Environment Variables), copied from .env.local:
| Name | Value |
|---|---|
DATABASE_URL | Supabase transaction pooler (port 6543) URL, ending in ?pgbouncer=true&schema=ph_jobs&connection_limit=1 |
DIRECT_URL | Supabase session pooler (port 5432) URL, ending in ?schema=ph_jobs |
APIFY_TOKENS | as in .env.local (used by Admin → "Check now") |
ADMIN_TOKEN | the /admin password |
ANTHROPIC_API_KEY, CLAUDE_MODEL | optional, as in .env.local |
connection_limit=1 keeps each serverless function to one database connection.
Deploy. vercel.json pins the functions to Sydney (syd1), next to the Supabase project —
change it if the database is in another region.
Vercel doesn't run long-lived processes, so the worker runs elsewhere (next section). The free plan
allows only daily crons, so vercel.json has none. On a Pro plan you can let Vercel do the checking
instead of a worker: add "crons": [{ "path": "/api/ingest/tick", "schedule": "*/10 * * * *" }] and
set CRON_SECRET.
Run npm run worker anywhere with .env.local pointing at the same Supabase database:
pm2 start ecosystem.config.cjs --only ph-jobs-worker && pm2 save.npm run build && pm2 start ecosystem.config.cjs && pm2 save (website + worker).Run only one worker — a second one exits by itself (see above).