docs: refresh README and GitHub Pages for v0.2.1

Sync project documentation with the current v0.2.1 implementation
(Tap-to-toggle recording, 5-step onboarding, Flow session model,
SpeechAnalyzer-only local engine, deepseek-v4-flash default).

README.md / README.zh.md
- Replace 'press-and-hold / 按住说话' with the v0.2.0+ tap-to-toggle
  interaction; add the 60-second per-take cap to feature bullets.
- Update 3-step onboarding to the real 5-step flow.
- Correct architecture diagram: AudioCaptureService in the extension
  is legacy/unused, PolishingService lives in OSGKeyboardShared, and
  the FlowSession* / LiveDictation* services are now in the tree.
- Replace the legacy single-pipeline data flow with the actual Flow
  session data flow (keyboard -> App Group -> host app -> chunked
  ASR -> LLM polish -> App Group -> insertText).
- Move the stale 'main -> 0.2 branch rename' banner into a project
  status section under the new 'v0.2.1' badge.
- Expand 'Known limitations' with 60s/3min caps, 60MB sandbox note,
  URL scheme caveat, and the v0.2.0->v0.2.1 on-device LLM rollback.
- Add a 'Development' section pointing to tests, CI, logging policy.
- Add version badge, license link, privacy policy link.

docs/index.html (GitHub Pages landing)
- Mirror the same copy fixes in both EN and ZH i18n tables
  (verified: 50 keys each, no missing translations).
- Grow feature grid from 6 to 8 cards (add 'Flow session' and
  'Local + cloud polish'), grow steps from 3 to 5.
- Bump footer to 'v0.2.1 · source available, non-commercial',
  add License link.

docs/privacy.html + docs/privacy/index.html
- Update 'Last updated' to July 3, 2026, tag v0.2.1.
- Add explicit iOS 26+ requirement, Flow session explanation,
  children's privacy section, policy-changes section, license
  reference, and rocky.hk@gmail.com contact.
- Make the 'no raw audio upload to any server' claim explicit.

