Feedback that builds better teams.
Replace numerical surveys with natural language. People write freely about their work; Claude reads, scores, and asks the follow-up questions you would have asked.
Five-point scales tell you that something is wrong. They don't tell you what. Candor flips that: respondents write a paragraph, and an LLM extracts the metrics you defined — happiness, engagement, "would you recommend" — with a confidence score and a one-line rationale. If the response is thin, Claude asks one or two clarifying questions before submitting.
The result is structured data you can chart, plus the actual words your team used.
A walkthrough of the four moments that matter — from the first visit to the insight that changes a decision.
The pitch in one screen: feedback that builds better teams, an explicit three-step model (Create → Collect → Analyze), and the features that make it work — natural language, smart follow-ups, real-time dashboard, AI insights, exports.
Respondents see a single textarea with a contextual opener (e.g. "Q1 Team Pulse Check"). No 1–5 scales, no required fields, no "select one" — just a placeholder inviting them to write about what's going well and what could be better. Behind the scenes, Claude reads the paragraph, scores each metric the creator defined, and decides whether to ask one or two clarifying questions before submitting.
Once responses come in, the creator opens the survey and sees the metrics they defined — extracted, aggregated, and tied back to the underlying responses. In this run of Q1 Team Pulse Check with 11 responses: average Happiness 3.8 / 5 at 89% confidence, and 82% would recommend the company to a friend (9 of 11). One click ships a public share link, a PDF, or a CSV.
Numbers tell you what; AI Insights tells you why. The same survey detail page surfaces a one-paragraph executive summary, key themes pulled from the corpus, and a strengths-vs-concerns split — "compelling mission and meaningful work driving motivation" on one side, "tight deadlines leading to overtime, stress, and coordination difficulties" on the other. This is the panel a manager screenshots into the next leadership meeting.
- Natural-language responses — no Likert scales shown to the user
- AI-extracted metrics — Claude returns
score,confidence,reasoningper metric defined by the creator - Adaptive follow-ups — up to N (default 2) clarifying questions per respondent, generated in-context
- Two access modes — invite-only (email allowlist) or public link
- Encrypted at rest — response payloads pass through
src/lib/crypto.tsbefore storage - Real-time dashboard — survey list, response counts, per-survey detail with charts (bar / pie / radar via
recharts) - AI-generated insights — themes and recommendations on top of aggregated metrics
- PDF export —
jspdf+html2canvasto ship a report - Light + dark theme —
next-themes
| Layer | Choice |
|---|---|
| Framework | Next.js 16 (App Router) + React 19 + TypeScript |
| Styling | Tailwind CSS 4 + shadcn/ui-style components + Framer Motion |
| Auth + DB | Supabase (Postgres, RLS, magic-link + Google OAuth, SSR via @supabase/ssr) |
| AI | Anthropic Claude (@anthropic-ai/sdk), Vercel AI SDK |
| Charts | Recharts |
| Hosting | Vercel |
Creator Respondent
│ │
▼ ▼
/create ── defines metrics ──► surveys ──┐
│
(invite/link) │
▼
/respond
│
▼
POST /api/analyze ──► Claude
│
extracted metrics ◄─┘
│
follow-up needed?
│ │
yes no
│ │
▼ ▼
ask again store in Supabase
│
▼
/dashboard ──► insights, charts, PDF
SurveyMetric— what to measure:name,description,type(rating|boolean),scale_min,scale_maxExtractedMetric— Claude's output:score,confidence,reasoningFollowUpQuestion— question/answer pair for clarification
src/
├── app/
│ ├── api/
│ │ ├── analyze/ # Claude extraction endpoint
│ │ ├── generate-question/ # Contextual opener + follow-ups
│ │ ├── insights/ # Aggregate themes / recommendations
│ │ └── surveys/[id]/ # check-response, invite, participants, submit, review
│ ├── auth/ # Magic-link callback + login page
│ ├── create/ # Creator flow + success
│ ├── dashboard/ # Creator's survey list + per-survey detail
│ ├── my-surveys/ # Surveys a respondent has been invited to
│ ├── respond/ # Public response page
│ └── survey/[id]/ # Tokenised survey link target
├── components/
│ ├── charts/ # bar / pie / radar wrappers
│ └── ui/ # button, card, input, textarea, skeleton, …
├── lib/
│ ├── anthropic.ts # Claude client
│ ├── crypto.ts # Response payload encryption
│ └── supabase/ # browser, server, admin, middleware clients
├── middleware.ts # Route guarding via Supabase SSR
└── types/
├── database.ts # Generated Supabase types
└── index.ts # Domain types
supabase/
└── migrations/ # SQL migrations (orgs, anon insights, etc.)
git clone --recursive https://github.com/ronakv/candor.git
cd candor
# or, if already cloned:
git submodule update --init --recursiveThe .claude/skills/gstack submodule provides browse / review / ship / retro slash commands when working in Claude Code.
npm installCopy .env.example → .env.local and fill in:
NEXT_PUBLIC_SUPABASE_URL=https://<project>.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=<anon-key>
SUPABASE_SERVICE_ROLE_KEY=<service-role-key> # server-only
ANTHROPIC_API_KEY=<sk-ant-…> # server-only
ANON_HASH_SALT=<32+ random chars, never rotate in prod># from a Supabase project with the CLI installed
supabase db push
# or paste files in supabase/migrations/ via the SQL editornpm run dev # http://localhost:3000
npm run build # production build
npm run start # production server
npm run lint # ESLint
npm test # Jest (covers crypto.ts at minimum)The app is deployed to Vercel at https://candor-smoky.vercel.app. Because NEXT_PUBLIC_* vars are baked into the client bundle at build time, a Vercel rebuild is required any time those variables change (e.g. after restoring a paused Supabase project to a new URL).
Private — © 2024 Candor Inc.



