Skip to content
NiyathnairPublic

About

Simulate a population of audience personas to stress-test campaign copy before publishing

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

17 Commits

Folders and files

Repository files navigation

crowdLens

A proactive simulation environment for marketers.

Test campaign copy against a simulated population of audience personas before publishing — and find out not just whether people will be offended, but what they think you said.

The idea

Offense is not a property of text. It is a relationship between text and an audience. So the primitive isn't a classifier — it's a population of simulated readers, each with distinct values, sensitivities, and readings of context.

Most backlash isn't caused by people being offended by what you said. It's caused by people being offended by what they think you said. Those are different failures with different fixes:

  • Misunderstood → the copy is ambiguous → clarify it
  • Controversial → the copy is understood and rejected → decide whether you accept that cost

A tool that reports only "risk: 62" can't distinguish them, and therefore can't tell you what to do. crowdLens models interpretation first and reaction second.

What it produces

Eight questions, twenty-four analysis views:

Question
🧠 What did they understand?
❤️ How did they feel?
⚠️ Why might they react badly?
🎯 Who is affected?
🔍 What exactly caused it?
📊 How does it compare to similar campaigns?
✏️ How can we fix it?
🔄 Did the fix actually work?

Design

DESIGN-SYSTEM.md — visual language: palette, typography, components, and how risk bands and Tier-2 findings are rendered.

Plan

BacklashTest-Complete-Plan.md — the complete specification: product framing, persona graph architecture, full mathematical treatment, all 24 dashboard panels, validation strategy, build phases, and an honest accounting of the risks.

Status

Backend stages 1-4 implemented (see backend/) — persona engine, scoring, rewrite engine, backlash graph, and live news ingest with a failure corpus. Frontend dashboard implemented (see frontend/) following the design system above.

Run locally

Two processes: the FastAPI backend on port 8000 and the Vite dev server on port 5173, which proxies /v1/* to the backend.

Backend (Python 3.11 or newer):

cd backend
python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"
export CLAUDE_CODE_OAUTH_TOKEN='<token printed by: claude setup-token>'
.venv/bin/uvicorn app.main:app --reload --port 8000

The credential is read from the process environment in this order: CLAUDE_CODE_OAUTH_TOKEN, ANTHROPIC_AUTH_TOKEN, ANTHROPIC_API_KEY. If none is set the server refuses to start and prints setup instructions. Optional settings use the CROWDLENS_ prefix (for example CROWDLENS_PERSONA_MODEL, CROWDLENS_TARGET_K, CROWDLENS_APIFY_TOKEN, CROWDLENS_SYNC_INTERVAL_HOURS, CROWDLENS_SYNC_ON_STARTUP); see backend/.env.example and backend/app/config.py.

Interactive API docs are served at http://localhost:8000/docs. A simulation request:

curl -X POST localhost:8000/v1/simulate -H 'content-type: application/json' -d '{
  "copy": "Our new protein bar — finally, a beef bar that doesn'\''t taste like a cow.",
  "brand_intent": "Position our protein bar as great-tasting and high-protein.",
  "context_scenario": "dietary_controversy_india"
}'

Frontend (Node.js and npm):

cd frontend
npm install
npm run dev

Open http://localhost:5173. Without a running backend, the Demo button in the top bar loads a hardcoded report, so the dashboard can be viewed with no backend and no Claude credential.

Tests (backend unit tests):

cd backend
.venv/bin/python -m pytest tests/unit -q

Repository layout

crowdlens/
├── backend/
│   ├── app/
│   │   ├── main.py          FastAPI entrypoint; mounts both routers under /v1
│   │   ├── config.py        settings (models, selection, scoring weights, ingest)
│   │   ├── api/             routes.py (simulate, runs, panels, personas, scenarios), ingest_routes.py (ingest, corpus)
│   │   ├── personas/        schema, registry, and YAML persona definitions
│   │   ├── router/          N→K persona selection
│   │   ├── orchestrator/    run execution
│   │   ├── composition/     Tier-2 composites
│   │   ├── scoring/         risk index and uncertainty interval
│   │   ├── analysis/        panel projections, backlash graph, redesign
│   │   ├── rewrite/         rewrite engine
│   │   ├── context/         context provider and JSON scenario fixtures
│   │   ├── ingest/          news sources, sync pipeline and scheduler
│   │   ├── corpus/          incident (failure) corpus store
│   │   └── llm/             Anthropic client, credential resolution, JSON salvage
│   ├── tests/unit/          pytest suite
│   ├── pyproject.toml
│   └── .env.example
├── frontend/
│   ├── src/                 App.tsx, panels/, components/, lib/ (API client, demo data), styles/
│   ├── public/              map, face and background assets
│   ├── package.json         scripts: dev, build, preview
│   └── vite.config.ts       dev server on 5173, proxies /v1 to localhost:8000
├── DESIGN-SYSTEM.md
└── BacklashTest-Complete-Plan.md

The scoring weights in the plan are priors to be calibrated against a golden set, not validated constants.

About

Simulate a population of audience personas to stress-test campaign copy before publishing

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages