TreeMap
무료 오픈소스 디스크 사용량 시각화 도구로, 사각형 트리맵·중복 파일 탐색·디스크 가득 예측·정리 시 파일을 휴지통으로만 이동한다
채용 공고를 붙여넣으면 11개의 ATS‑평가 템플릿에 맞춘 이력서와 면접 질문, 개선할 스킬 격차를 제공합니다
Paste a job posting and get your resume tailored in 11 ATS-rated templates, the interview questions it invites, and the skill gaps to close. Nothing invented.
생산성TypeScript · CSSGitHub @kos15온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Tailors a résumé to a job posting — six drafts, likely interview questions, and the skill gaps between them. Nothing is invented.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗One résumé in, eleven tailored out — plus the questions this posting suggests and the gaps it exposes. Nothing is invented: bullets are reordered, reworded and re-weighted, and every generated bullet carries a foreign key to the user's own words.
CLAUDE.md is the operating contract, docs/product/specs.md the architecture,
docs/product/plan.md the milestone order, and PENDING.md the open work. Read those before
changing behaviour. This file is the runbook. Every change is test-first: pnpm test.
pnpm install
cp .env.example .env.local # fill in Clerk, Supabase, OpenAI
Two connection strings, both required (.env.example documents both): DATABASE_URL is the
pooled pgbouncer connection (port 6543) the app runs on; DIRECT_URL is a real session
connection (port 5432) that migrations, the two admin scripts, and the deploy-time catalog lock and schedule install need — a transaction-mode
pooler can't provide one.
pnpm db:generate # regenerate the Prisma client after any schema.prisma change
pnpm db:migrate:dev --name x # author a new migration locally (prompts, applies immediately)
pnpm db:migrate # apply committed migrations — CI/prod, non-interactive
pnpm db:policies # apply lib/db/policies.sql — RLS lives in the repo
pnpm seed:catalog # templates + skills + link-checked course catalog
On Vercel, the build runs these automatically on every deploy (not seed:catalog — deploy:catalog syncs the catalog instead, link-checking only new URLs, and deploy:schedule installs the pg_cron schedule): build is
prisma migrate deploy && pnpm db:policies && pnpm deploy:catalog && next build --turbopack && pnpm deploy:schedule,
in that order, against whatever DATABASE_URL/DIRECT_URL that Vercel environment (production vs.
preview) has configured. Every step is idempotent, so this is safe to run on every build. A failure
in any step fails the build, so a broken migration cannot ship. Local pnpm db:migrate / pnpm db:policies above
are for authoring and testing a migration before it reaches that pipeline.
Deploy-time sync (N25):
pnpm deploy:catalog and pnpm deploy:schedule act only when VERCEL_ENV=production; on preview
and local builds they log one skip line and exit 0.catalog_syncs row.DATABASE_URL, DIRECT_URL, APP_URL, CRON_SECRET.pnpm db:schedule by hand after either.prisma/schema.prisma is the truth; migrations are generated, never hand-authored — except the
two CHECK constraints (N1/N2), which Prisma has no schema syntax for and which are added by
hand, once, to prisma/migrations/*_init/migration.sql. Table and column names are
@@map/@map'd to match lib/db/policies.sql exactly, so the RLS file never has to change
when the ORM does.
Create both storage buckets as private: resumes, exports. db:policies writes their
path-prefix policies; the buckets themselves are created in the dashboard once.
Use the native third-party integration, not the deprecated JWT-template path:
"role": "authenticated".auth.uid() is not used anywhere — it returns a UUID and Clerk subjects are strings. Every
policy reads public.clerk_user_id() instead.
Webhook: point Clerk at POST /api/webhooks/clerk (events user.created, user.updated,
user.deleted) and set CLERK_WEBHOOK_SIGNING_SECRET.
Light by design (CLAUDE.md §11): no continuous suite, no CI gating. One manual checklist per milestone, at the gate. These are the commands behind it.
| Command | What it is | When |
|---|---|---|
pnpm check:constraints | ★ Constraint smoke test — one bad insert per guard (N1, N2, RLS) | M1 gate, once |
pnpm check:fabrication | ★ Fabrication eval — 30 bullets vs postings demanding absent skills | M4 gate |
pnpm check:roundtrip | ★ DOCX round-trip — render, re-import, compare (bar: 95%) | M6 gate |
pnpm test | Every pure check (score, pre-strip, agents, quotas, lanes, push, jobs…) plus repo-shape rules. No DB, no keys | before every commit |
pnpm check:drill | Runs every DSA bank solution against its own tests — JavaScript in the QuickJS sandbox, Python via local python3 (F26). No DB, no keys | whenever the bank changes |
pnpm render:samples | Renders all eleven templates to .samples/. Open them | anytime |
pnpm check:links | Catalog link check, refreshes verified_at | manual full sweep (the daily cron re-checks due rows) |
pnpm tokens:calibrate | Measured p50/p95 tokens per purpose, for hand-recalibrating TOKEN_STAGES (F24) | after a prompt change, or quarterly |
The three ★ checks are the ones that survive the light-testing policy, because each catches a failure that would otherwise be expensive and silent.
check:fabrication needs EVAL_ANALYSIS_ID set to a real analysis you own — it writes
ai_runs rows like any other call. Its automated verdict catches mechanical fabrication;
read all 30 outputs by hand, because no regex sees "led" where the source said
"contributed to".
pnpm test (coverage) PASS all fixtures, including the hand-computed 61.11
pnpm check:roundtrip PASS 100% field recovery on all eleven templates
pnpm render:samples PASS PDFs render in 34–123 ms, full text layer, ATS High/High/Medium/Medium/Low/Low
pnpm build PASS clean; service-role client and DB adapter absent from every client chunk
pnpm check:constraints PASS 4/4 guards, against the live Supabase project — N1, N2, N10 all confirmed
pnpm seed:catalog PASS 123/129 courses seeded; 6 flagged unreachable (bot-blocking false
positives on Kaggle/Cloudflare/etc — re-check with pnpm check:links)
pnpm check:fabrication PASS 0/30 mechanical fabrications, live against OpenAI (gpt-4.1)
What a member touches and where each request lands (generated with gitdiagram):
The same system drawn by layer. Solid arrows are request-time calls; dotted arrows are
scheduled or webhook-driven. Nothing in lib/domain/ talks to I/O, and the model only ever
reaches the database through a Zod schema and the pipeline that validates it.
flowchart TB
member(["Member<br/>browser · PWA"])
subgraph edge["Edge"]
vercel["Vercel edge<br/>roleform.koustubh.org"]
cf["CloudFront<br/>files.koustubh.org"]
end
subgraph app["Next.js 15 App Router"]
pages["app/(app)/*<br/>onboarding · analyze · analysis/[id] tabs<br/>history · profile · jobs · admin"]
actions["app/actions/*<br/>Server Actions"]
stream["app/api/analyze/[id]<br/>streaming route"]
hooks["app/api/webhooks<br/>clerk · razorpay"]
cron["app/api/cron/*<br/>reminders · catalog<br/>Bearer CRON_SECRET (N24)"]
end
subgraph core["lib/ — server"]
pipeline["lib/services/pipeline<br/>run-analysis · stages"]
agents["lib/ai/agents · prompts · system-prompts<br/>runAgent + Zod schemas (N6) · lib/ai/openai"]
checkers["lib/ai/typesafe<br/>fabrication · answer claims · injection"]
learning["lib/services/learning<br/>bundles · build-plan · validate · refresh-catalog<br/>ONE model call (N12)"]
catalog["lib/catalog<br/>skills · courses · matcher (N8)"]
jobs["lib/services/jobs<br/>search + API adapters (N17–N19)"]
render["lib/render<br/>ats-rules · pdf · docx · zip"]
plans["lib/services/plans · promo · payments<br/>plan catalog · promos · razorpay"]
push["lib/services/push · mail<br/>dispatch · outbox · web-push · Resend"]
end
domain["lib/domain — PURE<br/>coverage · fabrication · ordering · diff<br/>binding · guardrails · entitlements"]
subgraph data["Supabase"]
pg[("Postgres via Prisma<br/>RLS on every user table (N10)<br/>NOT NULL evidence FKs (N1/N2)")]
storage[("Storage<br/>resumes · exports (private)")]
pgcron["pg_cron<br/>every 5 min · daily"]
end
subgraph ext["External services"]
clerk["Clerk<br/>auth · native Supabase integration"]
llm["GPT-5 writers<br/>Vercel AI SDK generateObject"]
jev["Jev checkers"]
rzp["Razorpay"]
boards["Job board APIs<br/>Greenhouse · Lever · Ashby · …"]
pushsvc["Web Push services"]
end
member --> vercel --> pages
member -->|signed export URLs| cf --> storage
pages --> actions
pages --> stream
member -.->|sign-in| clerk
stream --> pipeline
actions --> learning
actions --> jobs
actions --> render
actions --> plans
pipeline --> agents
pipeline --> domain
agents --> llm
agents --> checkers --> jev
learning --> catalog
learning --> agents
learning --> domain
jobs --> boards
jobs --> domain
render --> domain
plans --> rzp
pipeline --> pg
actions --> pg
actions --> storage
render --> storage
clerk -.->|user events| hooks
rzp -.->|captured payment| hooks
hooks --> pg
pgcron -.-> cron --> push
cron --> learning
push --> pg
push --> pushsvc -.-> member
lib/domain/ PURE. coverage · scoring · ordering · diff · fabrication guard
Imports nothing from db, ai, supabase or next.
lib/ai/ generateObject + Zod only. schemas/ IS the contract; prompts/ are docs.
lib/catalog/ skills canon + alias table · curated courses · deterministic matcher
lib/render/ ats-rules (the badge) · pdf/ · docx/ · zip · shared render model
lib/db/ index.ts (Prisma client) · policies.sql · queries/ (all scoped by subject)
prisma/ schema.prisma is the truth · migrations/ (in-repo, generated)
lib/services/pipeline/ the five stages, with per-tab degradation
app/actions/ Server Actions · app/api/ streaming + webhooks only
Four layers stand between the model and a fabricated claim, in order of how hard they are to talk around:
lib/domain/fabrication.ts — pure, then verbatim fallbacktailored_bullets.source_bullet_id NOT NULL ON DELETE RESTRICT (N1)Only the fourth cannot be argued with. That is why it exists.
exportAll logs its elapsed time so the trigger is measurable, not felt.