WolfDavid's picture
docs: create roadmap (6 phases)
9693b28
|
Raw History Blame
27.9 kB
<!-- GSD:project-start source:PROJECT.md -->
## Project
**Japanese Learning Avatar**
An animated 3D avatar tutor that teaches Japanese through spoken conversation, structured lessons, and immersion role-play β€” hosted as a Hugging Face Space. A VRM anime-style character listens to the learner speak Japanese, responds aloud with lip-synced speech and expressions, drills vocab and grammar, and adapts to the learner's level (N5 through N2). Built both as a daily-use learning tool for the author and as the flagship AI/ML engineering showcase on the WolfDavid Hugging Face profile.
**Core Value:** A learner can hold a real, level-appropriate spoken Japanese conversation with an animated avatar that talks back β€” and measurably improve over time because the avatar remembers them.
### Constraints
- **Platform**: Hugging Face Space (Gradio) β€” portfolio strategy requires it; free-tier visitors must get a working experience
- **Cost**: Free baseline for visitors β€” small open model default; frontier quality only via visitor's own API key (BYOK)
- **Tech**: In-browser avatar rendering (three.js/VRM) β€” no server-side video generation
- **Quality bar**: Flagship portfolio piece β€” "would a Google AI/ML hiring manager be impressed?" drives polish decisions
<!-- GSD:project-end -->
<!-- GSD:stack-start source:research/STACK.md -->
## Technology Stack
## ⚠️ Read This First: Two Findings That Reshape the Project
### 1. "Free CPU tier" is no longer the free path for a Gradio Space
### 2. ZeroGPU quota is consumed by the *visitor*, not the owner
| Visitor account type | Included daily GPU quota | Queue priority |
|---|---|---|
| Unauthenticated | **2 minutes/day** | Low |
| Free HF account | **5 minutes/day** | Medium |
| PRO account | 40 minutes/day (extensible) | Highest |
## Recommended Stack
### Core Technologies
| Technology | Version | Purpose | Why Recommended |
|---|---|---|---|
| **Gradio** | `6.22.0` (pin exactly) | App framework + Space SDK | Gradio 6 is the only maintained major line; the team has stated only v6 gets future releases. Crucially, **ZeroGPU is exclusively compatible with the Gradio SDK** β€” no Docker, no Static. Gradio 6 also ships the `gr.HTML` templating system (below) that makes the three.js avatar viable without a build step. |
| **Python** | `3.12.12` (declare in README) | Runtime | ZeroGPU provides **only** Python `3.10.13` and `3.12.12`. Pick 3.12.12. **Do not use 3.13** β€” this is the recurring "Python 3.13 / Gradio pin" gotcha from prior Spaces work, and here it's a hard platform limit, not a soft one (`spaces` requires `>=3.10,<3.15`, but ZeroGPU only builds those two images). |
| **`spaces`** | `0.51.1` | ZeroGPU allocation | Provides `@spaces.GPU(duration=...)`. Effect-free off-ZeroGPU, so local dev is unaffected. Use **dynamic durations** (`duration=callable`) β€” shorter declared durations improve queue priority for your visitors. |
| **three.js** | `0.185.1` (MIT) | 3D renderer | The only realistic in-browser 3D engine with first-class VRM support. Pin the exact version β€” three.js makes breaking renderer changes at a ~6-week cadence and `three-vrm` tracks it loosely. |
| **@pixiv/three-vrm** | `3.5.5` (MIT) | VRM avatar loading, humanoid bones, expressions, spring-bone physics | The reference implementation from the company that runs VRoid Hub. Supports both VRM 0.0 and VRM 1.0, so community VRoid models load without conversion. Peer dep is `three >= 0.137`, so 0.185.1 is safe. |
| **VOICEVOX CORE** | `0.16.4` (`+cpu` abi3 wheel) | Japanese TTS **with per-mora phoneme timing** | See "The lip-sync decision" below. This is the highest-leverage choice in the whole stack. |
| **whisper-large-v3-turbo** | via `transformers` 5.x on ZeroGPU | Japanese ASR | Best measured accuracy/speed balance for Japanese conversational audio in the Feb-2026 benchmark: CER 0.184, **RTF 0.013**. MIT-licensed. |
| **Qwen3.5-4B** | Apache-2.0, released 2026-03-02 | Free-default tutor LLM | 4B dense, **201 languages incl. Japanese**, 256K context, hybrid thinking (disable thinking for latency). Apache-2.0 means no license story to explain to a hiring manager. Fits easily in 48 GB with room for KV cache. |
| **`transformers`** | `5.14.1` | Model loading | v5 is current. Note: v5 was a breaking release β€” do not copy v4-era snippets from blogs. |
| **`huggingface_hub`** | `1.27.0` | Hub + Inference Providers client | v1.x. Provides `InferenceClient` for the BYOK/routed paths. |
| **Neon Serverless Postgres** | Free plan | User accounts + progress persistence | See "The database decision" below. |
### The lip-sync decision (do not skip this)
- **No audio-amplitude analysis.** ChatVRM and most AITuber kits drive the `aa` blendshape from a Web Audio `AnalyserNode` RMS β€” the mouth just flaps open and shut. Mora-timed visemes are visibly better and are the thing that makes the demo look expensive.
- **No forced alignment, no viseme ML model, no GPU.**
- **Zero ZeroGPU quota consumed for speech output**, which is what makes the free tier survivable.
- The same mora timeline doubles as **pedagogical data**: mora-by-mora pitch accent is already in the payload, so "here is where your pitch accent was wrong" is nearly free.
- `voicevox_core` is dual-licensed **LGPL v3** + a commercial no-source-disclosure license. Dynamic linking via the Python wheel keeps you clear of copyleft on your own code.
- **Each character voice has its own terms.** The general rule is *free for commercial and non-commercial use provided you display credit* in the form `VOICEVOX:キャラクター名`. Without credit, per-character paid licensing is reportedly Β₯400,000/character.
- **Read the specific character's terms before shipping**, and render the credit string persistently in the UI (a footer line next to the avatar). Prefer a character with permissive, well-documented terms (γšγ‚“γ γ‚‚γ‚“ / VOICEVOX Nemo voices are the usual safe picks).
- Also verify the terms permit *offering synthesis to third parties via a web app*, not merely using generated audio β€” this is the one clause a portfolio Space most plausibly trips.
### The avatar-embedding decision
| Approach | Verdict |
|---|---|
| `gr.HTML` with `html_template`/`js_on_load` | βœ… **Recommended.** No build step, no npm publish, hot-reloads with the app, `server_functions` gives direct JSβ†’Python calls, `watch('value')` gives Pythonβ†’JS push. Ships as one `app.py`. |
| Full Gradio custom component (`gradio cc`) | ❌ Requires Svelte, Node 18+, npm 9+, a build/publish cycle, and a separate package on PyPI. Justified only if you intend to publish the VRM component for others β€” a nice-to-have, not a v1 need. |
| Raw `<iframe>` + `postMessage` | ❌ You hand-roll the entire bridge, fight Space iframe sandboxing and cookie issues, and lose Gradio's event system. |
| Server-rendered talking-head video | ❌ Already correctly in `PROJECT.md` Out of Scope. Would also incinerate ZeroGPU quota. |
### The database decision
| Option | Verdict |
|---|---|
| **Neon serverless Postgres (free plan)** | βœ… **Recommended.** 0.5 GB storage + 100 compute-hours/project/month, up to 100 projects, no credit card. Compute **scales to zero after 5 min idle and auto-resumes in a few hundred milliseconds on the next query** β€” no manual intervention, ever. |
| Supabase (free plan) | ⚠️ Only if you need its Auth/Storage too. **Free projects are auto-paused after 7 days of inactivity and require a manual dashboard unpause.** For a portfolio piece whose entire value is "a hiring manager clicks the link and it works," a silent 7-day dead-man's-switch on your user database is a project-killing failure mode. |
| SQLite on Space disk | ❌ Space disk is **ephemeral** β€” wiped on every restart/rebuild, and Spaces rebuild on every git push. You would lose user progress every deploy. |
| HF Storage Buckets (S3-like, Xet-backed) | ⚠️ Great for **assets** (VRM files, cached TTS audio, lesson media) β€” mountable as a Space volume, mutable, free allowance. **Not** a transactional database; SQLite over a network-mounted bucket invites corruption under concurrency. |
| HF Dataset repo + `CommitScheduler` | ⚠️ The classic HF persistence pattern, fine for **append-only analytics/telemetry**. Wrong shape for per-user read-modify-write of progress records (git commits, no transactions, no concurrent-write story). |
### Supporting Libraries
| Library | Version | Purpose | When to Use |
|---|---|---|---|
| **SudachiPy** | `0.6.11` (Apache-2.0) | Japanese tokenization + `reading_form()` for furigana + lemmas | Primary Japanese NLP engine. Chosen over MeCab/fugashi for the clean Apache-2.0 story and pure-wheel install (no MeCab system dependency to fight in a Space build). Three splitting modes (A/B/C) map neatly onto "vocab item" vs "phrase" granularity for a tutor. |
| **SudachiDict-core** | `20260723` (Apache-2.0) | Dictionary for SudachiPy | Required. `-core` is the right size/coverage tradeoff; `-full` bloats the image. |
| **jaconv** | `0.5.0` (MIT) | hiragana ⇄ katakana ⇄ half-width conversion | Normalizing learner input, generating kana drills, feeding the viseme mapper. Tiny, zero-dependency, MIT. |
| **cutlet** | `0.5.2` | Romaji generation | N5 learners need romaji scaffolding. Built on fugashi; use only if you also pull fugashi, otherwise derive romaji from SudachiPy readings + `jaconv`. |
| **`@huggingface/transformers`** (transformers.js) | `4.2.0` (Apache-2.0) | **Browser-side** Whisper ASR fallback | v4 (Feb 2026) shipped a C++-rewritten WebGPU runtime (~4Γ— faster, 53% smaller bundles). Running ASR here costs **zero ZeroGPU quota** β€” this is how anonymous visitors get more than four conversational turns. |
| **`anthropic`** | `0.121.0` | BYOK frontier path (Claude) | Visitor pastes their key; nothing is stored server-side. |
| **`openai`** | `2.53.0` | BYOK frontier path (OpenAI) β€” and reused as the client for HF's OpenAI-compatible router (`https://router.huggingface.co/v1`) | One client library covers two providers. |
| **`psycopg[binary]`** | 3.x | Postgres driver | Neon over TLS. Use a pooled connection string; a Space restart should not leak connections. |
| **SQLAlchemy** | 2.x | ORM / schema | Optional but recommended once progress modelling gets past ~4 tables (level, vocab-seen SRS state, mistakes, sessions). |
| **`onnxruntime`** | pulled by voicevox_core downloader | VOICEVOX inference backend | CPU build. Managed by the VOICEVOX downloader, do not hand-install. |
| **`fastrtc`** | `0.0.34` | *Deferred.* True barge-in / VAD / turn-taking over WebRTC | HF's real-time library, Gradio-team maintained, with built-in VAD and turn detection + Cloudflare TURN. **Still `0.0.x`** β€” pre-1.0 API churn is not what you want under a flagship portfolio piece in v1. Revisit for a "real-time conversation" milestone once turn-based voice is solid. |
### Development Tools
| Tool | Purpose | Notes |
|---|---|---|
| **uv** | Dependency resolution + venv | Fast, and its lockfile makes the "works locally, breaks on Space rebuild" class of bug reproducible. Export to `requirements.txt` for the Space (Spaces do not read `uv.lock`). |
| **ruff** | Lint + format | Pre-commit hook. Prior GSD work in this account has been blocked by accumulated ruff debt β€” enforce from commit #1 here. |
| **pytest** | Unit tests | Focus on the viseme-timeline builder and the JLPT-level content selector β€” both are pure functions with high bug density. |
| **Playwright** | E2E | The avatar is a canvas; assert on `trigger()` events and audio playback state, not pixels. Screenshot-diff the VRM render at your own risk. |
| **`hf` CLI** | Space + bucket management | `hf buckets sync` for asset deploys. |
| **Space README front-matter** | Config | Must pin `sdk: gradio`, `sdk_version: 6.22.0`, `python_version: 3.12.12`, `hf_oauth: true`. |
## Authentication
# README.md front-matter
# no extra scopes needed for progress tracking β€” "openid profile" is always included
- Request **only** `openid profile` (always included) since progress lives in your own DB. Every extra scope is a consent-screen deterrent.
- Add the `inference-api` scope **only** if you implement the optional "spend my own HF credits" path (lets you call Inference Providers on the visitor's behalf β€” free users get ~$0.10/month of credits, PRO $2.00, so treat it as a nicety, not a tier).
- `hf_oauth_expiration_minutes` maxes at 43200 (30 days). Use it β€” re-authing daily kills a daily-habit app.
- ⚠️ **`gr.LogoutButton` was removed in Gradio 6.** Build your own sign-out. (`gr.LoginButton` / `gr.OAuthProfile` / `gr.OAuthToken` are believed intact β€” **verify on first spike**, MEDIUM confidence.)
- ⚠️ Use `target="_blank"` on the sign-in button, per HF docs, or third-party-cookie policies break the flow inside the Space iframe.
## Installation
# requirements.txt (Hugging Face Space)
# --- inference ---
# --- Japanese TTS (CPU, zero GPU quota) ---
# --- Japanese NLP ---
# --- persistence ---
# --- BYOK ---
# One-time, in the Space build (voicevox_core needs runtime + dict + voice models)
# The official downloader fetches onnxruntime, the Open JTalk dictionary, and .vvm voice models.
## Alternatives Considered
| Recommended | Alternative | When to Use Alternative |
|---|---|---|
| **VOICEVOX** (TTS) | **Qwen3-TTS-12Hz-0.6B / 1.7B** (Apache-2.0, Jan 2026, JA among 10 langs, voice cloning from 3s) | If VOICEVOX character terms turn out to prohibit third-party web synthesis, or you want a custom/cloned tutor voice. Cost: runs on GPU (burns visitor quota), and **gives you no phoneme timings** β€” you fall back to amplitude-driven lip-sync or add a forced aligner. |
| **VOICEVOX** (TTS) | **Style-Bert-VITS2** (`2.5.0`) | If you want maximum expressive/emotional Japanese prosody. Cost: **AGPL-3.0**, which would infect your whole app unless isolated behind a separate network service. For a public portfolio repo, that is a conversation you do not want to have in an interview. |
| **VOICEVOX** (TTS) | **Kokoro-82M** (Apache-2.0, `kokoro-js` 1.2.1 runs in-browser) | English-first fallback, or if you need TTS with literally zero server cost. **Rejected for Japanese**: its own VOICES.md grades the five JA voices **C- to C+** on <10 hours of training data and warns "support for non-English languages may be absent or thin due to weak G2P." A pronunciation-teaching app cannot ship C-grade Japanese. |
| **whisper-large-v3-turbo** (ASR) | **Qwen3-ASR-1.7B** | Best measured Japanese accuracy (CER 0.140 vs 0.184) β€” use if transcription errors are visibly hurting the correction/scoring feature. Cost: RTF 0.036 vs 0.013 (~3Γ— slower), which matters when GPU-seconds are the visitor's scarcest resource. |
| **whisper-large-v3-turbo** (ASR) | **transformers.js Whisper in-browser (WebGPU)** | **Recommend shipping both.** Browser-side = zero quota, works while the Space is queued, and is a genuinely impressive "runs on your GPU" demo. Server-side = the accuracy fallback for weak devices / no-WebGPU browsers. |
| **whisper-large-v3-turbo** (ASR) | **nvidia/parakeet-tdt-0.6b-v3** | Only if latency is the binding constraint (RTF 0.003) and you can tolerate CER 0.321 β€” too error-prone to grade a learner's pronunciation against. |
| **Qwen3.5-4B** (LLM) | **Nemotron Nano 9B JP** (NVIDIA) | Ranked **#1 in the sub-10B category on Nejumi Leaderboard 4** (the Japanese LLM leaderboard). Swap in if Qwen3.5-4B's Japanese pedagogy/naturalness disappoints in evaluation. Cost: 2Γ— the size (more GPU-seconds per turn) and the NVIDIA Open Model License rather than Apache-2.0. |
| **Qwen3.5-4B** (LLM) | **Qwen3.5-2B / 0.8B** | If per-turn GPU-seconds prove to be the binding UX constraint. Cheapest lever for stretching an anonymous visitor's 2-minute daily quota. |
| **Qwen3.5-4B** (LLM) | **LLM-jp-4** (32B MoE, 3.8B active, Apache-2.0, NII) | The Japanese-sovereign, research-credible choice β€” reportedly MT-Bench JA 7.82 vs GPT-4o's 7.29. MoE with 3.8B active params is surprisingly viable on a 48 GB Blackwell. Strong "I evaluated Japanese-specific models" story for a Google interview. Cost: 32B of weights to load = slow cold starts. |
| **Neon** (DB) | **Supabase** | If you later want its Auth, Realtime, or Storage as a bundle and will pay for Pro (which removes the 7-day pause). |
| **Gradio `gr.HTML`** | **Gradio custom component (`gradio cc`)** | If you decide to publish `gradio-vrm-avatar` as a reusable package β€” genuinely good portfolio surface area, but a Phase-N+1 concern. |
## What NOT to Use
| Avoid | Why | Use Instead |
|---|---|---|
| **CPU Basic as the free hosting plan** | Gradio Spaces on compute now require PRO for personal accounts. CPU Basic is not the free path, and its 2 vCPU could not run a 4B LLM anyway. | ZeroGPU Gradio Space (free for up to 2 Spaces on an account in good standing). |
| **Python 3.13** | ZeroGPU images provide **only** 3.10.13 and 3.12.12. This is the known "Python 3.13 / gradio pin" gotcha, and on ZeroGPU it is a hard wall, not a warning. | `python_version: 3.12.12` in README front-matter. |
| **Unpinned `sdk_version`** | Spaces silently rebuild on push. An unpinned Gradio floats you into a breaking release while you sleep β€” and Gradio 6 removed/renamed a lot (`show_api`β†’`api_visibility`, tuple chatbot messages, `gr.LogoutButton`, `mirror_webcam`, `cache_examples="lazy"`). | Pin `sdk_version: 6.22.0` and bump deliberately. |
| **Gradio 5-era tutorials and code** | Gradio 6 moved `theme`/`css`/`js`/`head` from the `Blocks()` constructor to `Blocks.launch()`, consolidated all `show_*_button` params into `buttons`, and **removed tuple-format chatbot messages entirely**. Copy-pasted v5 snippets will fail in non-obvious ways. | The [Gradio 6 migration guide](https://gradio.app/main/guides/gradio-6-migration-guide) as the primary reference. |
| **`torch.compile` on ZeroGPU** | Explicitly unsupported. | PyTorch **ahead-of-time** compilation (`torch >= 2.8`), documented in HF's zerogpu-aoti guide. Meaningful latency win = meaningful quota win. |
| **Lazy `.to('cuda')` inside `@spaces.GPU`** | Docs are explicit that CUDA transfers are optimized for startup placement; lazy loading is "significantly less efficient." Every wasted second is billed to your visitor's daily quota. | Load models to `cuda` at **module level** (a CUDA emulation layer makes this work outside GPU context). |
| **`pykakasi`** | **GPL-3.0-or-later.** For kana/romaji conversion β€” a trivially replaceable function β€” it would impose GPL on a flagship public portfolio repo. | `SudachiPy` (Apache-2.0) readings + `jaconv` (MIT) + `cutlet` for romaji. |
| **Style-Bert-VITS2 embedded in-process** | **AGPL-3.0.** Β§13 means network use triggers source disclosure for the embedding server. | VOICEVOX (LGPL + credit) or Qwen3-TTS (Apache-2.0). |
| **`edge-tts` / unofficial Microsoft endpoints** | Excellent Japanese voices, but it's an undocumented consumer endpoint used against its ToS, and it breaks without notice. A hiring manager finding a ToS-violating dependency in a flagship repo is a pure downside. | VOICEVOX. |
| **Web Speech API (`SpeechRecognition`) as primary ASR** | Chromium-only in practice, silently ships the learner's audio to Google, and returns no usable confidence/timing data β€” which is exactly the data pronunciation scoring needs. | transformers.js Whisper (browser) + whisper-large-v3-turbo (ZeroGPU). Web Speech is acceptable as a last-resort tertiary fallback only. |
| **kotoba-whisper (v1/v2)** | Fast (6.3Γ— large-v3) and great in-domain, but the Feb-2026 benchmark flags it as struggling with **unscripted/natural conversation** β€” which is 100% of this app's input. | whisper-large-v3-turbo. |
| **SQLite on Space disk** | Space disk is ephemeral; every `git push` rebuilds and wipes it. | Neon Postgres. |
| **Supabase free tier for the user DB** | Auto-pauses after 7 days idle, requires manual dashboard unpause. Guaranteed to be paused exactly when someone finally clicks your portfolio link. | Neon (scale-to-zero, auto-resume in ~hundreds of ms). |
| **`fastrtc` in v1** | `0.0.34` β€” pre-1.0, active API churn, and it wraps the Gradio version you must pin. | Turn-based `gr.Audio(sources=["microphone"])`; adopt fastrtc in a later real-time milestone. |
| **AI talking-head video generation** | Already Out of Scope in PROJECT.md β€” and it would consume a visitor's entire daily GPU quota in a single utterance. | VRM + mora-timed visemes. |
## Stack Patterns by Variant
- Hardware: **ZeroGPU**, max 2 such Spaces on the account β€” budget that slot deliberately against the other 4 HF-profile projects.
- Design every turn to fit inside ~3–6 GPU-seconds so an anonymous visitor gets 20+ turns from 2 minutes.
- Push ASR to the browser by default; use ZeroGPU ASR only as fallback.
- Free Spaces sleep after inactivity β†’ **expect a cold start on the recruiter's first click.** Make the loading state part of the show: render the VRM avatar immediately (it's client-side and needs no backend) with a "waking up" idle animation while the Python backend boots.
- Up to 10 ZeroGPU Spaces; the owner's own testing gets 40 min/day at highest queue priority.
- $2.00/month Inference Provider credits make an **Inference Providers–routed default LLM** viable, removing cold-start and quota concerns entirely for light traffic.
- Visitor quotas are unchanged β€” PRO does not fix the anonymous visitor's 2 minutes. Design for free-tier visitors regardless.
- Swap to **Qwen3-TTS-12Hz-0.6B** (Apache-2.0) on ZeroGPU.
- You lose free phoneme timings β†’ recover lip-sync by deriving the mora sequence from **SudachiPy readings β†’ katakana β†’ vowel sequence** and distributing it proportionally across the audio duration, refined by a Web Audio RMS envelope. Noticeably worse than VOICEVOX timings, still far better than pure amplitude flapping.
- Move the default LLM to **HF Inference Providers** routed with the *visitor's* OAuth token (`inference-api` scope) β€” their credits, their latency, no queue.
- Keep BYOK (Anthropic/OpenAI) as the premium path. This is the honest three-tier story: free/queued β†’ your-HF-credits β†’ your-frontier-key.
## Version Compatibility
| Package A | Compatible With | Notes |
|---|---|---|
| `gradio==6.22.0` | Python `>=3.10` (3.10–3.13 classifiers) | But **ZeroGPU narrows this to 3.10.13 / 3.12.12**. The platform is stricter than the package. |
| `spaces==0.51.1` | Python `>=3.10,<3.15` | Consistent with the above. |
| ZeroGPU | `torch` **2.8.0 β†’ 2.11.0**, Gradio **4+** | Pin torch explicitly; a transitive bump outside this range breaks GPU allocation. |
| ZeroGPU | **Gradio SDK only** | Not Docker, not Static. This makes Gradio non-negotiable, which conveniently matches the portfolio requirement. |
| `@pixiv/three-vrm@3.5.5` | `three >= 0.137` (peer) | Verified against `three@0.185.1`. Load both from the *same* CDN origin via importmap β€” mismatched three.js instances cause the classic "multiple instances of three.js imported" breakage. |
| `@pixiv/three-vrm-animation@3.5.5` | same peer range | Only needed if you use `.vrma` animation clips for idle/gesture motion. Recommended for idle breathing/blinking. |
| `transformers==5.14.1` | `huggingface_hub>=1.x` | Both are v-major releases from the last cycle; **v4-era `transformers` snippets will not run**. |
| `voicevox_core` 0.16.4 `cp310-abi3` wheel | Python `>=3.10` incl. 3.12 | `abi3` wheels are forward-compatible across minor versions β€” the `cp310` tag is not a 3.10-only restriction. Linux wheel: `manylinux_2_34_x86_64`. |
| `SudachiPy 0.6.11` | `SudachiDict-core 20260723` | Dict packages are date-versioned and must match the SudachiPy major line; pin both together. |
| Neon Postgres | `psycopg[binary]` 3.x | Requires TLS + SNI. Use the pooled endpoint; Spaces restart often and unpooled connections leak. |
## Open Questions for the Roadmap
## Sources
- [HF Spaces Overview](https://huggingface.co/docs/hub/spaces-overview) β€” hardware tiers, PRO requirement for Gradio/Docker Spaces, ephemeral disk, sleep behavior, built-in env vars
- [HF Spaces ZeroGPU](https://huggingface.co/docs/hub/spaces-zerogpu) β€” RTX Pro 6000 Blackwell, Gradio-only compatibility, torch 2.8–2.11, Python 3.10.13/3.12.12, per-visitor daily quotas, `@spaces.GPU`, no `torch.compile`
- [HF Spaces OAuth](https://huggingface.co/docs/hub/spaces-oauth) β€” `hf_oauth` metadata, scopes, expiration limits, `target=_blank` caveat
- [HF Spaces disk usage](https://huggingface.co/docs/hub/spaces-storage) + [Storage Buckets](https://huggingface.co/docs/hub/storage-buckets) β€” ephemerality, bucket volumes
- [HF Inference Providers pricing](https://huggingface.co/docs/inference-providers/pricing) β€” $0.10 free / $2.00 PRO monthly credits, OpenAI-compatible router
- [HF pricing](https://huggingface.co/pricing) β€” PRO $9/mo
- [Gradio 6 migration guide](https://gradio.app/main/guides/gradio-6-migration-guide) β€” breaking changes, removals
- [Gradio custom HTML components](https://gradio.app/main/guides/custom-HTML-components) + [HF blog: gr.HTML one-shot apps](https://huggingface.co/blog/gradio-html-one-shot-apps) β€” `html_template`, `head`, `js_on_load`, `server_functions`, three.js precedent
- [VRM 1.0 expressions spec](https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/expressions.md) β€” `aa`/`ih`/`ou`/`ee`/`oh` presets
- [VOICEVOX core releases](https://github.com/VOICEVOX/voicevox_core/releases) β€” 0.16.4, manylinux abi3 CPU wheel
- [Kokoro-82M VOICES.md](https://huggingface.co/hexgrad/Kokoro-82M/blob/main/VOICES.md) β€” Japanese voice grades C- to C+
- [Qwen3.5-4B model card](https://huggingface.co/Qwen/Qwen3.5-4B) β€” Apache-2.0, 201 languages, 256K context, thinking mode
- PyPI/npm registry APIs queried directly for every pinned version in this document
- [Japanese ASR benchmark, Feb 2026 (Neosophie)](https://neosophie.com/en/blog/20260226-japanese-asr-benchmark) β€” CER/WER/RTF table; single benchmark, not independently replicated
- [Japanese LLMs compared, Apr 2026 (lilting.ch)](https://lilting.ch/en/articles/japanese-llm-options-compared) β€” LLM-jp-4, Nemotron Nano 9B JP, PLaMo, Swallow, Namazu; Nejumi 4 rankings quoted secondhand
- [VOICEVOX engine API reference (DeepWiki)](https://deepwiki.com/VOICEVOX/voicevox_engine/4.1-tts-pipeline-api) β€” AudioQuery/mora structure
- VOICEVOX commercial-use and credit requirements β€” Japanese-language secondary sources; **must be confirmed against the official εˆ©η”¨θ¦η΄„ per character**
- [Transformers.js v4 release](https://huggingface.co/blog/transformersjs-v4) β€” WebGPU runtime rewrite
- Neon vs Supabase free-tier behavior β€” multiple 2026 sources agree, vendor docs corroborate scale-to-zero
<!-- GSD:stack-end -->
<!-- GSD:conventions-start source:CONVENTIONS.md -->
## Conventions
Conventions not yet established. Will populate as patterns emerge during development.
<!-- GSD:conventions-end -->
<!-- GSD:architecture-start source:ARCHITECTURE.md -->
## Architecture
Architecture not yet mapped. Follow existing patterns found in the codebase.
<!-- GSD:architecture-end -->
<!-- GSD:workflow-start source:GSD defaults -->
## GSD Workflow Enforcement
Before using Edit, Write, or other file-changing tools, start work through a GSD command so planning artifacts and execution context stay in sync.
Use these entry points:
- `/gsd:quick` for small fixes, doc updates, and ad-hoc tasks
- `/gsd:debug` for investigation and bug fixing
- `/gsd:execute-phase` for planned phase work
Do not make direct repo edits outside a GSD workflow unless the user explicitly asks to bypass it.
<!-- GSD:workflow-end -->
<!-- GSD:profile-start -->
## Developer Profile
> Profile not yet configured. Run `/gsd:profile-user` to generate your developer profile.
> This section is managed by `generate-claude-profile` -- do not edit manually.
<!-- GSD:profile-end -->