The commit message says it plainly: "Revamp UI with modern Dark Theme & Glassmorphism." What it doesn't say is that this was the third complete UI overhaul, that it happened because early user feedback was politely but clearly telling us the app looked unfinished, and that we spent more time arguing about the equalizer animation than any reasonable engineers should.
This is the story of how VORA's visual design evolved from a functional-but-ugly data dashboard into something that users actually compliment — and the specific technical and design decisions along the way.
Version 1: The Bootstrap-Era Dashboard
The first UI was built with one goal: put the functional elements on screen fast. Recording button, transcript area, statistics panel, settings. It worked. It was extremely ugly. The color scheme was default Bootstrap blue-and-white. The layout was a single-column flex container with padding that wasn't quite right. Text sizes were inconsistent. There was no visual hierarchy distinguishing recording state from idle state.
It felt like every other "AI tool" demo built by engineers who know how to train models but have never opened Figma. Functional. Joyless.
The first piece of feedback we got externally was: "Is this finished?" It was finished — it was a complete, working product. The UI was communicating "prototype" when the functionality was "product."
Version 2: Attempting to Polish the Wrong Foundation
Rather than rebuilding, we tried to polish Version 1. We added more padding. We made the fonts slightly larger. We added a status indicator that pulsed. We added color to the recording button.
This was a mistake. Small improvements on a bad foundation produce something that looks like a bad foundation with lipstick. The fundamental structural problem — a layout that didn't communicate the product's personality and capabilities — wasn't fixed by padding adjustments.
The commit "Update UI to v4.0 and add Smart Meeting Summary" covers this period. The v4.0 version number was optimistic. What we shipped was a slightly cleaner version of the same design problems.
The Decision to Rebuild
The commitment to a full redesign came from looking at apps in our space that had earned professional credibility: Notion, Linear, Vercel's dashboard, Loom. All of them use dark themes with carefully calibrated panel layers, precise typography scale, and motion that conveys system state rather than just looking animated. They look like tools built by people who take their craft seriously.
We identified the specific design choices that differentiated them from typical web apps:
- Dark backgrounds with layered depth: Not just dark gray everywhere, but a deliberate hierarchy:
#0f172a(page background) →#1e293b(panel background) →rgba(255,255,255,0.04)(card lift). Each layer is slightly lighter, creating spatial depth without explicit shadows. - Glass morphism for floating elements: Backdrop blur on the header and modals. This creates the visual impression that UI elements float above the content rather than being part of it.
backdrop-filter: blur(10px)with a semi-transparent background. - Indigo as the accent color: Not red or blue or green — indigo (
#6366f1) is the signature color of sophisticated SaaS tools. It's neutral enough to not clash with data visualization colors, vivid enough to communicate active states clearly. - Typography that scales intentionally: Noto Sans KR for Korean support with 9 weight levels. Heading weights at 900, body at 400, metadata at 300. The weight contrast communicates information hierarchy without color changes.
The Equalizer Animation Argument
Every team has a feature that becomes a proxy fight for deeper design disagreements. For us, it was the voice visualizer. The equalizer bars that animate during recording turned into a two-week engineering and design argument that consumed probably 30% of the redesign time.
The first implementation showed flat bars while idle and random-height bars while recording. Ugly. The second implementation used random animation even while idle. We shipped it. Someone pointed out that having animation while not recording was confusing — users thought it was responding to audio when it wasn't. We removed the idle animation.
The third implementation used actual FFT data from the AudioContext analyser. The bars responded to real voice frequency content. When a man spoke, the lower frequency bins lit up. When the microphone picked up keyboard noise, you could see it. This was the technically correct implementation and it looked genuinely impressive. One engineer loved it. Another thought it was "too much" and distracted from reading the transcript.
The fourth implementation (which ships today) combines real FFT data with a sine wave offset per bar:
// The final visualizer design
const wave = Math.sin(time * 10 + i * 0.8) * 0.5 + 0.5;
const baseHeight = 8; // minimum height
const dynamicHeight = audioValue * 25 + wave * 10;
const finalHeight = Math.min(Math.max(baseHeight + dynamicHeight, baseHeight), 40);
bar.style.height = `${finalHeight}px`;
bar.style.opacity = 0.5 + (audioValue * 0.5);
The sine wave adds organic motion even when audio input is low, preventing the bars from looking stuck or dead. The real audio value modulates the amplitude, so louder speech produces more vigorous animation. The clamping (Math.max(baseHeight) and Math.min(40px)) prevents extreme values from breaking the layout. This turned out to be the version that everyone agreed looked right. The commit "improve equalizer animation with frequency data and fix audio export" marks this decision.
The 3-Column Grid That Changed Everything
The most impactful layout decision was moving from a 2-column to a 3-column grid. In the 2-column layout, the transcript occupied the left column and all AI panels (Q&A, summary) shared the right column. The right column was cramped; users couldn't see meeting summary and Q&A simultaneously without scrolling.
The 3-column grid gives transcript, AI chat, and meeting summary each their own dedicated space. This mirrors how a professional note-taker works during a meeting: they simultaneously capture the flow of conversation, note decisions and action items, and track the overall narrative arc. The three-column layout makes these three activities visually distinct and simultaneously visible.
The CSS Architecture Problem We Had to Solve
There's a commit in the history: "restore corrupted CSS file and correctly apply AI correction styles." This represents a day we would rather forget. During the v4.0 redesign push, we had two developers editing the CSS file simultaneously. A merge conflict resulted in a file that passed syntax validation but had some properties applying to the wrong selectors. Specifically, the AI correction badge style (the ✨ indicator) was applying to all transcript items, making everything appear to have been AI-corrected regardless of whether it had.
The root cause was that our CSS file had become a 3,000-line monolith with minimal commenting and heavily nested selectors. The fix was both the immediate bug fix and a structural reorganization: CSS custom properties for all design tokens, BEM-like naming for component selectors, and section headers. The file became maintainable again.
If you're reading this and building a single-page app without a CSS framework or preprocessor: the discipline of CSS custom properties (variables) for design tokens is worth it from day one. The time we spent on the cascade debugging far exceeded what structured CSS would have cost upfront.
The Visual Result and What We Measure
The redesigned VORA is the product we intended to build. The dark glassmorphism aesthetic communicates sophistication without screaming for attention. The 3-column layout communicates capability. The recording state animations communicate system status without ambiguity. The typography scale communicates information hierarchy.
Do we have formal user research data proving this? Not beyond anecdotal feedback. What we have is: the question "Is this finished?" stopped appearing in feedback. People started describing VORA as "sleek" and "professional" rather than "functional." The visual design stopped being a conversation topic and started being invisible — which is the goal. Good UI becomes invisible. Bad UI makes itself felt.
The dark theme redesign wasn't about aesthetics for aesthetics' sake. It was about building a UI that communicated that we take the product seriously, so users take it seriously too. First impressions determine whether someone explores the features or closes the tab. We learned that the hard way.