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.
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.
ProductivityTypeScript · CSSGitHub @batool-farihaOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Score your PRD 0-100 across 12 categories, with fixes that quote your own text
Taken from the repository README
Loading the full README.
Read the full 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