Public

Changelog

Everything we've shipped on Unformal, reverse chronological.

Unformal — Changelog

Shipped features and fixes, reverse chronological. For the roadmap and upcoming features, see Roadmap.


2026-04-18

CLI Documentation — @unformal/cli Now Surfaced Everywhere

The @unformal/cli npm package has existed for a while but wasn't documented on the public site. Now surfaced in all four entry points: the /agents "Built for Agents" page, the /docs/api reference, the UNFORMAL.md skill file, and llms.txt.

  • Install: npm i -g @unformal/cli (or npx @unformal/cli <command>)
  • Every API endpoint exposed as a subcommand — unformal create, list, get, conversations, resonance, analytics, export, usage
  • --json flag on every command for piping structured output to other agents
  • Source at github.com/Spark-Collective/unformal-skills/tree/master/cli

Notification Routine — Claude Code Desktop Routines (Primary Path, Corrected)

Recommend Claude Code desktop routines (SKILL.md files at ~/.claude/scheduled-tasks/<name>/) as the primary notification path — these appear in the Claude Code desktop sidebar alongside other routines, run locally with access to local secrets, and let the user pick the schedule visually in the desktop UI.

  • Initial attempt used the schedule skill (remote triggers at claude.ai/code/scheduled) which was the wrong surface — those don't appear in the desktop sidebar
  • Corrected: unformal-notifications SKILL.md (in unformal-skills repo) now describes the desktop-routine pattern with the exact SKILL.md template and tempfile-based Python parsing (avoids heredoc stdin collision)
  • /agents page section updated: "Claude Code Desktop Routine" with the corrected copy-paste prompt
  • UNFORMAL.md skill updated to match
  • Created working example at ~/.claude/scheduled-tasks/unformal-new-responses/SKILL.md for WAT feedback monitoring
  • Disabled the (wrong) remote trigger trig_01R77BAkEBZehYSdYc5FvpRK

2026-04-17

Desktop Notifications — Real-time Pulse Response Alerts

