content-grade 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,198 @@
1
+ # Contributing to ContentGrade
2
+
3
+ Thanks for wanting to contribute. ContentGrade is a CLI + web dashboard for AI-powered content scoring. It runs entirely on local Claude CLI — no API keys, no external services (unless you add Stripe).
4
+
5
+ ---
6
+
7
+ ## Prerequisites
8
+
9
+ - **Node.js 18+**
10
+ - **pnpm** (`npm install -g pnpm`)
11
+ - **Claude CLI** — installed and logged in ([claude.ai/code](https://claude.ai/code))
12
+ - Verify: `claude -p "say hi"`
13
+
14
+ ---
15
+
16
+ ## Local development setup
17
+
18
+ ```bash
19
+ git clone https://github.com/StanislavBG/Content-Grade
20
+ cd Content-Grade
21
+ pnpm install
22
+ pnpm dev
23
+ ```
24
+
25
+ This starts two processes concurrently:
26
+ - **Client** (Vite) at [http://localhost:3000](http://localhost:3000) with hot reload
27
+ - **Server** (tsx watch) at [http://localhost:4000](http://localhost:4000) with hot reload
28
+
29
+ The client proxies API requests to the server automatically.
30
+
31
+ ---
32
+
33
+ ## Project structure
34
+
35
+ ```
36
+ bin/
37
+ content-grade.js CLI entry point — all CLI commands live here
38
+ server/
39
+ app.ts Fastify app factory (used by server and tests)
40
+ index.ts Production server entry (binds port)
41
+ claude.ts Claude CLI wrapper (server-side)
42
+ db.ts SQLite setup — usage tracking, stripe subscriptions
43
+ routes/
44
+ demos.ts API routes for all 6 web dashboard tools
45
+ stripe.ts Stripe checkout, webhooks, subscription management
46
+ services/
47
+ claude.ts askClaude() helper for route handlers
48
+ stripe.ts Stripe helpers — subscription checks, customer management
49
+ src/
50
+ App.tsx React app router
51
+ main.tsx React entry point
52
+ views/
53
+ HeadlineGraderView.tsx
54
+ PageRoastView.tsx
55
+ AdScorerView.tsx
56
+ ThreadGraderView.tsx
57
+ EmailForgeView.tsx
58
+ AudienceDecoderView.tsx
59
+ ContentGradeShared.tsx Shared UI components
60
+ data/
61
+ api.ts API client for the web dashboard
62
+ tests/
63
+ unit/ Unit tests (no Claude required)
64
+ integration/ Integration tests (spins up Fastify)
65
+ helpers/
66
+ db.ts Test database helpers
67
+ ```
68
+
69
+ ---
70
+
71
+ ## Running tests
72
+
73
+ ```bash
74
+ pnpm test # run all tests once
75
+ pnpm test:watch # watch mode — reruns on file changes
76
+ pnpm test:coverage # full coverage report
77
+ ```
78
+
79
+ Tests live in `tests/unit/` and `tests/integration/`. Integration tests spin up a real Fastify server but mock Claude responses — they don't require a live Claude CLI.
80
+
81
+ Unit tests cover:
82
+ - `tests/unit/validation.test.ts` — input validation
83
+ - `tests/unit/cli-utils.test.ts` — CLI helper functions
84
+ - `tests/unit/rate-limit.test.ts` — rate limit logic
85
+ - `tests/unit/edge-cases.test.ts` — edge case handling
86
+ - `tests/unit/quality-hardening.test.ts` — error path hardening
87
+
88
+ ---
89
+
90
+ ## TypeScript
91
+
92
+ ```bash
93
+ pnpm typecheck # run tsc --noEmit — check types without building
94
+ ```
95
+
96
+ The project has two TypeScript configs:
97
+ - `tsconfig.json` — client (Vite, React, ESNext)
98
+ - `tsconfig.server.json` — server (Node.js ESM, outputs to `dist-server/`)
99
+
100
+ Both must pass before merging.
101
+
102
+ ---
103
+
104
+ ## Building for production
105
+
106
+ ```bash
107
+ pnpm build # builds client (dist/) and server (dist-server/)
108
+ pnpm start # runs the production server
109
+ ```
110
+
111
+ After building, test the full CLI flow:
112
+
113
+ ```bash
114
+ node bin/content-grade.js init
115
+ node bin/content-grade.js demo
116
+ node bin/content-grade.js start
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Making changes
122
+
123
+ ### Adding or modifying CLI commands
124
+
125
+ All CLI logic lives in `bin/content-grade.js`. The router is the `switch (cmd)` block at the bottom.
126
+
127
+ Pattern for a new command:
128
+ 1. Add a `cmdFoo(args)` async function
129
+ 2. Add a `case 'foo':` branch in the switch
130
+ 3. Follow the existing error handling pattern: `blank()`, `fail()`, `process.exit(1)`
131
+ 4. Use `checkClaude()` before any `askClaude()` call
132
+
133
+ ### Adding a new web dashboard tool
134
+
135
+ 1. Create `src/views/FooView.tsx` — follow the pattern of existing views
136
+ 2. Add a route in `App.tsx`
137
+ 3. Add an API endpoint in `server/routes/demos.ts`
138
+ 4. Add the endpoint name to `FREE_TIER_LIMIT` tracking in `demos.ts`
139
+ 5. Add to the tool list in `bin/content-grade.js` `cmdStart()` output
140
+
141
+ ### Modifying Claude prompts
142
+
143
+ Prompts are inline in `bin/content-grade.js` (CLI) and `server/routes/demos.ts` (web). Both require JSON-only responses — the parser handles both clean JSON and JSON embedded in markdown fences.
144
+
145
+ The scoring calibration note at the bottom of each prompt is load-bearing: without it, Claude uses a compressed range and most content scores 50-70. Keep it.
146
+
147
+ ---
148
+
149
+ ## Claude model selection
150
+
151
+ | Use case | Model | Why |
152
+ |----------|-------|-----|
153
+ | `analyze` command | `claude-sonnet-4-6` | Richer analysis, better calibration |
154
+ | `headline` command | `claude-haiku-4-5-20251001` | Fast, good enough for structured scoring |
155
+ | `init` smoke test | `claude-haiku-4-5-20251001` | Just needs a JSON ping |
156
+ | Web dashboard tools | `claude-haiku-4-5-20251001` | Server-side, latency-sensitive |
157
+
158
+ ---
159
+
160
+ ## Rate limiting
161
+
162
+ The web dashboard uses SQLite-backed IP rate limiting:
163
+ - Free tier: 3 analyses/day per tool per IP (IP is SHA-256 hashed, never stored raw)
164
+ - Pro tier: 100 analyses/day — verified against Stripe API with a 5-minute cache
165
+ - AudienceDecoder: one-time purchase model (different Stripe Price ID)
166
+
167
+ The CLI (`analyze`, `headline`) has no rate limiting — it calls Claude directly from your machine.
168
+
169
+ ---
170
+
171
+ ## Stripe setup (optional)
172
+
173
+ The app works without Stripe — upgrade prompts show "Coming Soon" instead of a checkout button.
174
+
175
+ To enable payments:
176
+ 1. Copy `.env.example` to `.env`
177
+ 2. Add your Stripe keys
178
+ 3. Create products in Stripe dashboard — get the Price IDs
179
+ 4. Add `STRIPE_PRICE_CONTENTGRADE_PRO` and `STRIPE_PRICE_AUDIENCEDECODER`
180
+ 5. Set up a webhook pointing to `/api/stripe/webhook`
181
+
182
+ ---
183
+
184
+ ## Pull request checklist
185
+
186
+ - [ ] `pnpm typecheck` passes (zero TypeScript errors)
187
+ - [ ] `pnpm test` passes (all tests green)
188
+ - [ ] CLI smoke test passes: `node bin/content-grade.js demo`
189
+ - [ ] No hardcoded API keys or credentials
190
+ - [ ] Error paths follow the existing pattern (`blank()`, `fail()`, `process.exit(1)`)
191
+ - [ ] New Claude prompts include the scoring calibration note
192
+ - [ ] PR description explains what changed and why
193
+
194
+ ---
195
+
196
+ ## Questions
197
+
198
+ Open an issue or start a GitHub Discussion. Include your Node.js version, OS, and the output of `npx content-grade init` if it's a setup issue.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 StanislavBG
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,348 @@
1
+ # ContentGrade
2
+
3
+ > AI-powered content quality scoring for developers and content teams. Score any blog post, landing page, ad copy, or email — in under 30 seconds. No API keys. No accounts. Runs on your local Claude CLI.
4
+
5
+ [![npm](https://img.shields.io/npm/v/content-grade.svg)](https://www.npmjs.com/package/content-grade)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+ [![Node.js 18+](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org)
8
+ [![Requires Claude CLI](https://img.shields.io/badge/requires-Claude%20CLI-orange)](https://claude.ai/code)
9
+
10
+ ---
11
+
12
+ ## 60-second quickstart
13
+
14
+ ```bash
15
+ # 1. Verify Claude CLI is installed and logged in
16
+ claude -p "say hi"
17
+
18
+ # 2. Run an instant demo — no file needed
19
+ npx content-grade
20
+
21
+ # 3. Analyze your own content
22
+ npx content-grade ./my-post.md
23
+
24
+ # 4. Grade a single headline
25
+ npx content-grade headline "Why Most Startups Fail at Month 18"
26
+ ```
27
+
28
+ **One requirement:** [Claude CLI](https://claude.ai/code) must be installed and logged in. That's it — no API keys, no accounts, no data leaves your machine.
29
+
30
+ ---
31
+
32
+ ## What you get
33
+
34
+ ```
35
+ ╔═══════════════════════════════════════╗
36
+ ║ ContentGrade · Content Analysis ║
37
+ ╚═══════════════════════════════════════╝
38
+
39
+ OVERALL SCORE 72/100 B+ blog post
40
+ ████████████████████████░░░░░░░░░░░░░░░░
41
+
42
+ HEADLINE SCORE ████████████░░░░░░░░ 61/100
43
+ "Why Most Startups Fail"
44
+ ↳ Too vague — the reader doesn't know if this applies to them.
45
+
46
+ ──────────────────────────────────────────────────────────
47
+ DIMENSION BREAKDOWN
48
+
49
+ Clarity ████████████████████ 80/100
50
+ ↳ Well-organized with clear section breaks.
51
+
52
+ Engagement ████████████░░░░░░░░ 60/100
53
+ ↳ Opens with a statistic but drops momentum in paragraph 3.
54
+
55
+ Structure ████████████████░░░░ 72/100
56
+ ↳ Good use of subheadings but the conclusion is thin.
57
+
58
+ Value Delivery █████████████░░░░░░░ 65/100
59
+ ↳ Core advice is solid but needs a concrete takeaway.
60
+
61
+ VERDICT
62
+ Strong structure undermined by a weak headline — fix that first.
63
+
64
+ TOP IMPROVEMENTS
65
+ ● Make the headline specific: who fails, why, and what the fix is
66
+ Fix: "Why 90% of SaaS Startups Fail at Month 18 (and How to Be the 10%)"
67
+
68
+ ● Add one data point to support claims in paragraph 2
69
+ Fix: Cite a specific study — "CB Insights found..." beats "many startups..."
70
+
71
+ HEADLINE REWRITES
72
+ 1. Why 90% of SaaS Startups Fail at Month 18 (and How to Be the 10%)
73
+ 2. The Month 18 Startup Trap: What Kills Growth-Stage Companies
74
+
75
+ Free analysis complete. Pro unlocks:
76
+ · Competitor headline comparison
77
+ · Landing page URL audit (full CRO analysis)
78
+ · Ad copy scoring (Google, Meta, LinkedIn)
79
+ · 100 analyses/day vs 3 free
80
+ ```
81
+
82
+ ---
83
+
84
+ ## Commands
85
+
86
+ | Command | What it does |
87
+ |---------|-------------|
88
+ | *(no args)* | Instant demo on built-in sample content |
89
+ | `<file>` | Analyze a file directly — `npx content-grade ./post.md` |
90
+ | `.` or `<dir>` | Scan a directory, find and analyze the best content file |
91
+ | `demo` | Same as no args |
92
+ | `analyze <file>` | Full content audit: score, grade, dimensions, improvements |
93
+ | `check <file>` | Alias for `analyze` |
94
+ | `analyse <file>` | Alias for `analyze` (British spelling) |
95
+ | `headline "<text>"` | Grade a headline on 4 copywriting frameworks |
96
+ | `grade "<text>"` | Alias for `headline` |
97
+ | `init` | First-run setup: verify Claude CLI, run smoke test |
98
+ | `start` | Launch the full web dashboard (6 tools) |
99
+ | `help` | Full usage and examples |
100
+
101
+ ---
102
+
103
+ ## The 6 web dashboard tools
104
+
105
+ Launch with `content-grade start` — opens at [http://localhost:4000](http://localhost:4000):
106
+
107
+ | Tool | Route | What it does |
108
+ |------|-------|-------------|
109
+ | **HeadlineGrader** | `/headline` | A/B comparison, scores across 4 frameworks, suggests rewrites |
110
+ | **PageRoast** | `/page-roast` | Landing page URL audit: hero, social proof, clarity, CRO |
111
+ | **AdScorer** | `/ad-scorer` | Google/Meta/LinkedIn ad copy scoring |
112
+ | **ThreadGrader** | `/thread` | Twitter/X thread hook, structure, and shareability score |
113
+ | **EmailForge** | `/email-forge` | Subject line + body copy for click-through optimization |
114
+ | **AudienceDecoder** | `/audience` | Twitter handle → audience archetypes and content patterns |
115
+
116
+ Free tier: **3 analyses/day per tool**. Pro ($9/mo): **100 analyses/day** + all tools.
117
+
118
+ ---
119
+
120
+ ## Requirements
121
+
122
+ - **Node.js 18+**
123
+ - **Claude CLI** — install from [claude.ai/code](https://claude.ai/code), then run `claude login`
124
+
125
+ Verify Claude is working:
126
+
127
+ ```bash
128
+ claude -p "say hi"
129
+ ```
130
+
131
+ If this fails, run `npx content-grade init` for step-by-step diagnostics.
132
+
133
+ ---
134
+
135
+ ## CLI reference
136
+
137
+ ### `analyze` / `check`
138
+
139
+ ```bash
140
+ content-grade analyze <file>
141
+ content-grade check <file>
142
+ ```
143
+
144
+ Analyzes written content from any plain-text file. Detects content type automatically (blog, landing page, email, ad copy, social thread) and calibrates scoring accordingly.
145
+
146
+ **File limits:**
147
+ - Maximum size: 500 KB
148
+ - Minimum length: 20 characters
149
+ - Binary files are rejected — use `.md`, `.txt`, `.mdx`, or any plain-text format
150
+ - Files over 6,000 characters are truncated for analysis (the full file is still read)
151
+
152
+ **Output sections:**
153
+ 1. Overall score (0–100) with letter grade (A+ to F)
154
+ 2. Headline score with 1-2 sentence feedback
155
+ 3. Dimension breakdown — Clarity, Engagement, Structure, Value Delivery
156
+ 4. One-line verdict
157
+ 5. Strengths list
158
+ 6. Top improvements with specific, actionable fixes
159
+ 7. 2 headline rewrite suggestions
160
+
161
+ ```bash
162
+ # Examples
163
+ content-grade analyze ./blog-post.md
164
+ content-grade check ./email-draft.txt
165
+ content-grade analyze ~/landing-page-copy.md
166
+ ```
167
+
168
+ ---
169
+
170
+ ### `headline` / `grade`
171
+
172
+ ```bash
173
+ content-grade headline "<text>"
174
+ content-grade grade "<text>"
175
+ ```
176
+
177
+ Grades a single headline on 4 direct-response copywriting frameworks:
178
+
179
+ | Framework | Max points | What it checks |
180
+ |-----------|-----------|----------------|
181
+ | Rule of One | 30 | Single focused idea, one reader, one promise |
182
+ | Value Equation | 30 | Benefit clarity, specificity, reader desire |
183
+ | Readability | 20 | Length, word choice, scan-ability |
184
+ | Proof/Promise | 20 | Credibility signals, specificity, claims |
185
+
186
+ Output: overall score, per-framework breakdown with notes, 2 stronger rewrites.
187
+
188
+ ```bash
189
+ content-grade headline "How I 10x'd My Conversion Rate in 30 Days"
190
+ content-grade headline "The $0 Marketing Strategy That Got Us 10,000 Users"
191
+ ```
192
+
193
+ ---
194
+
195
+ ### `init` / `setup`
196
+
197
+ ```bash
198
+ content-grade init
199
+ ```
200
+
201
+ Three-step diagnostic:
202
+ 1. Checks Claude CLI is on `PATH` (or `CLAUDE_PATH`)
203
+ 2. Runs a live smoke test against Claude
204
+ 3. Checks whether the production web dashboard build exists
205
+
206
+ Use this when something isn't working — it tells you exactly what to fix.
207
+
208
+ ---
209
+
210
+ ### `start` / `serve`
211
+
212
+ ```bash
213
+ content-grade start
214
+ ```
215
+
216
+ Starts the production web server at [http://localhost:4000](http://localhost:4000) and opens your browser. Requires a production build (run `npm run build` first if self-hosting).
217
+
218
+ **Port:** controlled by `PORT` environment variable (default: 4000).
219
+
220
+ ---
221
+
222
+ ### `demo`
223
+
224
+ ```bash
225
+ content-grade demo
226
+ # or just:
227
+ npx content-grade
228
+ ```
229
+
230
+ Runs a full analysis on built-in sample content so you see exactly what ContentGrade does before analyzing your own work.
231
+
232
+ ---
233
+
234
+ ### Directory scan
235
+
236
+ ```bash
237
+ content-grade .
238
+ content-grade ./posts
239
+ content-grade /path/to/content
240
+ ```
241
+
242
+ Scans up to 2 directory levels deep for `.md`, `.txt`, and `.mdx` files. Picks the best candidate (prefers files with names like `post`, `article`, `blog`, `draft`, `copy` over `README.md`; larger files score higher). Then runs `analyze` on it.
243
+
244
+ ---
245
+
246
+ ## Configuration
247
+
248
+ All configuration is through environment variables — no config file needed.
249
+
250
+ | Variable | Default | Description |
251
+ |----------|---------|-------------|
252
+ | `PORT` | `4000` | Web dashboard server port |
253
+ | `PUBLIC_URL` | `http://localhost:4000` | Base URL for the server |
254
+ | `CLAUDE_PATH` | `claude` | Path to Claude CLI binary if not on `PATH` |
255
+ | `STRIPE_SECRET_KEY` | *(empty)* | Stripe secret key — leave empty to show "Coming Soon" on upgrade prompts |
256
+ | `STRIPE_PRICE_CONTENTGRADE_PRO` | *(empty)* | Stripe Price ID for Pro subscription |
257
+ | `STRIPE_PRICE_AUDIENCEDECODER` | *(empty)* | Stripe Price ID for AudienceDecoder one-time purchase |
258
+ | `STRIPE_WEBHOOK_SECRET` | *(empty)* | Stripe webhook signing secret |
259
+ | `VITE_API_URL` | `/api` | Vite dev server API proxy (development only) |
260
+
261
+ Copy `.env.example` to `.env` and fill in what you need:
262
+
263
+ ```bash
264
+ cp .env.example .env
265
+ ```
266
+
267
+ Stripe variables are entirely optional — all tools work without them; upgrade prompts show "Coming Soon" instead of a checkout button.
268
+
269
+ ---
270
+
271
+ ## Self-hosting / Development
272
+
273
+ ```bash
274
+ git clone https://github.com/StanislavBG/Content-Grade
275
+ cd Content-Grade
276
+ npm install
277
+ npm run dev # hot reload: server at :4000, client at :3000
278
+ ```
279
+
280
+ To build for production:
281
+
282
+ ```bash
283
+ npm run build # builds client to dist/ and server to dist-server/
284
+ npm start # runs the production server
285
+ ```
286
+
287
+ **Project layout:**
288
+
289
+ ```
290
+ bin/ CLI entry point (content-grade.js)
291
+ docs/ REST API reference (api.md)
292
+ server/ Fastify API server
293
+ routes/ API route handlers (demos, stripe)
294
+ services/ Claude integration, Stripe helpers
295
+ db.ts SQLite setup (usage tracking, subscriptions)
296
+ src/ React web dashboard
297
+ views/ 6 tool views (HeadlineGrader, PageRoast, etc.)
298
+ tests/
299
+ unit/ Unit tests
300
+ integration/ Server integration tests
301
+ ```
302
+
303
+ **REST API:** The web dashboard exposes a full REST API at `http://localhost:4000`. See [`docs/api.md`](./docs/api.md) for the complete reference — every endpoint, request shape, response schema, and cURL examples.
304
+
305
+ **Run tests:**
306
+
307
+ ```bash
308
+ npm test # run all tests
309
+ npm run test:watch # watch mode
310
+ npm run test:coverage # coverage report
311
+ ```
312
+
313
+ ---
314
+
315
+ ## Pricing
316
+
317
+ | | Free | Pro |
318
+ |-|------|-----|
319
+ | Price | Free forever | $9/month |
320
+ | Analyses/day (CLI) | Unlimited | Unlimited |
321
+ | Analyses/day (web dashboard, per tool) | 3 | 100 |
322
+ | HeadlineGrader (single grade) | ✓ | ✓ |
323
+ | HeadlineGrader (A/B comparison) | — | ✓ |
324
+ | PageRoast (URL audit) | — | ✓ |
325
+ | AdScorer | — | ✓ |
326
+ | ThreadGrader | — | ✓ |
327
+ | EmailForge | — | ✓ |
328
+ | AudienceDecoder | — | One-time purchase |
329
+
330
+ ---
331
+
332
+ ## How it works
333
+
334
+ ContentGrade uses **your local Claude CLI** — the same binary you use for `claude -p` commands. When you run `analyze`, it:
335
+
336
+ 1. Reads your file and detects content type (blog, email, ad, landing page, social)
337
+ 2. Calls `claude -p --no-session-persistence --model claude-sonnet-4-6` with a structured scoring prompt
338
+ 3. Parses the JSON response and renders the scored output in your terminal
339
+
340
+ No data is sent to any external service. No account required. Your content stays on your machine.
341
+
342
+ The web dashboard works the same way — every tool call goes through `claude -p` running locally on your server.
343
+
344
+ ---
345
+
346
+ ## License
347
+
348
+ MIT