TreeMap
A free, open-source disk-space visualizer. Squarified treemap, duplicate hunting, disk-full forecasting, and cleanup that only ever moves files to the Trash.
翻譯準備中
根據任何職位描述量身定制您的履歷——針對角色重新撰寫,絕不捏造。於會話中即時處理;除非您登入並保存版本,否則不會儲存。免費且開源。
AI 翻譯
Tailor your resume to any job description — rewritten for the role, never fabricated. Processed in-session; nothing stored unless you sign in and save a version. Free & open source.
生產力TypeScript · JavaScriptGitHub @dukesky上線中營運者未確認
試用過了嗎? 點一下就好,不需要登入。
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
Tailor your resume to any job description — in 30 seconds, without lying.
Upload your resume, paste a job link, and get it rewritten for that specific role —
plus an honest gap analysis of where you fall short. Your data is processed
in-session and never stored unless you sign in and explicitly save a version.
▶ Try the live demo · ⭐ Star this repo · Report an issue
Same method — an honest rewrite from your real experience, plus a gap analysis —
in whichever place you already are.檢視完整 README ↗Upload your resume, paste a job link, and get it rewritten for that specific role — plus an honest gap analysis of where you fall short. Your data is processed in-session and never stored unless you sign in and explicitly save a version.
▶ Try the live demo · ⭐ Star this repo · Report an issue
Same method — an honest rewrite from your real experience, plus a gap analysis — in whichever place you already are.
| What it is | Best when | |
|---|---|---|
| 🌐 Web app | career-allpath.com — paste a link, text, or screenshots and work through the result in a full editor. | You want the diff view, inline editing, and saved versions. |
| 🧩 Chrome extension | A side panel that reads the posting on the tab you're already looking at. | You're browsing LinkedIn, Greenhouse, Lever, Ashby or Workday and don't want to copy-paste. |
| 💻 CLI skill | resume-tailor — a free, open-source Agent Skill that runs inside Claude Code, Codex, or any skills-capable tool. | You live in a terminal and want no upload and no API keys. |
Built with Next.js 15 (App Router), TypeScript, and Tailwind CSS.
A four-step pipeline — all in one session, nothing stored by default.
unpdf / mammoth).Name_Company_Resume.pdf) + copy as Markdown| Route | Description |
|---|---|
/ | Landing page — value prop and a 3-step overview. |
/app | Workspace — resume + JD inputs, then the analysis/tailored-resume results view. |
/app/saved | My resumes — versions a signed-in user chose to save (preview / export / delete). |
/demo | No-backend preview of the results UI with sample data (no API calls). |
POST /api/parse-resume | Multipart PDF/DOCX (≤5MB) or a text field → extracted (unpdf/mammoth) → structured resume JSON. |
POST /api/fetch-jd | { url } → server-side fetch + Readability extraction. { ok:false, reason } on failure. |
POST /api/ocr-jd | 1–4 image uploads (PNG/JPG, ≤4MB each) → single vision call → transcribed JD text. |
POST /api/parse-jd | { text } → structured JD JSON. |
POST /api/analyze | { structuredResume, structuredJD, extraInfo } → gap analysis (score, requirements matrix, strengths, gaps). |
POST /api/tailor | analyze inputs + analysis → rewritten resume (same schema) + change_log. Never fabricates facts. Quota-gated (returns 402 when exhausted). |
GET /api/quota | Current free-tailor quota for the caller — signed-in, extension device, or anonymous ({ remaining, used, limit }). |
POST /api/device-token | Mints a server-signed, 24h device identity for a signed-out extension client. |
GET/POST /api/saved | Signed-in only. List saved versions, or save the current one (per-user Redis hash, capped at 50). |
DELETE /api/saved/[id] | Signed-in only. Delete one saved version. |
POST /api/waitlist | { email } → appended to an Upstash Redis list (early-access signup). |
Two independent concerns, two modules:
src/lib/quota.ts) — business logic. One "run" = one analyze +
tailor flow, charged once via a client-supplied runId and only on success
(see src/lib/auth.ts for how a caller is identified). Allowances by
caller: 5 per day signed in (quota:user:<userId>:<YYYY-MM-DD>, 48h
TTL); 3 per 30-day window for a signed-out extension device
(quota:device:<deviceId>); 5 per 30-day window for a signed-out web
visitor, keyed on the x-anon-id header when it's sent
(quota:anon:<anonId>, unchanged from before the extension work) or on IP
when it's absent (quota:anon:ip:<ip>). A per-IP ceiling of 20 per day
(quota:ip:<ip>:<YYYY-MM-DD>) applies on top of every tier, and a caller is
blocked when either its tier counter or the IP counter is exhausted.
Beta testers with a code in BETA_ACCESS_CODES (via ?code= →
x-access-code header) bypass the quota entirely (rate limiting still
applies). Extension callers are identified by a server-signed device JWT
(Authorization: Bearer <token>, minted by POST /api/device-token)
rather than a client-generated id, so clearing extension storage alone
doesn't reset the trial.src/lib/rate-limit.ts) — abuse protection. Per-IP fixed
window (30 requests / 60s) on the API routes.Both share a small KV abstraction (src/lib/kv.ts) backed by Upstash Redis,
falling back to an in-memory store when Upstash isn't configured. Server-side
input caps: resume 15k chars, JD 10k chars, extra info 5k chars.
Auth is handled by Clerk and is entirely optional —
the full tailoring flow works signed-out and stores nothing. Signing in unlocks a
single feature: opt-in saving. Clicking Save this version writes the current
tailored resume to a per-user Redis hash (saved:<userId>, capped at 50 versions)
via src/lib/saved.ts; those versions appear at /app/saved ("My resumes"),
each with a link back to the original posting when the JD came from a URL. Nothing
is written unless the user explicitly saves. (Clerk v7 removed the
<SignedIn>/<SignedOut> control components; src/components/clerk-auth.tsx is
a small shim that re-exposes them on top of the new <Show> primitive.)
All model choices live in one place — src/lib/llm.ts (MODEL_MAP /
QUALITY_MODELS). Calls go through OpenRouter via the openai package. A
quality flag ("fast" | "quality") overrides the analyze/tailor model; OCR is
pinned to a vision-capable model regardless.
# 1. Install dependencies
npm install
# 2. Set up environment variables
cp .env.example .env.local
# then open .env.local and add your OPENROUTER_API_KEY
# 3. Start the dev server
npm run dev
Open http://localhost:3000. The workspace lives at http://localhost:3000/app.
| Command | What it does |
|---|---|
npm run dev | Start the dev server with hot reload. |
npm run build | Create a production build. |
npm run start | Serve the production build locally. |
npm run lint | Run ESLint. |
npm test | Run this app's Vitest suite. |
npm run test:extension | Run the Chrome extension's Vitest suite (extension/). |
npm run test:all | Run both suites. |
test:extension and test:all shell out to npm --prefix extension. Since
extension/ is a separate package rather than an npm workspace, its
dependencies aren't pulled in by the root npm install — run
npm --prefix extension install once (see Chrome extension)
before either of those on a fresh clone, or they'll fail with a missing
extension/node_modules.
| Variable | Required | Description |
|---|---|---|
OPENROUTER_API_KEY | Yes | OpenRouter API key for parse/analyze/tailor/OCR (used server-side). The model is served via OpenRouter. |
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY | Yes | Clerk publishable key — required for the app to render (auth provider). Get one at clerk.com. |
CLERK_SECRET_KEY | Yes | Clerk secret key (server-side) — backs sign-in and the saved-versions API. |
UPSTASH_REDIS_REST_URL | Prod | Upstash Redis REST URL — backs quota, rate limiting, saved versions, and the waitlist. |
UPSTASH_REDIS_REST_TOKEN | Prod | Upstash Redis REST token. |
NEXT_PUBLIC_SITE_URL | Optional | Canonical site URL for absolute OG/Twitter share-image links. Falls back to the Vercel production URL, then localhost. |
BETA_ACCESS_CODES | Optional | Comma-separated codes granting unlimited tailors (via ?code=). |
DEVICE_TOKEN_SECRET | Prod | Secret for signing Chrome-extension device tokens (HS256). Generate with openssl rand -base64 32. |
ALLOWED_EXTENSION_IDS | Optional | Comma-separated Chrome extension IDs permitted to call the API (CORS). Empty means no extension origin is accepted. |
Keep the secret values server-side only — never expose them with a
NEXT_PUBLIC_ prefix (the two NEXT_PUBLIC_ vars above are intentionally
client-safe). Without the Upstash vars the app still runs, but quota/rate-limit/
saved-versions/waitlist use a per-process in-memory store that is not shared
across serverless instances — so set them for any real deployment. The Clerk
keys are required for the app to boot; grab free test keys from the Clerk
dashboard for local development.
OPENROUTER_API_KEY, the two
Clerk keys (NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY), and — for
real deployments — the Upstash Redis vars, for the Production (and Preview)
environments.npm i -g vercel
vercel # first run links the project and creates a preview
vercel --prod # promote to production
Pull the project's environment variables into your local .env.local at any
time with:
vercel env pull .env.local
extension/ is a separate, thin-client package (its own package.json, not an
npm workspace) that lets you tailor your resume against the job posting in
your active tab without leaving it. It talks to the same API as the web app —
no prompts or model choices live in the extension itself.
Not a browser person? resume-tailor runs the same method as an Agent Skill in Claude Code, Codex, and other skills-capable tools — no upload, no API keys.
/app/saved page shows.# 1. Install its dependencies (separate from the root install)
npm --prefix extension install
# 2. Build it — against production...
npm --prefix extension run build
# ...or against a local API (http://localhost:3000)
npm --prefix extension run build:dev
# 3. Run its tests
npm --prefix extension run test
Then load it unpacked:
chrome://extensions, enable Developer mode (top right).extension/dist.The manifest pins a key — the public key the Chrome Web Store generated at
first upload — so a locally loaded unpacked build and the store-installed
extension share one ID: epofgiefihhmbjhojdeffkdkhocjfpaf. Add it to the
server's ALLOWED_EXTENSION_IDS environment variable (comma-separated) so
the API's CORS layer recognizes it. That check is defense-in-depth, not the
thing making requests work: in MV3, a fetch from an extension page to a
host listed in the manifest's host_permissions bypasses CORS regardless of
ALLOWED_EXTENSION_IDS. (npm run package strips the key field from
store uploads, which the store requires on a first upload and ignores after.)
Sign-in uses Clerk's own client directly inside the extension — a dedicated
sign-in page, not the web app's session (Clerk's Sync Host doesn't work on
side panels, so signing in on the website does not carry over into the
extension). See CHANGELOG.md for what's shipped so far, and
/privacy for exactly what the
extension stores locally versus sends to the server.
career-path is designed to keep your data in your session. The parse → analyze → tailor pipeline is stateless: resume files and job descriptions are not written to any database or persistent store, whether or not you're signed in. A tailored result is persisted only when a signed-in user explicitly saves it (stored per-user in Redis, deletable from My resumes).
The server does keep a small amount of operational data for every caller, signed in or not, to enforce the free allowances and watch for abuse: usage counters, rate-limit counters, and aggregate model timing/token counts with no user content attached. None of it is your resume, your job description, or a tailored result you didn't explicitly save.
The complete list lives at /privacy.