$ cd ~/projects/ai-desloper
Desloper
Desloper scores how generic an AI-written landing page is against eight principles, with deterministic detectors plus a model judge, then hands you a fix prompt built from the findings you keep.
- web app
- ai
- dev tools

Desloper
Most landing pages written with AI look like each other: a purple gradient, a headline that starts with "Unlock", three feature cards with emoji, six different buttons, and nobody on the page.
Desloper reads your landing page, scores how generic it is, and shows you every finding. Then it hands you a prompt to paste into your own AI coding tool, so the fix happens in your codebase, on your stack.
91 F "🚀 The AI-Powered Platform to Supercharge Your Workflow and Unlock Your Team's Full Potential"
CTA 1.1 screens down · 20 emoji, 4 of them rockets · 12.7 screens tall on mobile
0 A the hand-made fixture
Both are test fixtures in lib/analyze/__fixtures__. The test suite checks that the sloppy page scores above 65 and the hand-made page below 35.
How it works
- Read. Paste a URL. A headless browser renders the page at 1440px and 390px, measures layout shift and paint time, and freezes a script-free snapshot. The status feed shows what it finds as it finds it, for example "Page is 14.5 screens tall on mobile", "18 different button labels" or "Fonts: Inter, Inter, and Inter".
- Score. Deterministic detectors and a model judge both score the page against eight principles. The detectors count 60% and the judge 40%. Emoji, em dashes and other tics add a separate penalty. 0 is clean and 100 is slop. If the judge is unavailable, the detectors score the page alone and the results still show.
- Review. The results list every finding under the principle it breaks, with the quoted evidence and a crop of the screenshot. Each finding is a toggle, and all of them start on. A five-second test and a list of what is already distinctive about the page sit alongside.
- Prompt. The next screen is a Markdown prompt built from the findings you kept, with no model call. It names the page, the product facts and distinctive parts to keep, each finding with its evidence and the principle behind it, and a set of hard constraints: headline and primary action inside the first 390px screen, reserved space for every image and video, a secondary contact path, a mobile length at most 60% of today's, and no emoji or generic marketing words. It tells your tool to keep your stack and not invent claims. Copy it or download it as a
.mdfile. - Make it yours. Beside the prompt, up to nine optional questions: why you built it, the pain in a customer's words, who it is for, the one action you want, and what you read, watch, play and do on weekends. Answers go into the prompt as you type, as the source for the story and the voice. One button skips the lot and builds the prompt from the findings alone.
The doctrine
Scoring and the fix prompt both run on the same eight principles, written out in lib/doctrine.ts:
- Name the pain in the first screen, in the customer's words.
- Show the product, don't decorate around it.
- One reader, one job, one primary action.
- Specificity is the whole game.
- A human made this.
- Every section earns its scroll.
- Identity through restraint.
- Speed and stability are design.
If you disagree with how a page is judged, change that file. The judge reads its instructions from it and the fix prompt quotes it, so the scoring and the instructions change together.
Stack
- Next.js 16 (App Router) on Vercel. Every API route runs on Node.
- AI SDK 7 through Vercel AI Gateway, for the judge only. The model names live in
lib/ai.ts. - Playwright for capture:
@sparticuz/chromiumon Vercel, regular Chromium locally. Every request the browser makes goes through a small egress proxy that refuses private and loopback addresses, including after redirects and DNS changes. - Supabase for Postgres, Auth and Storage. Row-level security is on for every table. Anonymous reports carry a claim token, so you can save one to your account later.
- Motion for the transitions and Vitest for the tests.
Run it locally
yarn
npx playwright install chromium
cp .env.example .env.local # add AI_GATEWAY_API_KEY
yarn dev
AI_GATEWAY_API_KEY turns on the model judge. Without it, the detectors score the page alone. Without Supabase settings, reports are kept in memory and accounts are turned off.
To persist reports, create a Supabase project, fill in the Supabase variables in .env.local, then:
npx supabase link --project-ref <ref>
npx supabase db push --linked
Command line and agent skill
The same capture, detectors, score and fix prompt run from a terminal, against any URL, localhost included:
bin/desloper analyze http://localhost:3000 # screenshots, findings, a detector-only score
bin/desloper finish <run-dir> --judgement j.json # blend in a judgement, write fix-prompt.md
bin/desloper doctrine # the eight principles
bin/desloper analyze readme # the README in this directory
A README is scored on six of the principles (no folds, buttons or fonts), plus four checks only Markdown can answer: no example, no install path, a badge wall and a template outline. Its fix prompt edits the README instead of a page.
--judge on analyze runs the model judge when AI_GATEWAY_API_KEY is set. Without it, a coding agent can write the judgement itself: skills/desloper/SKILL.md walks Claude Code through capturing the page, judging it against the doctrine, and applying the fix prompt in whatever repo it is working in. Install it for every repo with:
ln -s "$PWD/skills/desloper" ~/.claude/skills/desloper
The command line skips the egress proxy so it can read your own dev server. Keep it on your machine; the web app is the one meant for strangers' URLs.
Checks
yarn test # detectors, scoring, the fix prompt, the egress guard, persistence
yarn typecheck
yarn lint
CAPTURE_E2E=1 yarn test # also drives a real browser
Layout
app/page.tsx the whole flow, one staged screen
app/r/[id] a saved report, reopened on its results
app/api/analyze capture → detectors → judge, streamed as server-sent events
app/api/interview saves the optional answers for the report's author
lib/analyze/ capture, snapshot, egress guard, detectors, judge, score
lib/fix-prompt.ts builds the fix prompt, deterministically
lib/generate/ interview questions, request schemas
lib/doctrine.ts what a good page is
cli/desloper.ts the command line (bin/desloper runs it from any directory)
skills/desloper/ the Claude Code skill that drives it
supabase/migrations/ schema, row-level security, storage bucket
Known limits
- Some sites block headless browsers and return 403. Desloper reports that rather than guessing.
- The built-in rate limit is held in memory per instance. A Vercel Firewall rule is still needed for a real per-IP cap in production.
more projectsls ~/projects
~/mark85
Iron Man suit firmware: four limb IMUs drive synthesized stereo servo whir and repulsor charge-up.
~/claude-tts
Claude Code narrates its work out loud with offline neural TTS. Piper + FFmpeg, driven by hooks.
~/claude-usage-widget
Your Claude Code limits as Apple-Watch-style activity rings, with a forecast of when you'll hit them.
~/mini-kitchen
Toddler play kitchen with a sink that actually runs. CNC oak plywood, 12 V pump, Python-generated cut sheets.
~/speedster
A focused, dark-mode Rubik's cube timer for iOS: scrambles, rolling averages and progress charts.
~/age-of-potatoes
The source behind ageofpotatoes.com, golden-file tests for the deterministic sim included.