What it is, how to set it up, and how to use every feature during your meeting.
Undrift runs in a browser tab during your meeting. It listens to what's being said — or you can type observations — compares the conversation to your agenda, and alerts you when things start to drift. When a topic goes off-track, it suggests a diplomatic redirect you can say out loud, so you're never the bad cop.
Undrift's Terms of Service and Privacy Policy are available for review.
Not yet. This Open Beta (v2.0.0) is designed specifically for in-person meetings where everyone is physically in the same room.
We're launching in-person first because it lets us perfect the core experience — real-time drift detection, smart redirects, and session analytics — without the added complexity of screen sharing, virtual participants, or audio routing.
What's next: If the in-person beta is successful, remote and hybrid support will be our immediate next priority. We'll begin development as soon as we hit our beta success metrics.
Open Undrift in Chrome or Edge. You'll land on the Session Setup screen with three ways to enter your agenda:
Build form — type agenda items directly, set topic, minutes, and type.
Upload agenda — download the .md template, fill it in, upload the completed file. Accepts .md, .txt, .csv, .json. Note: .docx files cannot be uploaded (browsers cannot read binary Word files without external libraries).
Paste & parse — paste any agenda format and AI extracts the structure.
Meeting title and agenda items are required. Date, duration, audience, facilitator name, and desired outcomes are optional but improve the report and redirect suggestions.
Click the date field or the calendar icon to open a date picker. Today is pre-selected. The date always displays as DD-MMM-YYYY (e.g. 07-Apr-2026). Dates imported from uploaded or pasted agendas are automatically converted to this format.
Gentle — flags only clear drift. Balanced — recommended for most meetings. Vigilant — flags early and often for tight, high-stakes sessions.
Click Launch session to review your configuration, then Enter meeting room to start the session timer.
| Type | Use when… |
|---|---|
| Discussion | Open conversation without a required decision |
| Decision | The group needs to reach a firm conclusion |
| Info share | One person presents, minimal back-and-forth |
| Workshop | Collaborative working time — exercises, whiteboarding |
| Q&A | Structured question and answer |
| Break | Scheduled pause |
| Element | What it does |
|---|---|
| Meeting title | Your meeting name and audience |
| Status pill | Live → Wrapping up → Over time |
| Scope slider | Adjust AI sensitivity live — Gentle / Balanced / Vigilant |
| Elapsed badge | Total session time running |
| Clock | Current wall clock time |
| Help | Opens this user guide in a new tab |
| End session | Stops the timer and generates your end-of-meeting report |
The color-coded track shows all agenda items proportional to their time allocation. Blue pulsing = active, Green = done, Gray = upcoming. The row below shows current item name, counter, on-track status, type, and a live countdown that turns amber at 80% and red when over.
Each item shows a timing row: pending items show allocated minutes in gray; the active item shows live elapsed time shifting blue → amber → red; completed items show actual vs. allocated time in green (on time) or red with overage. Click any item to jump to it.
| Card type | Color | Meaning |
|---|---|---|
| Flag | Amber left border | AI or manual flag — discussion is drifting |
| Drift detected | Red left border | Significant drift — redirect suggested |
| Time alert | Purple left border | Item or session is at time risk |
| Suggested redirect | Blue left border | AI-generated script you can say out loud |
| Note | Gray left border | Manual observation or system message |
Each card has a dismiss (×) button. Flag/Drift cards have Park it. Redirect cards have Copy. Use Filter to show one card type. The speaker icon enables audio cues.
Type into the input at the bottom of each tab and press Enter to add. All buckets appear in the end-of-meeting report.
The action bar scrolls horizontally between the feed and input bar. Each button gives a subtle press animation to confirm it registered.
Stamps the active item done with an exact timestamp and advances to the next item. Keeps timing data accurate for the report.
Manually raises a flag — logged in the feed and the report scorecard. Use when you spot drift before the AI does.
Opens a capture sheet. Describe the off-agenda topic and it saves to the Parking tab and appears in the report.
Opens a capture sheet. Describe the action item (add an owner if known) and it saves to the Actions tab.
Pops a summary: item elapsed vs. allocated, session elapsed vs. total, and items remaining — all color-coded.
Asks the AI for a diplomatic redirect script based on the current transcript. Use Copy to grab it.
Opens a capture sheet for a freeform facilitator note, saved to the Notes tab.
Capture sheet shortcut: Cmd/Ctrl+Enter saves without reaching for the mouse.
Click the microphone button or press M (when not in an input field) to start listening. A red pulsing bar appears when the mic is active.
Click the speech bubble icon in the input bar to open the live transcript. It auto-opens on first mic activation and shows every finalized utterance with a timestamp and running word count.
The dropdown in the listening bar lets you switch between EN, ES, FR, DE, PT, ZH, and JA mid-session.
Undrift listens through your microphone — it doesn't tap into video call software directly. For fully remote meetings where you want to capture all participants:
Without this setup, Undrift only hears your microphone — useful for in-person or hybrid rooms where a room mic captures everyone.
Only text — not audio. The last ~600 characters of the transcript buffer are sent with each analysis request, along with current agenda item state and timing data.
Undrift automatically analyzes the transcript against your agenda on a rolling basis. Frequency depends on sensitivity:
| Setting | Behavior |
|---|---|
| Gentle | Only flags clear, unambiguous off-topic discussion |
| Balanced | Flags moderate drift after a noticeable stretch — recommended |
| Vigilant | Flags early and often — best for tight, high-stakes sessions |
Change sensitivity at any time with the Scope slider in the top bar. The Suggest redirect button triggers an on-demand suggestion regardless of the automatic schedule.
Click End session and confirm. The report appears immediately. At the top of the report, the co-facilitator summarizes the session — below that summary, click .md to download a markdown version (pastes cleanly into Notion, email, Slack, or any doc tool) or .pdf (coming soon). Click New session to reload and start fresh. Download your report first — session data is not persisted.
| Section | Contents |
|---|---|
| Score badge | 0–100 with letter grade: Excellent / Good / Fair / Needs work |
| Scorecard | Items completed, time on-agenda %, session duration vs. planned, flags raised |
| Agenda recap | Each item with actual vs. allocated time and completion status |
| Desired outcomes | Your pre-meeting goals for reference |
| Action items | Everything logged to the Actions bucket |
| Parking lot | All parked topics |
| Facilitator notes | All notes added during the session |
Click Download .md to save a markdown version — pastes cleanly into Notion, email, Slack, or any doc tool. Click New session to reload and start fresh. Download your report first — session data is not persisted.
| Version | Change |
|---|---|
| v2.3.0-beta | FAQ page — New standalone faq.html at https://undrift.io/faq; 7 sections, 29 questions with full content; two-level accordion (sections collapse/expand independently, questions single-open globally); all sections start collapsed; template download links wire directly to downloadTemplateMd() / downloadTemplate() via mirrored inline script block. |
| v2.3.0-beta | Nav standardization — All nav bars across index.html and faq.html are now identical: Logo → How it works → Features → Who it's for → FAQ → Start free. FAQ link absolute URL; active state on faq.html; anchor links use root-relative cross-page format. |
| v2.3.0-beta | Scorecard card colors fixed — .sc-card.sc-ok, .sc-card.sc-warn, .sc-card.sc-over CSS rules added to undrift-styles.css; green/amber/red top-border now renders correctly. Also fixed a malformed .sc-card.sc-card.sc-card.sc-label chained selector preventing .sc-label from being styled. |
| v2.2.0-beta | Mobile responsive layout — Full accordion-based mobile UI at max-width 767px. Now Bar, hamburger menu, animated sections, live data mirroring, mic toggle with permission flow, tap-to-capture transcript actions. Desktop layout completely unaffected. |
| v2.2.0-beta | Dead code cleanup — Removed 25 orphaned CSS classes, 5 orphaned JS functions, stale comment placeholders. App reduced ~6KB. All mobile colors use CSS variables for automatic dark mode support. |
| v2.1.0-beta | Legal pages refactored to static HTML — Converted Terms and Privacy from JS-rendered to fully static HTML; eliminated 5 files (~1,009 lines); removed -landing.html variants; single unified page works everywhere; faster loading, better SEO, simpler maintenance. |
| v2.1.0-beta | Duration field validation — Setup screen now enforces 60-minute max on total duration field; real-time error toast appears on exceed; blocks Preflight Check button when invalid; yellow danger styling; positioned beside field. |
| v2.1.0-beta | Timecheck toast positioning fix — Moved from bottom: 70px; left: 20px to bottom: 100px; left: 300px to clear dashboard chrome; yellow styling matches brand; button active state syncs with toast visibility. |
| v2.1.0-beta | Logo file corruption fix — Renamed undrift_logo.png → undrift-logo.png (hyphen fixes MIME type); updated all references across 9 files; standardized logo size to 32×32px everywhere; removed subtitles from legal page headers. |
| v2.1.0-beta | CSP Google Fonts fix — Added https://fonts.googleapis.com to style-src and https://fonts.gstatic.com to font-src in vercel.json CSP headers. |
| v2.1.0-beta | Send button dark mode fix — Added explicit dark mode override to keep send button bright brand blue (#1A6BFF) instead of washed-out light blue in dark theme. |
| v2.1.0-beta | Header button visited state fix — Help and Feedback buttons now preserve brand blue color on :visited:hover instead of reverting to browser default purple. |
| v2.1.0-beta | Legal metadata updated — Effective Date changed from April 10 → April 22, 2026; Version updated to 2.0.0-beta.0; Open Beta Addendum rewritten for public open beta (removed confidentiality, invitation requirements, closed beta language). |
| v2.0.0-beta | Open Beta launch — Public open beta release on April 22, 2026. Free access, no gate. Success metrics: 100+ users, 50+ sessions, NPS ≥40, 99%+ uptime. |
| v1.13.3 Beta | Report polish — Report topbar replaced with inline setup-topbar pattern; Session Health label moved above score; theme toggle added; grade label color now matches score (green/blue/amber/red); all badge text changed to white for better contrast. |
| v1.11 Beta | Report export to PDF — Download .pdf button wired up in report topbar; downloadPDF() calls window.print(); @media print CSS hides beta ribbon, topbar, co-facilitator pill, nav, and dashboard chrome; report body goes full-width on print. |
| v1.11 Beta | One-click transcript capture — Inline capture buttons on every transcript line (hover-reveal); Flag, Action item, Decision, Parking lot, Note; pill-style matching action bar; pre-fills capture modal with transcript text; CAPTURE_CONFIGS lookup eliminates SVG injection in onclick; hover highlight on transcript lines. |
| v1.11 Beta | Action bar trimmed — Reduced to 4 facilitation-focused buttons: Mark complete, Time check, Suggest redirect, Add note. Capture actions moved to transcript line buttons. |
| v1.11 Beta | Security hardening — CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy headers added to vercel.json; CORS restricted from wildcard to undrift.io only; req.body validated and sanitised in proxy before forwarding to Anthropic; maxlength attributes added to all user text inputs. |
| v1.11 Beta | app.undrift.io routing fix — Host-based rewrite replaced with redirects entry; app.undrift.io now correctly redirects to undrift.io/app. |
| v1.11 Beta | CONTRIBUTING.md — Added to repo root; covers branch/PR workflow, commit format, build/deploy steps, version bump checklist, code style, file naming, bug reporting, and GitHub Issues label reference. |
| v1.10 Beta | Kit waitlist integration — double opt-in signup wired into both landing pages; Kit form fields replace Mailchimp convention; email confirmation toast added (?confirmed=1 → green glass toast, auto-dismisses 5s, URL cleaned via history.replaceState). |
| v1.10 Beta | Waitlist confirmation page — undrift-kit-confirmation.html served at /confirmed; nav and footer match index.html; Kit welcome email produced for Waitlist Welcome sequence. |
| v1.10 Beta | Logo standardized — undrift-logo.png at absolute URL replaces all inline SVG logo marks across every page and the undrift-report.js dynamic template literal; orphaned CSS gradient backgrounds and SVG rules removed. |
| v1.9 Beta | Sensitivity fix — slider ID mismatch fully resolved; SENS_LABELS declared and used throughout; session now launches correctly with all agenda data and timers. |
| v1.9 Beta | Legal pages — Terms and Privacy now available in two skins: in-app (light) at /terms and /privacy, and dark landing skin at /terms/landing and /privacy/landing. Content is managed from a single source — both skins always match. |
| v1.9 Beta | Post-launch landing page — undrift-landing-launch.html added at undrift.io/launch. Features accordion with 6 unique interactive mockup panels. Problem stats redesigned as branded cards with gradient eyebrow stripes. |
| v1.9 Beta | Landing page polish — ticker upgraded to vivid gradient borders; quote section repositioned and restyled; section order updated on both landing pages; typography bumped throughout; sourced problem stats. |
| v1.9 Beta | Report footer — standardized to v1.9 Beta · © Undrift LLC 2026 · April 11, 2026 · Terms · Privacy with "Generated by Undrift.io" bold and centered below. |
| v1.8 Beta | Bug fixes — onboarding welcome/ToS gate restored; launch button fixed (was silently failing due to a slider ID mismatch); landing page content below the hero now visible. |
| v1.8 Beta | Report download — download buttons moved into the co-facilitator pill at the top of the report. A divider separates the session summary from the download row. .md downloads immediately; .pdf is coming soon. |
| v1.8 Beta | Logo & favicon — Undrift logo now appears at all brand locations in the app and as the browser tab icon. |
| v1.8 Beta | Domain — Undrift is now live at undrift.io (landing page) and app.undrift.io (app). |
| v1.8 Beta | Legal pages added — undrift-terms.html (Terms of Service) and undrift-privacy.html (Privacy Policy) linked from app footer. |
| v1.8 Beta | Agenda template redesigned — cleaner format, inline hints for all fields, realistic example items. Parser aliases: MEETING_DURATION_MINUTES and SENSITIVITY accepted alongside original keys. |
| v1.8 Beta | Dynamic footers — all HTML doc pages now show live version and date via UNDRIFT_VERSION. Copyright updated to © Undrift 2026. |
| v1.8 Beta | Audio compatibility — Zoom, Teams, and Skype work via virtual audio device (Loopback on Mac, VB-Audio on Windows). See Section 5 for setup steps. |
| v1.7 Beta | Co-facilitator voice — contextual Undrift messages appear after agenda upload, paste & parse, on the preflight card, and at the top of the post-meeting report. |
| v1.7 Beta | Welcome / ToS gate — first-visit screen with co-facilitator greeting and clickwrap ToS acceptance. Stored in localStorage. |
| v1.7 Beta | Preflight check — session launch screen renamed and updated; co-facilitator message injected before entering the meeting room. |
For full version history (v1.0 Alpha through v1.6 Beta), see CHANGELOG.md.
Architecture, module structure, API integration, build process, and technical specifications.
Undrift is a single-file, client-side AI meeting facilitator. No backend server, no runtime build toolchain, no external JS dependencies beyond the Anthropic Messages API.
claude-sonnet-4-20250514docx npm package (documentation build only — not shipped)| File | Module | Description |
|---|---|---|
| undrift-styles.css | Styles | Design tokens, themes, layout, all component CSS including date picker |
| undrift-setup.js | M1 | Setup screen: form, date picker, upload, paste-and-parse, SESSION_DATA |
| undrift-dashboard.js | M2–M6 | Dashboard: agenda, timers, action buttons, STT, AI engine, feed cards |
| undrift-report.js | M7 | Report screen: scorecard, HTML render, markdown download |
| undrift-build.py | Build | Python script — assembles all parts into undrift-app.html, runs JS obfuscation |
| api/analyze.js | Proxy | Vercel serverless function — forwards requests to Anthropic, adds API key, enforces rate limiting |
| proxy.py | Dev | Local dev proxy — same role as api/analyze.js for local testing |
| undrift-docs.html | Docs | Combined user guide + developer docs (this file) |
| undrift-docs.css | Docs | Shared styles for documentation and feedback pages |
| undrift-docs.js | Docs | Shared JS for documentation pages — theme, version constant |
| undrift-kit-confirmation.html | Marketing | Waitlist email-verified confirmation page — served at /confirmed |
| undrift-feedback.html | Docs | Feedback submission form wired to Google Sheets |
| vercel.json | Config | Vercel routing — hostname routing, path rewrites, /confirmed, /launch, /terms/landing, /privacy/landing |
undrift-setup.js — Builds SESSION_DATA. Owns form, date picker, file upload, paste-and-parse, and screen transition to dashboard.
undrift-dashboard.js — Three-panel layout (fixed positioning), topbar, status bar, ResizeObserver, agenda navigation, live clocks.
undrift-dashboard.js — Seven buttons wired to capture sheets, feed cards, and SESSION_DATA.flags. Action bar scrolls horizontally.
undrift-dashboard.js — Web Speech API with continuous recognition, auto-restart, language switching, stt-final event pipeline.
undrift-dashboard.js — Debounced scope-check. Sends transcript context to Claude, routes structured JSON result to feed.
undrift-dashboard.js — Feed card rendering, dismiss/park/copy, filter pills, flag counter, Web Audio cues.
undrift-report.js — Scorecard calculation, report screen render, markdown download. Transitions body[data-mode] to "report".
| Function | Description |
|---|---|
| initSetup() | Bootstraps tabs, date picker (today default), default rows, theme |
| initDatePicker() | Wires display field, hidden date input, calendar icon; sets today as default |
| parseToISO(raw) | Normalizes any date string → YYYY-MM-DD; strips ordinals, falls back to JS native |
| fmtDateDisplay(iso) | Converts YYYY-MM-DD → DD-MMM-YYYY for display |
| getDateValue() | Returns current DD-MMM-YYYY string from display field for SESSION_DATA |
| launchSession() | Validates, builds SESSION_DATA, shows success card |
| goToDashboard() | Sets body[data-mode="dashboard"], calls initDashboard() |
| parseAgenda() | Calls Anthropic API to extract structure from pasted text |
| applyData(d) | Populates all form fields including date picker from parsed data |
| Function | Description |
|---|---|
| initDashboard(sd) | Receives SESSION_DATA, populates UI, starts timers |
| observeStatusbar() | ResizeObserver keeps --statusbar-h accurate for fixed layout positioning |
| renderAgendaList() | Builds sidebar with per-item timing rows (pending / active / done states) |
| jumpToItem(idx) | Stamps startedAt/endedAt, advances agenda state |
| markNextDone() | Completes active item, starts next with fresh timestamp |
| Setting | Debounce | Min words | Cooldown |
|---|---|---|---|
| Gentle (1) | 8 s | 40 words | 20 s |
| Balanced (2) | 5 s | 25 words | 20 s |
| Vigilant (3) | 3 s | 15 words | 20 s |
window.SESSION_DATA is initialized in M1 and is the single source of truth consumed by all modules.
window.SESSION_DATA = {
title: string,
date: string, // DD-MMM-YYYY e.g. "07-Apr-2026"
duration: number, // total minutes
audience: string,
facilitator: string,
aggression: 1 | 2 | 3, // Gentle | Balanced | Vigilant
aggressionLabel: string,
agenda: [{
topic: string,
minutes: number,
type: 'Discussion' | 'Decision' | 'Info share' | 'Workshop' | 'Q&A' | 'Break',
status: 'pending' | 'active' | 'done',
startedAt: number | null, // Date.now() timestamp
endedAt: number | null,
}],
outcomes: string[],
startedAt: number, // session start timestamp
endedAt: number | null,
actionItems: string[], // populated on endSession()
parkingLot: string[],
notes: string[],
flags: [{
type: 'manual-flag' | 'ai-analysis',
topic?: string, ts: number,
onTrack?: boolean, driftSeverity?: string, flagType?: string
}]
}
All API calls from the app route through /api/analyze, a Vercel serverless function that adds the API key server-side. The app never has direct access to the key. The proxy forwards the full request body to Anthropic and returns the response verbatim. Rate limiting is enforced at 20 requests per IP per 15-minute window.
Request: POST /api/analyze (from browser)
Proxy: POST https://api.anthropic.com/v1/messages (with x-api-key from env)
Response: forwarded back to browser
The API key is stored in Vercel environment variables under ANTHROPIC_API_KEY. For local development, it's read from .env.local via vercel dev.
POST https://api.anthropic.com/v1/messages
{
model: "claude-sonnet-4-20250514",
max_tokens: 1000,
system: "<dynamic prompt>",
messages: [{ role: "user", content: "<user content>" }]
}
Called once on "Parse agenda." System prompt instructs the model to return only JSON matching the agenda schema. Regex-based fallback runs if API is unavailable.
{
onTrack: boolean,
driftDetected: boolean,
driftSeverity: "none" | "mild" | "moderate" | "severe",
driftReason: string | null,
suggestRedirect: boolean,
redirectScript: string | null,
flagType: "none" | "off-topic" | "scope-creep" | "time-risk" | ...,
flagNote: string | null, // max 15 words
timeRisk: boolean,
timeRiskNote: string | null
}
All dates in Undrift are stored and displayed as DD-MMM-YYYY (e.g. 07-Apr-2026). The underlying hidden <input type="date"> stores YYYY-MM-DD and the browser's native picker handles display in the user's locale.
f-date-display — read-only text input showing DD-MMM-YYYY; clicking opens the pickerf-date-hidden — hidden type="date" input; stores YYYY-MM-DD; drives the native picker popupf-date-icon — calendar SVG button that calls hidden.showPicker()Normalizes any imported date string to YYYY-MM-DD before setting the picker. Pipeline:
YYYY-MM-DD — return as-isnew Date() — handles most written formatsImported dates from upload or paste-and-parse always go through parseToISO() → fmtDateDisplay() so the displayed date is always consistent with the picker.
Light/dark toggled via data-theme on <html>. Persisted in localStorage under key undrift_theme.
The dashboard uses position: fixed for all three layers, eliminating height-calculation bugs:
.topbar { position: fixed; top: 0; height: var(--topbar-h); }
.statusbar { position: fixed; top: var(--topbar-h); }
.layout { position: fixed; top: calc(var(--topbar-h) + var(--statusbar-h));
left: 0; right: 0; bottom: 0; }
--statusbar-h is measured live by a ResizeObserver on the statusbar element, so the layout grid always anchors correctly regardless of statusbar reflow.
body[data-mode="setup"] { min-height: 100vh; overflow-y: auto; }
body[data-mode="dashboard"] { height: 100vh; overflow: hidden; }
body[data-mode="report"] { min-height: 100vh; overflow-y: auto; }
| Property | Light | Dark | Usage |
|---|---|---|---|
| --brand | #1A6BFF | #1A6BFF | Buttons, active states, links |
| --bg | #F4F6F9 | #0D1117 | Page background |
| --surface | #FFFFFF | #161B22 | Cards and panels |
| --success | #16A34A | #16A34A | Completed items, on-time |
| --warning | #D97706 | #D97706 | Approaching limit, mild drift |
| --danger | #DC2626 | #DC2626 | Over time, severe drift |
| --purple | #7C3AED | #7C3AED | Parking lot, time alerts |
| --statusbar-h | Set by ResizeObserver | Layout top offset — never hardcode | |
python undrift-build.py
undrift-app.html is generated — do not edit it directly. Edit the source modules and rebuild.The build script automatically obfuscates the compiled JS block using javascript-obfuscator before injection. Install once with npm install -g javascript-obfuscator. If not installed, the build continues unobfuscated with a warning. All HTML-facing entry point functions are protected via --reserved-names so obfuscation never breaks runtime behavior.
ac-mymodule.js)undrift-styles.cssundrift-build.py, read the file and inject into the JS concatenation block_ENTRY_POINTS in undrift-build.pypython undrift-build.pyundrift-docs.html and README.md| Version | Change |
|---|---|
| v2.3.0-beta | FAQ page — faq.html added as standalone marketing page; two-level accordion; 7 sections, 29 questions; inline <script> mirrors _safeBlobDownload(), _TPL_CONTENT, downloadTemplateMd(), downloadTemplate() from undrift-setup.js so template links work without loading app JS. Nav updated in index.html and faq.html to include FAQ link. |
| v2.3.0-beta | Scorecard CSS fix — .sc-card.sc-ok { border-top-color: var(--success) }, .sc-card.sc-warn { border-top-color: var(--warning) }, .sc-card.sc-over { border-top-color: var(--danger) } added to undrift-styles.css; previously missing, causing all cards to render with neutral gray border. Also corrected malformed .sc-card.sc-card.sc-card.sc-label selector — was never matching, preventing .sc-label font/color rules from applying. |
| v2.2.0-beta | Mobile responsive layout — Full accordion-based mobile UI triggered at max-width 767px; isMobile() utility gates all behavioral differences; Now Bar (current item + live timer), hamburger menu (animated slide), four accordion sections (Agenda, Objectives, Live Feed, Transcript) with animated open/close via grid-template-rows; live data mirroring for feed cards, transcript lines, agenda, objectives; tap-to-expand transcript capture (Flag, Action, Decision, Parking, Note); mic toggle with getUserMedia() permission flow; report screen 2-col scorecard reflow; setup drop zone hidden after parse on mobile. Files modified: undrift-shell.html, undrift-styles.css, undrift-dashboard.js, undrift-utils.js, undrift-setup.js. |
| v2.2.0-beta | Dead code cleanup — Removed 25 orphaned CSS classes, 5 orphaned JS functions (actFlag, actParking, actLogAction, closeTimeCheck, collapseObjIfOpen), stale comment placeholders; all mobile colors converted to CSS variables for automatic dark mode; app size reduced ~6KB (249KB → 243KB). |
| v2.1.0-beta | Social preview cards — Added Open Graph and Twitter Card meta tags to index.html and undrift-shell.html; enables rich link previews when sharing undrift.io URLs on X, Facebook, LinkedIn; undrift-social-card.png (1200×630px) served from domain root; meta description tags added for improved SEO. |
| v2.0.1-beta | Visual identity refinement and critical fixes — Co-Facilitator gradient identity system implemented across all surfaces (purple #f5f3ff backgrounds, 4px gradient accent stripe, gradient pill labels, white sparkles 18×18px); CF redirect cards redesigned with premium visual hierarchy; mobile warning banner added for viewport < 1024px with localStorage persistence; session end auto-complete bug fixed (agenda item status preserved); sentiment moved to statusbar; facilitator coaching loading indicators enhanced with multi-stage progress; 12px border radius standardized across all cards; QA checklist completion (77 items verified). Files modified: undrift-shell.html, undrift-styles.css, undrift-dashboard.js, undrift-report.js, undrift-docs.html, undrift-docs.css, undrift-terms.html, undrift-privacy.html, vercel.json, all feedback forms. |
| v2.1.0-beta | Legal pages static HTML refactor — Replaced JS rendering system with static HTML; deleted 5 files: undrift-terms-content.js, undrift-privacy-content.js, undrift-legal-render.js, undrift-terms-landing.html, undrift-privacy-landing.html (~1,009 lines total); undrift-terms.html and undrift-privacy.html now fully self-contained; all content inline; no external dependencies except brand.js; faster load, better SEO, simpler maintenance. |
| v2.1.0-beta | Duration validation — Added initDurationValidation() in undrift-setup.js called from showSetupScreen() in undrift-report.js; enforces 60-minute max on duration input; real-time yellow danger toast positioned left: calc(100% + 12px); blocks Preflight Check button via isSetupValid() when value > 60; input[type=number] added to .field styling rule for proper background color. |
| v2.1.0-beta | Timecheck toast repositioning — CSS updated: bottom: 70px → 100px, left: 20px → 300px; yellow styling added via --yellow, --yellow-subtle, --yellow-border variables; timecheck button active class syncs with toast visibility; removed Dismiss button (toggle behavior). |
| v2.1.0-beta | Logo corruption fix — Root cause: undrift_logo.png served as MIME type "document" instead of "image/png"; renamed to undrift-logo.png (hyphen fixes detection); updated references in 9 files: undrift-shell.html, undrift-docs.html, undrift-feedback.html, undrift-privacy.html, undrift-terms.html, undrift-report.js, index.html, undrift-privacy-landing.html, undrift-terms-landing.html; standardized size to 32×32px everywhere. |
| v2.1.0-beta | CSP Google Fonts — Added https://fonts.googleapis.com to style-src and https://fonts.gstatic.com to font-src in vercel.json Content-Security-Policy headers. |
| v2.1.0-beta | Dark mode button fixes — Send button: added [data-theme="dark"] .btn-send override to preserve bright blue #1A6BFF; Header buttons: added :visited:hover states to preserve brand blue instead of browser default purple. |
| v2.1.0-beta | Legal metadata — Updated Effective Date from April 10 → April 22, 2026; Version from 1.0 → 2.0.0-beta.0 in both undrift-terms-content.js and undrift-privacy-content.js (before static conversion); rewrote Open Beta Addendum for public open beta (removed confidentiality clauses, invitation requirements, closed beta language). |
| v2.0.0-beta | Open Beta launch — Public open beta release. Free access, no gate. Channels: Kit.com waitlist + X/LinkedIn. Analytics tracking, NPS feedback, hotfix readiness. Success criteria: 100+ users, 50+ sessions, NPS ≥40, 99%+ uptime. |
| v1.13.3 Beta | Session health enhancements — Enhanced calcScorecard() with weighted Session Health Score (0–100). New signals: drift density, drift recovery rate, objective completion. Facilitator Coaching section in report. Full transcription recording with checkbox include in export. |
| v1.11 Beta | PDF export — downloadPDF() added; @media print block hides all screen-only chrome; beta ribbon, topbar buttons, co-facilitator pill suppressed in print output. |
| v1.11 Beta | Transcript capture refactor — CAPTURE_CONFIGS object centralises icon/title/placeholder/label data; transcriptCapture(bucket, prefill) and transcriptFlag() helpers added; openCapture() gains optional prefill param (backward compatible); transcript line hover highlight via @media CSS; .t-capture-btns pill buttons on hover. |
| v1.11 Beta | Security pass — vercel.json: security headers block added (CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy); api/analyze.js: CORS restricted to undrift.io + Vary: Origin; body validation added with safeBody field whitelist; undrift-app.html: maxlength on all text inputs. |
| v1.11 Beta | vercel.json routing fix — Host-based rewrites for app.undrift.io replaced with redirect rule; static file serving priority issue resolved. |
| v1.10 Beta | Kit integration — Kit.com form replaces Mailchimp; field names: fields[first_name], fields[last_name], email_address; honeypot removed; double opt-in configured; post-verification redirect: https://undrift.io/?confirmed=1. |
| v1.10 Beta | Email confirmation toast — #confirm-toast element added to index.html and undrift-landing-launch.html; IIFE reads URLSearchParams for confirmed=1, adds .show class, removes after 5s, calls history.replaceState to clean URL; CSS uses cubic-bezier(0.34, 1.56, 0.64, 1) spring for entry. |
| v1.10 Beta | undrift-kit-confirmation.html — new page at /confirmed; nav: fixed frosted glass, logo img, same links as index.html; footer: matches index.html exactly (Undrift LLC copy, Terms/Privacy/Contact links, hello@ entity-encoded in Contact); vercel.json route added. |
| v1.10 Beta | Logo standardized to undrift-logo.png — all HTML files and undrift-report.js template literal updated; all paths absolute (https://undrift.io/undrift-logo.png); .brand-icon and .welcome-brand-icon gradient backgrounds and orphaned svg CSS rules removed from undrift-styles.css and undrift-docs.css. |
| v1.10 Beta | hello@ obfuscated — entity-encoded in undrift-kit-confirmation.html footer Contact link. |
| v1.9 Beta | Sensitivity migration — AGG_LABELS renamed to SENS_LABELS (now declared); slider IDs corrected to f-sensitivity / sens-pill; SESSION_DATA contract carries sensitivity / sensitivityLabel only; parser map populates d.sensitivity; applyData(), initDashboard(), updateSens() all updated; resolves silent crash on session launch. |
| v1.9 Beta | Legal content modules — undrift-terms-content.js and undrift-privacy-content.js are the single source of truth for all legal text; undrift-legal-render.js shared IIFE renderer serves all 4 shell pages; landing-skin shells (undrift-terms-landing.html, undrift-privacy-landing.html) added. |
| v1.9 Beta | Legal shell paths — all script src and link href paths in legal shells changed to absolute / prefix; relative paths caused 404s under Vercel URL rewrites. |
| v1.9 Beta | vercel.json — routes added: /launch → undrift-landing-launch.html; /terms/landing → undrift-terms-landing.html; /privacy/landing → undrift-privacy-landing.html. |
| v1.9 Beta | Ticker CSS — .ticker-strip upgraded to border-image gradient; old flat var(--rim) border definition removed; single definition per page (no fallback version). Applies to both index.html and undrift-landing-launch.html. |
| v1.9 Beta | Orphaned CSS removed — undrift-landing-launch.html: .stat-n, .stat-l, .stat-src, .problem-grid, .p-card and all variants removed after problem section redesign. |
| v1.9 Beta | Zip manifest rule — files with Drive folder prefix (pm-, qa-, uat-, etc.) excluded from source zip; go in G-Drive-v[version]-[suffix].zip instead. |
| v1.8 Beta | Onboarding gate fix — handleTosChange(), enterApp(), showWelcomeScreen(), showSetupScreen() added; startup router replaces bare initSetup() call with localStorage.getItem('undrift_tos_accepted') check. |
| v1.8 Beta | Launch button fix — slider HTML IDs corrected: f-sensitivity / sens-pill in HTML now match JS; resolves null ref TypeError in launchSession() and applyData(). |
| v1.8 Beta | Domain routing — vercel.json updated with has/host hostname conditions: undrift.io → index.html, app.undrift.io → undrift-app.html, www.undrift.io → 301 to apex. /app fallback route added. undrift-landing.html renamed to index.html. |
| v1.8 Beta | Report download restructure — .cf-voice pill extended with .cf-voice-body flex column, .cf-voice-divider, and .cf-voice-footer row housing CTA label + .md/.pdf buttons. Download .md removed from report topbar. |
| v1.8 Beta | Logo — undrift-logo.png replaces inline SVGs at all 4 brand icon locations. Favicon added via <link rel="icon">. |
| v1.5 | JS obfuscation — javascript-obfuscator added to build pipeline. All JS obfuscated as one unit before injection. Entry points protected via --reserved-names. Graceful fallback if tool not installed. |
| v1.5 | Rate limiting — in-memory IP rate limiting added to api/analyze.js (20 req/IP/15 min) and proxy.py (60 req/IP/min). Returns 429 with Retry-After header. |
| v1.5 | Combined docs — user guide and developer docs merged into single undrift-docs.html with fixed header, tab bar, scrollable sidebar+content, and fixed footer. |
| v1.2 | Vercel proxy — api/analyze.js serverless function routes all API calls server-side. Fetch URLs changed from https://api.anthropic.com/v1/messages to /api/analyze in both undrift-setup.js and undrift-dashboard.js. Fixes CORS errors from file:// origin. |
| v1.2 | Feedback form — undrift-feedback.html styled feedback page wired to Google Forms/Sheets. |
| v1.2 | M5 engine improvements — DEBOUNCE now 6/4/2s, COOLDOWN per-sensitivity 12/8/5s, MIN_WORDS measures new words since last analysis, buildUser() separates RECENT SPEECH from EARLIER CONTEXT. |
| v1.2 | parseTemplate fix — now skips <!-- HTML comment --> lines in addition to # comments. |
| v1.2 | Deployment infrastructure — vercel.json, .env.example, .gitignore, DEPLOYMENT.md, proxy.py added to repo. |
| v1.1 | Template format — Agenda template switched from .docx to .md. Accepted upload types: .md, .txt, .csv, .json. |
| v1.1 | Date picker — setup form date field replaced with display/hidden/icon picker pattern. All imported dates normalized to YYYY-MM-DD via parseToISO(). |
| v1.1 | Layout fix — dashboard layout switched to position: fixed anchoring. Eliminates gray dead zone and content clipping. |
| v1.0 | Initial release — session setup, live AI scope-check, 7 action buttons, STT, feed cards, end-of-meeting report. |
For full version history, see CHANGELOG.md.