New unformal-notifications Agent Skill in the [unformal-skills repo](https://github.com/Spark-Collective/unformal-skills) that gives Claude Code (or any agent) real-time awareness of new Pulse responses.

  • New unformal-notifications/SKILL.md — teaches Claude to summarize inbox events on demand, fall back to completedSince API polling when no listener is running, archive processed events, and act on new responses
  • New unformal-listen.sh shell script — connects to the SSE stream, shows native macOS notifications (Linux: notify-send fallback), writes each event to ~/.unformal/inbox/.json
  • Script also hosted at unformal.ai/unformal-listen.sh for quick one-liner install
  • New "Desktop Notifications" section on /agents page with install + demo output
  • UNFORMAL.md skill extended with the same notification patterns

HR Use Case — Refocused on Feedback Surveys

Shifted the HR use case page away from "exit interviews" (which felt heavy and odd to productize as a survey) toward feedback surveys and interviews — the actual sweet spot for a conversational form tool.

  • Hero: "What if feedback surveys captured what people really think?"
  • Use case table now leads with engagement pulse checks, onboarding feedback, team feedback interviews, performance reviews, 360 feedback, and training/event feedback
  • Nav dropdown, landing page card, and OG metadata updated to match
  • Exit interviews removed as a headline use case

Interviewer-style Thinking Animation (replaces token-by-token streaming)

Replaced the slow character-by-character streaming of AI responses with a rotating shimmer animation that reflects the interviewer role — words like "Listening carefully", "Taking that in", "Following your thread", "Curious to dig deeper", "Framing a follow-up", "Jotting that down". When streaming completes, the full message reveals at once with a smooth fade-in. This directly addresses the UX friction Florian flagged in WAT beta feedback — the perceived lag between questions.

  • New ThinkingAnimation component with gradient shimmer, dark-mode aware, rotates every 1.8s
  • Shows for the entire isLoading duration (was previously only before first token, then switched to live streaming)
  • No more slow-typing feel between questions

Public Changelog

  • New public /changelog page at unformal.ai/changelog
  • Inline markdown renderer (no new dependencies)
  • Synced from workspace via skills/changelog/sync-to-app.sh
  • Added "Changelog" link to marketing footer
  • /ship skill updated: mandatory changelog entry before every commit, auto-sync to app

2026-04-15

Automated Reminders + Onboarding Drip via Resend Automations

End-to-end event-driven email automation for survey reminders and new user onboarding.

  • New convex/resendEvents.ts — shared helper to fire Resend Automation events (recipient.invited, conversation.completed, user.created, pulse.created)
  • New convex/resendAutomations.ts — idempotent setup actions that create templates and automations via Resend API
  • Reminder sequence: 2-day delay → check for completion → send reminder → repeat once more
  • Onboarding drip: 1-day delay → check for pulse creation → nudge → 2-day delay → personal help email
  • Templates created and published in Resend dashboard programmatically
  • Auto-reminders toggle on pulse Distribution tab (saves autoRemindersEnabled)
  • Schema: systemConfig table for storing automation IDs, autoRemindersEnabled field on pulses

Admin Dashboard + LLM Cost Tracking

Super admin view of platform-wide metrics and real-time cost visibility.

  • Role-based admin access via users.role: "admin" (replaced email whitelist)
  • Token usage logging added to all 5 previously untracked backend actions: resonance, extractEcho, insightExchange, pulseOptimizer, research
  • New convex/llmHelpers.ts — shared cost calculation and usage extraction
  • New /studio/admin page: platform stats (users, workspaces, pulses), LLM costs (today/7d/30d/all-time), 14-day trend chart, cost breakdown by model and by source, top workspaces by cost
  • Added source field to usageEvents schema
  • Backfilled token costs for 20 historical completed conversations using transcript char count estimation
  • Fixed auth race condition in admin page (skip queries until useConvexAuth is loaded)

Insight Exchange — Respondent Reward Mechanism

Respondents who complete a conversation unlock personal insights + anonymized group intelligence.

  • Schema: insightExchange toggle on pulses, insightExchangeObservation field on conversations
  • New public query resonanceHelpers.getForInsightExchange — returns anonymized aggregate data (requires insightExchange: true and 3+ completions)
  • New CollectiveInsightsSection component renders below personal InsightsScreen: group sentiment bar, top themes with frequency bars, consensus/divergence cards
  • Phase 2: New convex/insightExchange.ts generates personalized AI observation contextualizing respondent's answers within group (Claude Sonnet, ~1K tokens)
  • Phase 3: Welcome screen shows respondent count ("14 people have shared their thoughts. Complete yours...")
  • API: insightExchange field on POST/PATCH/GET pulse endpoints, llms.txt docs, UNFORMAL.md example
  • Cleanup: deleted 90 abandoned test conversations
  • See Insight Exchange

Email Distribution List + Automated Reminders (P0)

Full workflow infrastructure for sending invitations, tracking completion, and reminding non-completers.

  • Schema: pulseRecipients table with status tracking (pending → sent → started → completed)
  • Mutations: addRecipients, removeRecipient, sendInvitations, sendReminders, _updateRecipientStatus, _markReminded
  • Actions: sendInvitations and sendReminders via Resend with branded HTML templates
  • Studio Distribution tab: recipient list with status badges, bulk add, send invitations, reminder settings (24h/48h/72h delays, 1/2/3 max reminders)
  • Conversation flow integration: recipientToken URL param (?t=xxx) tracked through create → started → completed
  • Automatic status updates via scheduler when conversations complete
  • See Email Distribution List, Reminders & Nudges

CSV/JSON Export (P0)

Data portability — download conversations from any Pulse.

  • GET /api/v1/pulses/:id/export?format=csv|json — public API endpoint
  • Studio InboxTab: Export dropdown (CSV or JSON) with client-side generation via Blob
  • CSV: flattens echo fields as columns, one row per conversation
  • JSON: includes full transcript, echo, and metadata
  • New convex/exports.ts + exports_queries.ts for action/query separation

Pulse Creation — Custom Slug Support

  • Added optional slug field to create and _createFromApi mutations with validation (format, reserved list, uniqueness)
  • Shared resolveSlug helper replaces duplicate slug generation logic
  • Studio /studio/new: slug input with unformal.ai/p/ prefix and debounced availability check
  • API: slug field on POST /pulses (falls back to auto-generation if omitted)
  • Agents get branded URLs instead of understand-what-a-new-clie-x7k2m9

Built for Agents Page + Navbar

  • New /agents route (renamed from /integrate) — full integration guide for AI agents
  • Uses shared MarketingHeader / MarketingFooter for consistency across marketing pages
  • Added "Built for Agents" link to desktop and mobile navbar (between Docs and Sign in)
  • /integrate redirects to /agents for backward compatibility
  • Landing page CTA updated

Completion UX Polish

  • Removed full-screen "Analyzing" takeover that replaced the conversation — now shows inline "Wrapping up..." spinner instead
  • Input field and textarea form hidden immediately when completion is detected (was still showing under "View insights" button due to form being outside the conditional block)
  • Reduced completion delay from 3s → 1.5s → 0.8s for snappier transition
  • Fixed: onFinish callback now uses conversationIdRef.current instead of conversationId state, ensuring the first AI message is always saved to the transcript (fixes "first message missing" bug)

Agent Behavior Fixes

  • AI now skips questions in extract mode that were already answered in the initial brain dump (was re-asking for URL after user included it in Q1 dump)
  • Strengthened "one question per message" instruction to a CRITICAL RULE (AI was firing 2-3 questions per response)
  • Instructed AI to never write internal status notes like "starts researching..." — added frontend regex safety net
  • Research mode instructions updated to not re-ask for URL if one was already provided in conversation history
  • Set FIRECRAWL_API_KEY and EXA_API_KEY in Convex env — research was silently failing before
  • Bumped 100in-pitch maxQuestions from 10 to 12

Storage ID Alias System (Image Attachments)

  • Root cause: AI was truncating long 32-character Convex storageIds when reproducing them in image_select ui_hint JSON output (e.g. dropping gwcqa0n from the middle of the 4th image's ID)
  • Fix: system prompt now passes short aliases (img1, img2, ...) instead of real storageIds
  • Frontend resolves aliases back to real IDs via pulse.questionFramework, with label-based fuzzy match fallback for already-broken conversations
  • Also fixed broken attachment images in PulseSettingsForm — the isStorageId heuristic required a : that Convex IDs don't contain
  • Fixed getFileUrl crash on invalid IDs (restored v.id("_storage") for optimized performance after root cause fix)

Dynamic Pricing Spec (Documentation Only)

  • Added Dynamic Pricing feature spec — token-based credit consumption model with conversation-length tiers
  • Recommended approach: Option B (tiered based on maxQuestions: 3Q=1cr, 5Q=2cr, 8Q=3cr, 12Q=5cr, 20Q=8cr)
  • Margin analysis, credit pack impact, three implementation phases

Workspace Agent OS Improvements

  • Added .claude/launch.json for preview servers
  • Pre-commit hooks in settings.json to catch secrets before git commit
  • New /rollback command for emergency production reverts
  • Activated /learn system (data/learnings.jsonl)
  • Expanded /user-support command to 15 structured steps across 5 phases
  • Created docs/troubleshooting.md runbook for Convex/Vercel/auth/Stripe/AI failures

Miscellaneous Fixes

  • Removed hardcoded "WAT" reference from Insight Exchange welcome text — now generic
  • Fixed build error: added mode to chat route pulseConfig type
  • Enabled token cost tracking end-to-end: frontend now sends workspaceId and pulseId to chat API (was silently missing)
  • Set jonas@sparkcollective.be as admin role

2026-04-12

Pulse Attachments + Image Select Component

Creator-uploaded attachments on Pulses. The AI can reference and display images during conversations.

  • Schema: attachments array on pulses table (storageId, name, filename, mimeType, type)
  • Mutations: addAttachment, removeAttachment (+ internal variants for API)
  • API: attachments in PATCH whitelist and GET response
  • New adaptive input: image_select — grid of clickable image cards with checkmark overlay, single/multi select
  • Prompt templates bumped to V2 with image_select documentation
  • Chat route injects pulse attachments into system prompt
  • Studio: attachment upload section in PulseSettingsForm with thumbnail grid and delete
  • See Pulse Attachments

Email Distribution List + Completion Tracking

Send Pulse invitations to named recipients and track who completed.

  • Schema: pulseRecipients table (pulseId, name, email, linkToken, status, conversationId, sentAt, completedAt)
  • Mutations: addRecipients, removeRecipient, sendInvitations, sendReminders
  • Actions: sendInvitationEmails, sendReminderEmails via Resend
  • Pulse schema: reminderEnabled, reminderDelayHours, maxReminders fields
  • Conversation page: recipientToken support for tracking named respondents
  • See Email Distribution List, Reminders & Nudges

CSV/JSON Export API

  • GET /api/v1/pulses/:id/export?format=csv — download conversations as CSV
  • GET /api/v1/pulses/:id/export?format=json — download as JSON
  • convex/exports.ts — generateCsv and generateJson internal actions

Website: 5 New Pages

  • /use-cases/accelerators — "Screen 200 applicants without reading 200 forms"
  • /use-cases/agencies — "Briefs that actually brief"
  • /use-cases/hr — "What if exit interviews captured what people really think?"
  • /compare — Unformal vs Typeform comparison with pricing table
  • /blog/why-forms-give-garbage-data — SEO blog post about form pain points

Navigation Redesign (React Bits Pro)

  • New MarketingLayout.tsx shared component (header, CTA, footer) used across all marketing pages
  • Glass-effect rounded navbar with expanding card dropdown for use cases (AnimatePresence from motion/react)
  • Mobile hamburger menu with full use case cards
  • Landing page and pricing page refactored to use shared MarketingHeader/MarketingFooter
  • React Bits Pro setup: components.json, license, cn utility, Navigation-2 block installed

FAQ Redesign (Pricing Page)

  • Replaced bordered boxes with clean divider lines
  • Plus/cross toggle icon with filled circle on active state
  • Smooth AnimatePresence height animation
  • Consistent max-w-3xl width matching rest of page

Ranking Drag-and-Drop Fix

  • Fixed page-level file upload drop zone intercepting Ranking component's internal drag events
  • Added e.dataTransfer.setData(), e.preventDefault() on drop, and e.stopPropagation() on all drag events
  • Added dataTransfer.types.includes("Files") check to page-level handlers

WAT Beta Feedback Pulse Improvements

  • Updated WALDO persona: three pivots origin story, celebrates WAT before critiquing
  • Reduced maxQuestions 12 → 8
  • Added meme picker opening question with 4 AI-generated meme images (via XAI Grok Imagine)
  • Updated context: celebration-first tone, meta-awareness of being an Unformal demo

Form Pain Index Campaign Pulse

  • Created market research Pulse at /p/understand-the-deepest-frustrations-peop-9c3muf
  • Casual tone, 8 questions, coverage-based completion, insights shown to respondent
  • 3 LinkedIn post drafts in campaign plan

2026-04-11

Question Framework Field + Smart Completion Algorithm

Smart Completion: Replaced hard maxQuestions limit with coverage-based completion. Three modes: balanced (default, 80% coverage target), coverage/thorough (90%, extends freely), speed/quick (70%, respects question target). buildSmartCompletionPrompt() in chat route, completionPriority field on Pulse schema, UI toggle in Studio. See Smart Completion Algorithm.

Question Framework Field

Clean architectural separation: persona = personality only, questionFramework = structured questions with ui_hint definitions.

  • Schema: questionFramework array on pulses table
  • Backend: generateConfig and fallback prompt builder use it cleanly
  • Studio UI: JSON editor in settings and create flow with validation
  • Chat route: persona now properly forwarded

2026-04-04

Auto-Improving Pulses (V1)

Self-optimizing conversation flows — analyze past conversations and propose config improvements. See Auto-Improving Pulses for full spec.


2026-04-03

Response Limit per Pulse + Closed/Archived Pulse Page

  • maxResponses field on pulses (Unlimited / 10 / 25 / 50 / 100)
  • ClosedPulseScreen for archived/paused, ResponseLimitScreen for limit-reached
  • Studio inbox shows "X / Y responses"
  • API: maxResponses in POST/PATCH/GET

2026-03-31

ui_hint JSON Flash Fix

parseUIHint now detects ui_hint-shaped JSON in both code block types. Partial blocks stripped during streaming.

Resonance Compute Race Condition Fix

lastComputedAt + _shouldCompute + _markComputing — transactional lock prevents duplicate API calls.

Adaptive Input AI Reliability

Strengthened system prompt: MUST use structured inputs for finite options. Dutch language quality instructions added.

Docs — Shipped

/docs index, /docs/concepts guide, /docs/best-practices playbooks.

Terms + Privacy Date Update

Updated "Last updated" dates.


2026-03-30

Pulse Settings Tab — Now Inline

Settings form embedded directly in the "Settings" tab on Pulse detail page, no longer a separate page.

Workspace Not Auto-Created — Fallback Fix

getOrCreate mutation in Studio layout now reliably creates a workspace if the afterUserCreatedOrUpdated callback fails. Not a root cause fix (Convex Auth callback is unreliable), but eliminates user-facing impact.

Model Fallback + Budget Monitoring

Claude Sonnet → GPT-4o → Gemini Flash failover. Token usage tracking. Usage dashboard. X-Unformal-Model header.

Session Recovery

localStorage persistence. "Welcome back" banner with Continue/Start Over. Resume via URL params.

DNS Email Deliverability

SPF + DMARC records. Login spam warning + resend button.

Landing Page Updates

"Try it yourself" demo section. Trust/transparency section. Pricing tiers. Footer links.

Multi-Workspace Support — Phase 1

workspaceMembers table, roles, workspace switcher, scoped queries, getOrCreate guard.

Extract Mode

New mode field (interview | extract). Casual tone. Dump-first strategy with field coverage tracking.

Credit System + Stripe

Stripe Checkout, webhook handler, credit packs (€9/100 → €249/10K), Studio settings integration.

Agent Neutrality Rules

Universal rules: never praise, stay neutral, repeat proper nouns, position as preparation not replacement.

Welcome Screen Customization

welcomeTitle + welcomeDescription fields on Pulses.

2026-03-29

REST API

Full API: create/list/get/update/delete Pulses, list conversations, get conversation, usage stats, agent signup.

Agent-Friendly Distribution

llms.txt, UNFORMAL.md skill file, ai-plugin.json, SSE stream, integration docs page.

Templates

4 pre-built: Client Onboarding, User Research, Lead Qualification, Brain Dump Intake.

File Uploads + Link Sharing

Image upload, drag & drop, Convex file storage, URL detection, link previews, FileUpload + LinkInput adaptive inputs.

Security Hardening (7 Critical + 3 Important)

Session tokens, rate limiting, webhook secrets, email verification protection, signup rate limiting, SSRF protection, file upload auth. See SECURITY_FIXES.md.

Dark Mode

Full coverage: Studio, conversation page, login, privacy/terms.

Legal Pages

GDPR-compliant privacy policy + terms of service (Belgian law, Gent).

Email Templates

Coinbase-inspired design for verification + completion notification emails.


2026-03-28

Echo + Resonance

Primary + fallback Echo extraction. Resonance: themes, consensus, divergence, sentiment, recommended actions.


User Feedback Log

Sil (Shift & Season, 2026-03-30)

1. Login email in spam → Fixed (SPF + DMARC) 2. No demo/preview without building → Fixed (demo Pulse on landing page) 3. Free tier trust / GDPR concerns → Fixed (transparency section, business model explanation) 4. Conversation crash before completion → Session recovery shipped 5. No session recovery → Fixed 6. Privacy concern about voice input → Needs clearer explanation 7. "What happens with my answers?" → Needs post-completion explanation 8. Auto-generate Pulse from website URL → Future feature idea


Related: Roadmap, Product Spec*