TreeMap
무료 오픈소스 디스크 사용량 시각화 도구로, 사각형 트리맵·중복 파일 탐색·디스크 가득 예측·정리 시 파일을 휴지통으로만 이동한다
PRD를 붙여넣거나 업로드하면 12개 항목에 대해 0‑100 점수를 제공하고, 직접 문구를 인용한 수정안을 제시, 무료·개인·계정 필요 없음
Paste or upload a PRD and get a 0-100 score across 12 categories, with fixes that quote your own words. Free, private, no account.
생산성TypeScript · CSSGitHub @batool-fariha온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Score your PRD 0-100 across 12 categories, with fixes that quote your own text
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Paste a PRD, get a score out of 100 and the exact sentences to fix. Free, no account, and your document never leaves your browser.
Try it: https://prd-doctor.vercel.app · Built with Next.js 16, TypeScript, Tailwind 4, shadcn/ui and PostHog.
PRD Doctor scores a product requirements document across 12 categories (problem, users, evidence, pain, scope, metrics, acceptance criteria, risks, edge cases, dependencies, prioritization, experiment design). For every weak category it says what is missing, why it matters, what to add, and one question to answer. Each fix quotes a sentence from your own PRD, or says "No mention found". It never writes your PRD and never makes anything up.
PRDs are the most reviewed and least measured document in product work. Feedback is slow and social: reviewers catch what they happen to care about, and gaps (no non-goals, no baseline for the metric, no rollback plan) surface at kickoff or after launch. There was no fast, private way to ask "is this ready for review?" before the meeting.
Who it is for: product managers who write PRDs weekly, plus founders and designers writing specs without a PM, and anyone learning to write one.
The bet: if you get a specific, quote-anchored critique in about 10 seconds, before sending the PRD out, you fix more gaps before review. Success looks like a high analysis_completed / analysis_started, repeat analyses of the same PRD with rising scores, and a healthy share_clicked rate per score_viewed.
Input
.md or .txt file. Files are read in your browser and never uploaded..doc, input under 40 words or over 60,000 characters, and code-like or repeated text.Results
[bracketed blanks].Iteration
+N since last time. Recent analyses are listed on the home page..md, or print and save as PDF.Sharing
/r/<18 characters>) that opens the score on any device. The link carries scores only, never your text.55 to 67, with the previous radar dashed underneath).Polish
Twelve categories, each scored 0 to 100, combined by weight. The weights sum to 100, so overall = Σ(score × weight / 100).
| Category | Weight | Category | Weight | |
|---|---|---|---|---|
| Problem clarity | 12 | User pain severity | 8 | |
| Success metrics | 11 | Risks | 7 | |
| Target user clarity | 10 | Edge cases | 6 | |
| Evidence | 10 | Prioritization | 6 | |
| Acceptance criteria | 10 | Experiment design | 6 | |
| Scope | 9 | Dependencies | 5 |
Each category is a rubric of three to five signals, each with a weight and a pattern (see RUBRICS in lib/analyzer.ts). For Success metrics, for example: a named KPI, a numeric target or baseline, a concrete metric such as conversion or retention, and a time frame. A category's score is the sum of the signals found. The live rubric is also shown in the app at /how-scoring-works, generated from the same code so the page cannot drift.
Status per category: strong 70 and above, ok 40 to 69, weak below 40. The top three weaknesses are ranked by points lost, (100 − score) × weight, so a missing success metric outranks a missing dependency list.
# Heading, numbered headings, **Bold**, Label: lines, or a plain standalone line like Risks, as in most Word and PDF files). A filled section with real content earns its category's headline signal. Front matter (Version, Status, Owner) is ignored.Risks: none, TBD, N/A or an empty heading are detected and capped at 15.The output is only ever (a) sentences copied from your PRD, (b) fixed rubric text, and (c) [bracketed placeholders]. Quote labels tell you what you are looking at: You wrote (a sentence that satisfied part of the rubric), Vague wording, Placeholder section, and Nearest text (the closest sentence to where the section would go). Quotes are distinct across categories. When nothing is relevant, the report says "No mention found in your PRD" instead of quoting something unrelated.
It checks structure and specifics, not whether the idea is good. A keyword engine detects that a PRD talks about risks, not that the risks are the right ones.
To keep it honest, the engine was calibrated against real PRDs I scored by hand first, then tuned until it landed close without changing the rule for any single document:
| PRD (real, confidential, not in this repo) | My score | Engine |
|---|---|---|
| A | 73 | 73 |
| B | 72 | 68 |
| C | 69 | 66 |
| D | 70 | 68 |
Mean absolute error is about 2 points and the engine has so far been at or below my score. Caveats: all four come from one author's well-structured template, so the zone least tested is weak and messy real-world PRDs. The regression ranges in scripts/score-check.mts also cover three fictional examples (about 3, 58 and 88) plus hand-written samples. If a score feels wrong to you, the in-app feedback prompt is how it gets better.
localStorage on your device only. "Clear history" wipes it. If storage is blocked, results still open for the session./r/<code> encodes the overall score and 12 category scores. Anyone opening it sees the score, radar and bars, never the document.lib/analytics.ts), so the text you type is never recorded. Six events are sent, with counts, scores and category names only: analysis_started, analysis_completed, share_clicked, score_viewed, score_feedback, example_loaded. Without NEXT_PUBLIC_POSTHOG_KEY, analytics are a no-op.Requires Node 20 or newer for the app, and Node 22.6 or newer for the check and fuzz scripts (they use --experimental-strip-types).
npm install
cp .env.example .env.local # optional: add NEXT_PUBLIC_POSTHOG_KEY
npm run dev # http://localhost:3000
| Script | What it does |
|---|---|
npm run dev | Dev server |
npm run build / npm start | Production build and server |
npm run lint | ESLint |
npm run typecheck | TypeScript, no emit |
npm run check | Scoring regression check (see below) |
npm run paste | Checks the rich-text paste converter on Google Docs, Notion and Confluence-style HTML |
npm run fuzz | Hostile-input check |
npm test | check, paste and fuzz together (what CI runs) |
Environment variables (both optional):
| Variable | Purpose |
|---|---|
NEXT_PUBLIC_POSTHOG_KEY | PostHog project key. Public by design. Leave empty to disable analytics. |
NEXT_PUBLIC_POSTHOG_HOST | Defaults to https://us.i.posthog.com. |
Deploying. It deploys to Vercel with no configuration (Hobby tier is enough; share cards are CDN-cached so a traffic spike stays cheap). Add the two variables above in the project settings if you want analytics. It also runs anywhere Node does. The site address used in share cards and metadata lives in lib/site.ts; change it if you fork the project.
Run after any change to lib/analyzer.ts:
npm run check # regression ranges, all must pass
node --experimental-strip-types scripts/score-check.mts path/to/prd.md
VERBOSE=1 node --experimental-strip-types scripts/score-check.mts path/to/prd.md
npm run fuzz
After a change to lib/paste.ts, run npm run paste. It feeds the converter HTML shaped like Google Docs, Notion and Confluence clipboards and includes regression cases for two bugs found by hand (lost soft line breaks, a list in a table cell pasted twice).
score-check runs the fictional examples and hand-written samples against the range a careful reviewer would accept. Pass a file path to see a per-category breakdown of any PRD, so confidential documents never need to enter the repo. VERBOSE=1 shows which checks fired.<name>.expect-<score>.md into scripts/private/ (git-ignored). score-check then verifies each is within ±5 of the score you gave it.fuzz runs 20 hostile inputs (empty, 60,000 characters, nested markdown, RTL and emoji text, null bytes, pathological repeats): no crashes, scores stay within 0 to 100, and the slowest case takes well under 100 ms.Audited with axe-core (a dev dependency) on the home page, a result page with every fix open, the shared-link page, How scoring works and the 404, in light and dark mode: no violations. The audit needs a real browser, so it is not part of npm test. To repeat it, follow the steps at the top of scripts/axe-snippet.js. Beyond axe: visible keyboard focus, one h1 per page, labelled icon buttons, and reduced-motion support.
app/page.tsx editor → analyzePRD() in the browser → localStorage → /result/[id]
app/result/[id]/page.tsx server shell; generateMetadata() sets the preview image
app/r/[code]/page.tsx public score page from a short code
app/api/og/route.tsx 1200×630 share card PNG (next/og), also the "Download card" file
app/how-scoring-works/ rubric page generated from the live code
lib/analyzer.ts rubrics, section parsing, scoring, quotes, rewrite, share payload
lib/examples.ts the three fictional example PRDs
lib/storage.ts localStorage: results, history, draft, addressed fixes, feedback
lib/files.ts PDF / Word / text reading, fully client-side
lib/paste.ts rich-text paste to markdown-ish text
lib/validate.ts input checks (length, junk, repetition)
lib/report.ts Markdown report and per-fix export
lib/analytics.ts PostHog wrapper (no-op without a key)
lib/site.ts site name, URL, author links
components/result-view.tsx hero, radar, bars, fixes, rewrite, share controls
components/ diagnosis overlay, example picker, feedback, footer, theme toggle, charts
scripts/ score-check.mts and fuzz.mts
Key decisions:
mammoth (Word) and unpdf (PDF) are only fetched when someone uploads that file type.localStorage. Clearing the browser loses them. Fine for an anonymous tool.This is a finished v1, lightly maintained. Ideas, roughly in order, not promises:
Issues and pull requests are welcome, especially a PRD where the score felt wrong (remove anything confidential first). Run npm run lint, npm run typecheck and npm test before opening a PR; GitHub Actions runs the same checks plus a production build. Dependabot opens weekly pull requests for dependency updates.
MIT © Fariha Batool.
Designed and built by Fariha Batool. Source: https://github.com/batool-fariha/prd-doctor