Limen helps teams decide whether a landing page is actually ready for launch-day or paid traffic — before weak messaging, low trust, or poor CTA clarity waste the moment.
Quickstart · What it does · How it works · Capabilities · Local development
Should this page launch for this audience and this traffic source right now?
That is the entire reason Limen exists.
A landing page can look polished and still fail the moment real traffic hits it.
Typical launch mistakes are simple, expensive, and easy to miss:
- the headline is too vague for cold traffic
- the CTA asks for commitment too early
- trust proof appears too late
- metadata is weak or missing
- the page is parseable, but not persuasive
Most tools catch isolated issues.
Limen is built to make a launch decision.
Limen takes a launch brief and a public landing page URL, then produces a launch-oriented review based on captured evidence.
- target audience
- traffic channel
- desired action
- offer
- objections
- competitors
- brand voice
- HTML snapshot
- rendered screenshot via Playwright
- page title and metadata
- hero and heading structure
- CTA-like actions
- trust-related signals
- viewport and page capture metadata
- launch verdict
- confidence level
- launch summary
- top reasons
- top fixes
- evidence-linked findings
- persona replay
- rewrite suggestions
- extracted signals explorer
- screenshot and HTML artifact previews
flowchart TD
A[Create launch run] --> B[Submit launch brief]
B --> C[Persist AuditRun]
C --> D[Queue worker job]
D --> E[Validate and normalize URL]
E --> F[Fetch HTML]
F --> G[Capture screenshot]
G --> H[Persist artifacts]
H --> I[Extract signals]
I --> J[Generate findings]
J --> K[Generate verdict]
K --> L[Generate persona replay]
L --> M[Generate rewrite suggestions]
M --> N[Synthesize launch board]
N --> O[Render run results UI]
Brief → Evidence → Findings → Verdict → Persona view → Rewrites
Limen is intentionally built as a decision pipeline, not a generic scanner.
- Verdict — should this page launch?
- Confidence — how strong is the current evidence?
- Top reasons — why Limen reached the verdict
- Top fixes — what to change first
- HTML snapshot
- rendered screenshot
- extracted signals
- evidence-linked findings
- persona replay
- rewrite suggestions
| Area | Current state | Notes |
|---|---|---|
| Launch brief intake | ✅ Working | Audience, channel, offer, objections, and more |
| Queue-backed execution | ✅ Working | BullMQ + Redis |
| HTML fetch | ✅ Working | URL normalization + fetch pipeline |
| Screenshot capture | ✅ Working | Playwright rendered evidence |
| Artifact persistence | ✅ Working | HTML + screenshot artifacts |
| Extracted signals | ✅ Working | H1, metadata, CTA candidates, trust signals, hero density |
| Findings generation | ✅ Working | Rule-based heuristics with evidence refs |
| Verdict generation | ✅ Working | LLM report when available; deterministic fallback produces a partial result |
| Launch summary | ✅ Working | Summary, top reasons, top fixes |
| Persona replay | ✅ Working | Primary + skeptical cold visitor |
| Rewrite suggestions | ✅ Working | Hero, support line, CTA, trust section |
| Artifact previews | ✅ Working | Screenshot + HTML snapshot in UI |
| Extracted signals UI | ✅ Working | Transparent evidence explorer |
| Ranking quality | 🚧 Improving | Needs better launch-readiness weighting |
| Telemetry vs findings separation | 🚧 Improving | Some internal pipeline events still need cleanup |
| Screenshot-aware reasoning depth | 🚧 Improving | Evidence exists; deeper interpretation still evolving |
Limen is presented as a launch-decision product, not just a diagnostics dashboard.
Collects the launch brief before the analysis starts.
Shows:
- launch board summary
- verdict
- pipeline progress
- top findings
- screenshot + HTML evidence
- persona replay
- rewrite suggestions
- extracted signals
apps/
web/ -> Next.js control plane and UI
worker/ -> queue consumers, capture, extraction, synthesis
packages/
shared/ -> schemas, constants, shared contracts
db/ -> Prisma schema and DB client
ui/ -> shared UI package placeholder
- launch brief intake
- run creation
- run detail rendering
- artifact serving
- consuming queued runs
- fetching page data
- rendering screenshots
- extracting signals
- creating findings
- generating summaries, persona outputs, and rewrites
- audit runs
- page captures
- artifacts
- extracted signals
- findings
- persona replays
- rewrite suggestions
- analyzer outputs
- background execution for launch runs
- Next.js 16
- React 19
- TypeScript
- Tailwind CSS
- React Hook Form
- Zod
- Node.js
- TypeScript
- BullMQ
- Redis
- Playwright
- Postgres
- Prisma
- Node.js 22 (the version used by the deployment configuration)
- pnpm 9.15.0 (see
packageManagerinpackage.json) - Docker for the local Postgres and Redis containers below
pnpm install --frozen-lockfiledocker run --name limen-postgres \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=limen \
-p 5432:5432 \
-d postgres:16If already created:
docker start limen-postgresdocker run --name limen-redis -p 6379:6379 -d redis:7If already created:
docker start limen-rediscp .env.example .envDATABASE_URL="postgresql://postgres:postgres@localhost:5432/limen"
REDIS_URL="redis://localhost:6379"pnpm --filter @limen/db prisma:generate
DATABASE_URL='postgresql://postgres:postgres@localhost:5432/limen' \
pnpm --filter @limen/db prisma:deploypnpm --filter worker exec playwright install chromiumDATABASE_URL='postgresql://postgres:postgres@localhost:5432/limen' \
REDIS_URL='redis://localhost:6379' \
pnpm --filter web devIn another terminal:
DATABASE_URL='postgresql://postgres:postgres@localhost:5432/limen' \
REDIS_URL='redis://localhost:6379' \
pnpm --filter worker devRun workspace commands from the repository root. The web app and worker run in separate terminals.
The worker loads the root .env on Node.js 22. For the web app, put DATABASE_URL and REDIS_URL in apps/web/.env.local, or keep the inline environment variables shown in the quickstart.
Once the dev server is ready, open the local app or the new run form.
HTML and PNG artifacts default to the worker's .artifacts directory. ARTIFACT_STORAGE_PATH can select an absolute directory; the web process must be able to read the paths saved by the worker. Separate hosts need shared storage for artifact previews.
-
pnpm dev:webstarts the web development server from the repository root. -
pnpm dev:workerstarts the worker in watch mode from the repository root.
A partial_failed run can still include captured evidence and deterministic findings. This status is used when no reasoning provider is configured or all configured reasoning providers fail.
-
Run stays queued: start the worker and check that both processes use the same
REDIS_URLandDATABASE_URL. -
Database connection or missing table errors: check the Postgres container and
DATABASE_URL, then apply the existing migrations from the quickstart. -
Missing Chromium executable: run
pnpm --filter worker exec playwright install chromiumin the environment that runs the worker. -
Artifact preview returns 404: check that the file still exists and is readable by the web process. A database record alone does not restore a deleted artifact file.
Use pnpm typecheck to check all workspace packages, or target them individually:
pnpm --filter web typecheck
pnpm --filter worker typecheck
pnpm --filter @limen/db typecheck
pnpm --filter @limen/shared typecheck
pnpm --filter @limen/ui typecheckpnpm --filter worker buildpnpm --filter @limen/db prisma:generateAfter editing packages/db/prisma/schema.prisma, create a named migration against your local development database:
DATABASE_URL='postgresql://postgres:postgres@localhost:5432/limen' \
pnpm --filter @limen/db prisma:migrate --name <migration-name>pnpm --filter web buildpnpm --filter web lintThe worker and shared package lint scripts are currently placeholders; they do not perform lint checks.
DATABASE_URL='postgresql://postgres:postgres@localhost:5432/limen' \
pnpm --filter @limen/db exec prisma migrate status --schema ./prisma/schema.prisma- launch run creation
- queue-backed worker execution
- HTML fetch
- Playwright screenshot capture
- artifact persistence
- extracted signal persistence
- finding generation
- verdict generation
- launch summary
- persona replay
- rewrite suggestions
- artifact preview UI
- extracted signals UI
- issue prioritization quality
- stronger launch-board scoring/rubric
- more grounded persona replay
- more concrete copy rewrites
- clearer distinction between telemetry and user-facing issues
- deeper screenshot-aware analysis
- final UI polish for launch-grade presentation
POST /api/runs accepts a JSON launch brief. A successful response queues background work; it does not mean the analysis has finished.
competitors is optional and accepts up to five nonempty strings, each at most 200 characters.
objections must contain 1–8 nonempty strings, each at most 200 characters.
Text lengths: audience 3–200 characters, desiredAction 2–120, offer 2–240, and brandVoice 2–120.
Supported trafficChannel values are cold_paid, branded_search, founder_social, and launch_day.
Send the request with Content-Type: application/json:
{
"url": "https://example.com",
"audience": "Independent software founders",
"trafficChannel": "cold_paid",
"desiredAction": "Start a free trial",
"offer": "A launch review for landing pages",
"objections": ["Unsure how much setup is needed"],
"brandVoice": "Clear and practical"
}On success, the API returns HTTP 200:
{"runId": "<run-id>", "status": "queued"}HTTP 400 includes error and issues fields when the JSON launch brief fails validation.
HTTP 500 reports that a run could not be created or queued; inspect the web server logs for the underlying error.
Open /runs/<runId> in the web app to follow progress and review results.
Create a launch run.
Enter:
- page URL
- target audience
- channel (for example
cold_paid) - desired action
- offer
- objections
- brand voice
Limen will:
- validate the URL
- capture page HTML
- render a screenshot
- extract structure and trust signals
- generate findings
- produce a verdict
- explain likely visitor reactions
- propose copy improvements
Review:
- summary
- top reasons
- top fixes
- findings
- evidence
- persona replay
- rewrite suggestions
Findings should be backed by captured artifacts and structured signals.
A page should not be judged without its audience and channel.
The product should answer:
- should I launch?
- why not?
- what do I fix first?
Findings alone are not enough. Teams need summaries, personas, and actionable rewrites.
Potential next improvements:
- cleaner separation between telemetry and user-facing findings
- stronger ranking model for blockers vs opportunities
- better verdict logic tied to launch readiness dimensions
- more concrete rewrite outputs
- more evidence-linked persona replay
- screenshot-region-specific analysis
- side-by-side before/after comparisons
- preview URL support
- launch history and regressions
Limen is fully configured for automated cloud deployment and vertical auto-scaling on Zerops.
Create the project and provision all required services (Next.js web app, background worker, managed PostgreSQL, and KeyDB queue) using the provided zerops-project.yml:
# Using the Zerops CLI (zCLI)
zcli project service-import zerops-project.ymlOr paste the contents of zerops-project.yml directly into the Zerops GUI under Project > Import Services.
- In your Zerops project dashboard, connect your GitHub repository to both the
webandworkerservices. - Zerops will detect
zerops.ymland automatically run the build, dependency installation, browser binary provisioning, and database schema synchronization.
Zerops automatically injects database and queue connection strings. Configure your LLM API keys in the Zerops GUI under the worker service environment variables:
| Variable | Description | Required |
|---|---|---|
DATABASE_URL |
Injected automatically by Zerops (${db_connectionString}) |
Yes |
REDIS_URL |
Injected automatically by Zerops (redis://${redis_hostname}:${redis_port}) |
Yes |
GEMINI_API_KEY |
Google Gemini; first reasoning provider when configured | Recommended |
GROK_API_KEY |
Grok; tried after Gemini | Optional |
ANTHROPIC_API_KEY |
Anthropic; tried after Grok | Optional |
OPENAI_API_KEY |
OpenAI; tried after Anthropic | Optional |
apps/
web/
worker/
packages/
db/
shared/
ui/
This repository intentionally focuses on the product code. Internal planning, local research, and non-essential local files are excluded from GitHub.
Limen is not trying to become another generic audit dashboard.
The long-term goal is to become the layer teams run before launch to answer:
Is this landing page ready for the traffic we’re about to send?
That means Limen should eventually become:
- more context-aware
- more evidence-backed
- more trustworthy
- more decisive
- more useful in real launch workflows
Limen already runs a real end-to-end launch review pipeline.
The next stage is making that intelligence:
- sharper
- more trusted
- more product-ready
Don’t ask whether the page exists. Ask whether it’s ready.