The meeting export feature went through three complete redesigns. The first was a text dump. The second was an HTML report that looked nice but contained unusable content. The third — which ships today — uses Gemini to generate a professionally structured meeting report with proper Korean business writing conventions, decision tables, and action item tracking. The journey from dump to document is worth documenting in full.
Version 1: The Text Dump (And Why "Export" ≠ "Useful")
The first export feature was a single button that collected this.data.fullTranscript and dumped it to a .txt file. Every utterance, in order, with timestamps. Something like:
[09:32:15] API 연동 부분에서 에러가 발생하고 있어요.
[09:32:28] 어떤 에러인지 확인했나요?
[09:32:41] 400 에러인데 아직 원인을 모르겠어요.
[09:33:02] 로그 한번 공유해줄 수 있어요?
This is what people said, in order. It's useful if you need a verbatim record. It's completely useless for the common need: "I need to send the team a summary of what we decided." Real meeting documentation requires extracting signal from noise. A 45-minute meeting generates 15-20 pages of raw transcript. Nobody reads 15 pages. They need decisions highlighted, action items listed, key discussion points summarized.
We knew the text dump was insufficient. But it was better than nothing and shipped fast. The commit "feat: add Meeting Export functionality" represents this version.
Version 2: Template-Based HTML Report
The second version generated a styled HTML report from a template. We defined sections: Meeting Overview, Key Points, Questions & Answers, Full Transcript. The template looked professional. The content was still raw: key points were extracted using simple regex for question-like sentences, Q&A was just the literal question and AI answer pairs from the session, full transcript was the same dump as before but in a pretty box.
We shipped it and used it ourselves. The verdict: it looked like a real meeting report until you read it. The "key points" section extracted questions because our regex pattern treated sentences ending in "?" as important, which meant: "Should we get lunch soon?" appeared as a key meeting decision point alongside "We need to implement proper rate limiting before GA."
The UI for this version had an Export button that showed a dropdown: "Download as Text," "Download as HTML," "Generate AI Summary." Having three options caused decision paralysis — users weren't sure which one they needed. The commit "fix: implement showExportMenu and exportMinutes methods" covers our attempt to simplify this. We eventually replaced the dropdown with a single smart button.
The Prompt Engineering Challenge for Professional Reports
Version 3 uses Gemini to write the entire report. This required solving a prompt engineering problem: how do you instruct an AI to produce output in a specific professional format, in Korean, using the correct formal register, without including preamble or explanation?
Korean business meeting minutes have a specific style called 개조식 (gaejojeok) — a concise, nominalized writing style using sentence endings like "~함," "~하였음," "~임" instead of the polite "~습니다" form. This is standard for formal Korean business documentation. Getting Gemini to produce this style reliably required explicit instruction in the prompt:
**작성 지침 (필수 준수):**
1. 문체: '~함', '~하였음', '~임' 등 개조식 종결 어미를 사용할 것 (~습니다 사용 금지).
2. 강조: 마크다운 강조 기호(**) 사용을 최소화하여 가독성을 높일 것.
3. 형식: 결정 사항과 실행 과제는 반드시 마크다운 표 형식을 사용할 것.
4. 구조:
## 1. 회의 개요
## 2. 주요 논의 사항
## 3. 결정 사항 (표 형식: 항목 | 내용 | 비고)
## 4. 향후 실행 과제 (표 형식: 과제명 | 담당자 | 기한)
## 5. 핵심 키워드 (#태그)
The "do not use ~습니다" instruction was necessary because Gemini's default Korean output uses polite form endings, which are correct for conversational AI but wrong for formal minutes. Without this instruction, roughly 40% of sentences would use the wrong register. With it, the compliance rate is near 100%.
The "minimize ** markdown emphasis" instruction addressed a different problem: Gemini heavily uses bold text (**bold**) for emphasis, which looks fine in a markdown renderer but is distracting when the output is displayed in the app's HTML export. We found that instructing Gemini to minimize markdown emphasis produced cleaner reports.
The Table Rendering Problem
Version 3 requests markdown tables for decisions and action items. The generated markdown looks like:
| 과제명 | 담당자 | 기한 |
|--------|--------|------|
| API 에러 로그 분석 | 이팀장 | 2026년 2월 21일 |
| 수정 사항 스테이징 배포 | 김팀원 | 2026년 2월 22일 |
But our export target is HTML. Rendering markdown tables in HTML required either a markdown-to-HTML parser (which we didn't want to add as a dependency) or custom table rendering logic. The MeetingExporter module now includes a lightweight markdown table renderer: it splits on | delimiters, identifies header rows by checking for the --- separator row, and wraps them in proper <table><thead><tbody> structure.
This handles the common table patterns Gemini produces reliably. It doesn't handle all markdown — blockquotes, nested lists, code blocks in minutes — but meeting minutes don't need those. A narrow parser that handles the specific patterns you use is better than a full markdown library with edge cases you'll never hit.
Export UX: From Three Buttons to One Smart Action
The final UX decision was collapsing the export options to a single action. When the user clicks Export:
- Show a toast: "AI is generating a refined meeting report..."
- Call Gemini to produce the full formatted report.
- Generate and download an HTML file with the report rendered.
The HTML file is self-contained: inline CSS, the meeting report content, and the full transcript in a collapsible section at the bottom. Recipients can open it in any browser without needing any external dependencies. The filename includes the meeting title and date: VORA_Report_2026-02-18.html.
The audio recording export (the captured microphone audio) is a separate button that's only enabled after recording stops. Keeping these separate avoids the confusion of "which format should I choose" — the meeting minutes and the audio recording are different artifacts with different use cases.
What's Still Missing
The honest answer about what Version 3 still doesn't do well: it doesn't extract assignee names from the transcript. The action items table has a "담당자 (Assignee)" column, but if the meeting transcript doesn't explicitly mention who's responsible for what, Gemini fills in placeholders or omits the field. We don't have speaker identification (as discussed in our earlier post), so there's no way to automatically attribute tasks to specific people.
The solution we're considering: a pre-export flow where the user can input participant names, which are then injected into the Gemini prompt as context. This would let Gemini make educated guesses about assignees based on the meeting discussion. But it adds friction to what should be a fast one-click action. We're still evaluating the tradeoff. For now, export works excellently for meeting content, and users manually fill in assignees in the downloaded report.