Verification
- grep confirms no leftover 'press and hold' / '按住' / 'press to'.
- HTML structure validated (well-formed on all three pages).
- EN/ZH i18n keys are symmetric (50 each).
This commit is contained in:
Mavis
2026-07-03 05:25:55 +00:00
parent dc9697bf3d
commit 2e6e70247a
5 changed files with 427 additions and 339 deletions
+114 -52
View File
@@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>OSGKeyboard — Voice dictation keyboard for iOS</title>
<meta name="description" content="OSGKeyboard — hold to talk, release to insert AI-polished text in any app. On-device speech recognition, bring-your-own LLM.">
<meta name="description" content="OSGKeyboard — tap to start, tap to stop. AI-polished text in any app. On-device speech recognition (iOS 26+), bring-your-own LLM, source available.">
<meta name="theme-color" content="#0A0A0B">
<link rel="icon" href="assets/app-icon.png" type="image/png">
<link rel="apple-touch-icon" href="assets/app-icon.png">
@@ -399,6 +399,7 @@
background: radial-gradient(circle at 30% 30%, #5fd080, var(--accent) 55%, #2a7a45);
box-shadow: 0 0 0 10px var(--accent-muted), 0 12px 28px var(--accent-glow);
animation: pulse 2.4s ease-in-out infinite;
position: relative;
}
@keyframes pulse {
@@ -406,6 +407,22 @@
50% { transform: scale(1.04); }
}
/* Pulsing recording rings overlay for the keyboard mock */
.kb-mic::after {
content: "";
position: absolute;
inset: -6px;
border-radius: 50%;
border: 2px solid var(--accent);
opacity: 0;
animation: ring 2.4s ease-out infinite;
}
@keyframes ring {
0% { transform: scale(0.9); opacity: 0.55; }
100% { transform: scale(1.6); opacity: 0; }
}
.phone-glow {
position: absolute;
inset: 10% 5% auto;
@@ -483,12 +500,16 @@
.steps {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
grid-template-columns: repeat(5, 1fr);
gap: 0.8rem;
counter-reset: step;
}
@media (max-width: 760px) {
@media (max-width: 1080px) {
.steps { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
.steps { grid-template-columns: 1fr; }
}
@@ -597,10 +618,10 @@
<section class="hero">
<div class="section-inner hero-grid">
<div>
<div class="eyebrow"><span class="eyebrow-dot"></span><span data-i18n="hero.eyebrow">Open source · iOS 26+</span></div>
<h1 data-i18n="hero.title">Hold to talk.<br>Polished text in any app.</h1>
<div class="eyebrow"><span class="eyebrow-dot"></span><span data-i18n="hero.eyebrow">Source available · iOS 26+</span></div>
<h1 data-i18n="hero.title">Tap to talk.<br>Polished text in any app.</h1>
<p class="hero-lead" data-i18n="hero.lead">
A custom keyboard that transcribes your voice on-device and optionally polishes the result with the LLM you configure WeChat, Notes, Mail, ChatGPT, and everywhere else you type.
A custom keyboard that transcribes your voice on-device and optionally polishes the result with the LLM you configure. Works in WeChat, Notes, Mail, ChatGPT everywhere you type. Up to 60 seconds per take, with a long-lived Flow session so you never bounce back to the host app.
</p>
<div class="hero-cta">
<a class="btn btn-primary" href="https://github.com/hkgood/OSGKeyboard" data-i18n="hero.cta.primary">View on GitHub</a>
@@ -610,6 +631,7 @@
<span class="badge" data-i18n="hero.badge1">On-device ASR</span>
<span class="badge" data-i18n="hero.badge2">Bring your own API</span>
<span class="badge" data-i18n="hero.badge3">Zero dependencies</span>
<span class="badge" data-i18n="hero.badge4">Flow session · 60s / take</span>
</div>
</div>
@@ -649,8 +671,8 @@
<div class="features">
<article class="feature-card">
<div class="feature-icon" aria-hidden="true">🎙</div>
<h3 data-i18n="features.f1.title">Push-to-talk</h3>
<p data-i18n="features.f1.body">Press and hold the mic key, speak naturally, release — polished text lands at your cursor.</p>
<h3 data-i18n="features.f1.title">Tap-to-toggle, 60s cap</h3>
<p data-i18n="features.f1.body">Tap the mic to start, speak naturally, tap again to stop. A live countdown keeps you honest at 60 seconds per take.</p>
</article>
<article class="feature-card">
<div class="feature-icon" aria-hidden="true">🧠</div>
@@ -677,6 +699,16 @@
<h3 data-i18n="features.f6.title">Lean & native</h3>
<p data-i18n="features.f6.body">Pure Swift 6 and SwiftUI — no CocoaPods, no Carthage, no third-party packages.</p>
</article>
<article class="feature-card">
<div class="feature-icon" aria-hidden="true">🔁</div>
<h3 data-i18n="features.f7.title">Flow session</h3>
<p data-i18n="features.f7.body">A long-lived host-app session keeps the recorder warm. Record many takes without bouncing back to the app.</p>
</article>
<article class="feature-card">
<div class="feature-icon" aria-hidden="true">🧩</div>
<h3 data-i18n="features.f8.title">Local + cloud polish</h3>
<p data-i18n="features.f8.body">Local mode is ASR-only. Enable cloud polish to route the transcript through your chosen LLM when iOS speech recognition isn't strong enough.</p>
</article>
</div>
</div>
</section>
@@ -689,16 +721,24 @@
</div>
<div class="steps">
<article class="step-card">
<h3 data-i18n="steps.s1.title">Enable the keyboard</h3>
<p data-i18n="steps.s1.body">Install from source, turn on OSGKeyboard in iOS Settings, and allow Full Access for mic + your API.</p>
<h3 data-i18n="steps.s1.title">Open the app</h3>
<p data-i18n="steps.s1.body">Build from source and launch. The 5-step onboarding starts the Flow session automatically once permissions are granted.</p>
</article>
<article class="step-card">
<h3 data-i18n="steps.s2.title">Hold the mic</h3>
<p data-i18n="steps.s2.body">Switch to OSGKeyboard in any text field, press and hold the circular record button, and speak.</p>
<h3 data-i18n="steps.s2.title">Allow mic & speech</h3>
<p data-i18n="steps.s2.body">Grant microphone and on-device speech recognition access when prompted. Both stay on-device.</p>
</article>
<article class="step-card">
<h3 data-i18n="steps.s3.title">Release to insert</h3>
<p data-i18n="steps.s3.body">On-device transcription runs instantly; optional LLM polish returns clean text right where you type.</p>
<h3 data-i18n="steps.s3.title">Enable the keyboard</h3>
<p data-i18n="steps.s3.body">In iOS Settings, add OSGKeyboard and allow Full Access so it can use the mic and your API.</p>
</article>
<article class="step-card">
<h3 data-i18n="steps.s4.title">Pick engine + API</h3>
<p data-i18n="steps.s4.body">Choose local ASR or cloud. For cloud polish, paste any OpenAI-compatible key (DeepSeek works out of the box).</p>
</article>
<article class="step-card">
<h3 data-i18n="steps.s5.title">Tap to talk</h3>
<p data-i18n="steps.s5.body">Switch to OSGKeyboard in any text field, tap the mic, speak (up to 60s), tap again. Polished text lands at your cursor.</p>
</article>
</div>
</div>
@@ -719,11 +759,13 @@
<footer class="footer">
<div class="footer-inner">
<span data-i18n="footer.copy">© OSGKeyboard source available</span>
<span data-i18n="footer.copy">© OSGKeyboard · v0.2.1 · source available, non-commercial</span>
<span>
<a href="https://github.com/hkgood/OSGKeyboard" data-i18n="footer.source">Source code</a>
·
<a href="privacy/" data-i18n="footer.privacy">Privacy</a>
·
<a href="https://github.com/hkgood/OSGKeyboard/blob/main/LICENSE" data-i18n="footer.license">License</a>
</span>
</div>
</footer>
@@ -733,86 +775,106 @@
en: {
"nav.github": "GitHub",
"hero.eyebrow": "Source available · iOS 26+",
"hero.title": "Hold to talk.<br>Polished text in any app.",
"hero.lead": "A custom keyboard that transcribes your voice on-device and optionally polishes the result with the LLM you configure WeChat, Notes, Mail, ChatGPT, and everywhere else you type.",
"hero.title": "Tap to talk.<br>Polished text in any app.",
"hero.lead": "A custom keyboard that transcribes your voice on-device and optionally polishes the result with the LLM you configure. Works in WeChat, Notes, Mail, ChatGPT everywhere you type. Up to 60 seconds per take, with a long-lived Flow session so you never bounce back to the host app.",
"hero.cta.primary": "View on GitHub",
"hero.cta.secondary": "Privacy Policy",
"hero.badge1": "On-device ASR",
"hero.badge2": "Bring your own API",
"hero.badge3": "Zero dependencies",
"hero.badge4": "Flow session · 60s / take",
"mock.title": "Notes",
"mock.sub": "OSGKeyboard active",
"mock.sub": "OSGKeyboard active · Flow session",
"mock.text": "Tomorrow at 3 PM, sync with the design team on the new onboarding flow. Send the draft before lunch.",
"features.title": "Built for real typing workflows",
"features.subtitle": "Native SwiftUI, privacy-first architecture, and a Typeless-style push-to-talk experience.",
"features.f1.title": "Push-to-talk",
"features.f1.body": "Press and hold the mic key, speak naturally, release — polished text lands at your cursor.",
"features.subtitle": "Native SwiftUI, privacy-first architecture, and a tap-to-toggle Flow session model.",
"features.f1.title": "Tap-to-toggle, 60s cap",
"features.f1.body": "Tap the mic to start, speak naturally, tap again to stop. A live countdown keeps you honest at 60 seconds per take.",
"features.f2.title": "On-device ASR",
"features.f2.body": "Speech stays on your iPhone. Apple's on-device speech stack handles transcription — audio never leaves the device.",
"features.f2.body": "Speech stays on your iPhone. Apple's iOS 26 SpeechAnalyzer + DictationTranscriber handle transcription — audio never leaves the device.",
"features.f3.title": "AI polish",
"features.f3.body": "Optional cloud pass adds punctuation, structure, and clarity. Only the transcript is sent — not your voice.",
"features.f4.title": "Bring your own API",
"features.f4.body": "Works with any OpenAI-compatible endpoint: OpenAI, DeepSeek, Qwen DashScope, or your own server.",
"features.f4.body": "Works with any OpenAI-compatible endpoint: OpenAI, DeepSeek, Qwen DashScope, Moonshot, Zhipu, or your own server.",
"features.f5.title": "Privacy first",
"features.f5.body": "No ordinary keystroke logging. You choose when cloud polish runs and which provider receives text.",
"features.f6.title": "Lean & native",
"features.f6.body": "Pure Swift 6 and SwiftUI — no CocoaPods, no Carthage, no third-party packages.",
"steps.title": "How it works",
"steps.subtitle": "Three gestures between thought and sent message.",
"steps.s1.title": "Enable the keyboard",
"steps.s1.body": "Install from source, turn on OSGKeyboard in iOS Settings, and allow Full Access for mic + your API.",
"steps.s2.title": "Hold the mic",
"steps.s2.body": "Switch to OSGKeyboard in any text field, press and hold the circular record button, and speak.",
"steps.s3.title": "Release to insert",
"steps.s3.body": "On-device transcription runs instantly; optional LLM polish returns clean text right where you type.",
"features.f7.title": "Flow session",
"features.f7.body": "A long-lived host-app session keeps the recorder warm. Record many takes without bouncing back to the app.",
"features.f8.title": "Local + cloud polish",
"features.f8.body": "Local mode is ASR-only. Enable cloud polish to route the transcript through your chosen LLM when iOS speech recognition isn't strong enough.",
"steps.title": "Get started in five steps",
"steps.subtitle": "From clone to first polished message — about three minutes.",
"steps.s1.title": "Open the app",
"steps.s1.body": "Build from source and launch. The 5-step onboarding starts the Flow session automatically once permissions are granted.",
"steps.s2.title": "Allow mic & speech",
"steps.s2.body": "Grant microphone and on-device speech recognition access when prompted. Both stay on-device.",
"steps.s3.title": "Enable the keyboard",
"steps.s3.body": "In iOS Settings, add OSGKeyboard and allow Full Access so it can use the mic and your API.",
"steps.s4.title": "Pick engine + API",
"steps.s4.body": "Choose local ASR or cloud. For cloud polish, paste any OpenAI-compatible key (DeepSeek works out of the box).",
"steps.s5.title": "Tap to talk",
"steps.s5.body": "Switch to OSGKeyboard in any text field, tap the mic, speak (up to 60s), tap again. Polished text lands at your cursor.",
"privacy.title": "Privacy at a glance",
"privacy.body": "Audio is processed on your device. We do not log ordinary keystrokes. In cloud polish mode, only transcribed text — never audio — goes to the API provider you configure.",
"privacy.cta": "Read full policy",
"footer.copy": "© OSGKeyboard source available",
"footer.copy": "© OSGKeyboard · v0.2.1 · source available, non-commercial",
"footer.source": "Source code",
"footer.privacy": "Privacy"
"footer.privacy": "Privacy",
"footer.license": "License"
},
zh: {
"nav.github": "GitHub",
"hero.eyebrow": "源码可见 · 需要 iOS 26+",
"hero.title": "按说话,<br>任意 App 里获得润色文字。",
"hero.lead": "自定义键盘扩展:在设备端转写语音,并可选通过你配置的 LLM 润色结果。适用于微信、备忘录、邮件、ChatGPT 等所有出现键盘的场景。",
"hero.title": "按说话,<br>任意 App 里获得润色文字。",
"hero.lead": "自定义键盘扩展:在设备端转写语音,并可选通过你配置的 LLM 润色结果。适用于微信、备忘录、邮件、ChatGPT 等所有出现键盘的场景。单次录音上限 60 秒,配合长生命周期的 Flow 会话,多次录音无需反复跳回主 App。",
"hero.cta.primary": "GitHub 仓库",
"hero.cta.secondary": "隐私政策",
"hero.badge1": "设备端语音识别",
"hero.badge2": "自带 API",
"hero.badge3": "零第三方依赖",
"hero.badge4": "Flow 会话 · 单次 60s",
"mock.title": "备忘录",
"mock.sub": "OSGKeyboard 已启用",
"mock.sub": "OSGKeyboard 已启用 · Flow 会话",
"mock.text": "明天下午三点和设计团队同步新引导流程,午饭前把草稿发过去。",
"features.title": "为真实输入场景设计",
"features.subtitle": "原生 SwiftUI、隐私优先架构,以及 Typeless 风格的按住说话体验。",
"features.f1.title": "按住说话",
"features.f1.body": "按住麦克风键自然说话,松手后润色文字直接插入光标位置。",
"features.subtitle": "原生 SwiftUI、隐私优先架构,以及点按切换的 Flow 会话模型。",
"features.f1.title": "点按录音 · 单次 60 秒",
"features.f1.body": "点一下麦克风开始说话,再点一下结束。60 秒倒计时实时显示,长按也不会被卡住。",
"features.f2.title": "设备端转写",
"features.f2.body": "语音留在 iPhone 本地处理,由系统端侧语音能力完成转写,音频不会上传。",
"features.f2.body": "语音留在 iPhone 本地处理,由 iOS 26 SpeechAnalyzer + DictationTranscriber 完成转写,音频不会上传。",
"features.f3.title": "AI 润色",
"features.f3.body": "可选云端润色,自动补全标点与结构。仅发送转写文字,不发送录音。",
"features.f4.title": "自带 API",
"features.f4.body": "兼容 OpenAI 风格接口:OpenAI、DeepSeek、通义 DashScope 或自建服务均可。",
"features.f4.body": "兼容 OpenAI 风格接口:OpenAI、DeepSeek、通义 DashScope、Moonshot、智谱 或自建服务均可。",
"features.f5.title": "隐私优先",
"features.f5.body": "不记录普通击键。是否启用云端润色、发给哪家服务商,完全由你决定。",
"features.f6.title": "轻量原生",
"features.f6.body": "纯 Swift 6 + SwiftUI 实现,无 CocoaPods、无 Carthage、无第三方包。",
"steps.title": "如何使用",
"steps.subtitle": "三个步骤,从想法到可发送的文字。",
"steps.s1.title": "启用键盘",
"steps.s1.body": "从源码安装后,在 iOS 设置中启用 OSGKeyboard,并允许完全访问(麦克风与 API 所需)。",
"steps.s2.title": "按住麦克风",
"steps.s2.body": "在任意输入框切换到 OSGKeyboard,按住圆形录音键开始说话。",
"steps.s3.title": "松手插入",
"steps.s3.body": "设备端即时转写;若开启润色,LLM 返回整洁文字并插入当前光标处。",
"features.f7.title": "Flow 会话",
"features.f7.body": "主 App 维持长生命周期录音会话,多次录音无需跳回主 App,体验更连贯。",
"features.f8.title": "本地 + 云端润色",
"features.f8.body": "本地模式仅做 ASR;当 iOS 识别效果不理想时,可一键开启云端润色走你配置的 LLM。",
"steps.title": "五步上手",
"steps.subtitle": "从克隆到发出第一条润色消息,约 3 分钟。",
"steps.s1.title": "打开 App",
"steps.s1.body": "从源码编译运行 App,权限齐全后 5 步引导会自动启动 Flow 会话。",
"steps.s2.title": "授权麦克风与语音",
"steps.s2.body": "按提示授予麦克风与端侧语音识别权限,二者均在设备端处理。",
"steps.s3.title": "启用键盘",
"steps.s3.body": "在 iOS 设置中添加 OSGKeyboard,并允许完全访问(麦克风与 API 所需)。",
"steps.s4.title": "选择引擎与 API",
"steps.s4.body": "选择本地或云端引擎;云端润色需粘贴 OpenAI 兼容 KeyDeepSeek 开箱即用)。",
"steps.s5.title": "点按说话",
"steps.s5.body": "在任意输入框切换到 OSGKeyboard,点麦克风开始(上限 60 秒),再点结束,文字自动插入光标。",
"privacy.title": "隐私摘要",
"privacy.body": "音频在设备端处理。我们不记录普通击键。云端润色模式下,仅转写文字(非音频)会发送到你配置的 API 服务商。",
"privacy.cta": "查看完整政策",
"footer.copy": "© OSGKeyboard · 源码可见",
"footer.copy": "© OSGKeyboard · v0.2.1 · 源码可见,禁止商用",
"footer.source": "源代码",
"footer.privacy": "隐私"
"footer.privacy": "隐私",
"footer.license": "许可协议"
}
};