LocaleKit Docs Enhancements — Design Spec
Date: 2026-03-18 Status: Draft
Overview
Enhance the LocaleKit VitePress documentation site with developer-focused features: brand typography, version/timestamp display, source links, navigation improvements, auth badges, engine/model icons, configuration reference, and accuracy improvements (JSON schemas, exit codes, env vars, shell completions, snapshot docs, Apple Intelligence caveat). All changes must be compatible with the existing generate-cli-docs.mjs automation.
1. Manrope Font
Load Manrope from Google Fonts (the same font family used in the macOS app via LocaleKitTheme.swift).
Implementation:
- Add Google Fonts
<link>toconfig.tshead with&display=swapto avoid flash of invisible text - Override VitePress font CSS variables in
custom.css:--vp-font-family-base: 'Manrope', sans-serif--vp-font-family-monostays as-is (monospace for code)
2. CLI Version + Last Updated Timestamp
The generation script reads CLIVersion.swift to extract the current version string, and stamps the generation date. This information appears in two places:
A. Index page badge — at the top of docs/index.md, below the title:
::: info
**CLI version: 1.2.0** · Documentation generated on Mar 18, 2026
:::When the version is "dev" (local builds without CI tag), display:
::: info
**CLI version: dev** · Documentation generated on Mar 18, 2026
:::This is accurate — "dev" tells the reader they're looking at docs generated from an unreleased build.
B. Footer — update config.ts footer message to include version dynamically. The generation script writes a small docs/.vitepress/generated-meta.ts file:
export const cliVersion = '1.2.0'
export const generatedAt = '2026-03-18'config.ts imports this and uses it in the footer. This file is committed to git (like generated-cli-sidebar.ts), so vitepress dev works without running generation first.
Source: CLIVersion.swift → static let current = "..." — parsed via regex from the Swift source.
3. View Source Link
Add a "View LocaleKit source" link on each page pointing to the LocaleKit repo.
Since generated pages come from Swift files (not editable markdown), a per-file :path mapping doesn't apply. Instead, use a custom nav link rather than VitePress's built-in editLink (which requires a :path template and would produce broken URLs).
Implementation: Add to config.ts nav:
nav: [
{ text: 'Reference', link: '/' },
{ text: 'Source', link: 'https://github.com/hexagone-studio/LocaleKit' },
]This is simpler and more correct than abusing editLink.
4. Right-Side Outline (Table of Contents)
VitePress has a built-in outline feature. Enable it to show h2 headings (Usage, Arguments, Options, Flags, Examples) in the right sidebar.
Implementation in config.ts:
outline: {
level: [2, 3],
label: 'On this page'
}No changes to generated markdown needed — it already uses ## Usage, ## Options, etc.
5. Prev/Next Navigation
VitePress auto-generates prev/next links from the sidebar order. The sidebar is grouped, so prev/next follows group order:
init → scan → status → translate → validate → diff (Localization) → export → convert (Export & Convert) → sync (GitHub) → login → logout → whoami (Auth) → mcp (AI)
Implementation: VitePress enables this by default with our sidebar structure. Verify it renders. Optionally customize labels via docFooter in config:
docFooter: {
prev: 'Previous',
next: 'Next'
}6. Custom 404 Page
Use VitePress's built-in not-found layout support. Create docs/404.md:
---
layout: page
title: Page Not Found
---
<div style="text-align: center; padding: 4rem 1rem;">
<p style="font-size: 4rem; font-weight: 700; margin: 0; background: linear-gradient(135deg, #90ccf0, #00AAff); -webkit-background-clip: text; -webkit-text-fill-color: transparent;">404</p>
<p style="color: var(--vp-c-text-2); margin-top: 1rem;">This page doesn't exist.</p>
<a href="/" style="color: var(--vp-c-brand-1);">Back to CLI Reference</a>
</div>VitePress generates a 404.html from this. The existing nginx.conf already routes to 404.html via try_files ... /404.html, so no deployment changes are needed.
This is a manual file (not generated).
7. Code Groups in Generated Pages
For commands that have an --engine option (translate, sync), generate a tabbed "Quick Start" section with per-engine examples:
## Quick Start
::: code-group
```bash [DeepL]
localekit translate --engine deepl --api-key $DEEPL_API_KEYlocalekit translate --engine openai --api-key $OPENAI_API_KEYlocalekit translate --engine mlx --mlx-model mlx-community/Qwen3-4B-4bit:::
**Implementation:** The generator checks if a command's options include one named `engine`. If so, it emits the code group after the description. The engine names and example flags are defined as static data in the script (not parsed from Swift), since help text for the `--engine` option varies between commands.
**Note:** `translate`'s help text says "openai, deepl" while `sync` says "openai, deepl, mlx" — but both commands actually support all three engines in code. The code group will show all three for both commands.
**Commands affected:** `translate`, `sync`.
## 8. Improved Index Page
The root index currently jumps straight into command tables. Add a practical header with install and quick-start sections.
**A. Version badge** (from Section 2) at the top.
**B. Install snippet** with code group:
```markdown
## Install
::: code-group
```bash [Homebrew]
brew tap hexagone-studio/localekit https://github.com/hexagone-studio/LocaleKit.git
brew install localekit-clicd LocaleKitCore
swift build -c release
sudo cp .build/release/LocaleKitCLI /usr/local/bin/localekit:::
**C. Quick start** — 3-line workflow:
```markdown
## Quick Start
```bash
localekit init ./MyApp # Create .localekitrc.yml
localekit status # Check translation coverage
localekit translate --engine deepl # Translate missing keys
These sections are **static content** defined as constants in the generation script (not parsed from Swift). They are prepended to the generated command tables in the index. Future changes to install instructions require editing the script constants.
## 9. Auth/Tier Badges on Commands
Extract authentication requirements from the Swift source and display badges.
**Extraction logic** — scan each command's `run()` method body:
- `CLIAuthGuard.requireTier(.solo)` → badge: `Solo plan`
- `CLIAuthGuard.requireAuth()` → badge: `Requires login`
- `CLIAuthGuard.isExportLimited` or `CLIAuthGuard.isConvertLimited` → append: `Limited on free tier`
- No auth guard → no badge
**Commands and their tiers** (verified from Swift source):
| Tier | Commands |
|------|----------|
| No guard | login, logout, whoami, init, mcp |
| Requires login | scan, status, validate, diff |
| Requires login + limited on free | export, convert |
| Solo plan | translate, sync |
**Display — command page** (after the description, before Usage):
```markdown
<Badge type="warning" text="Solo plan" />Display — index table — third column:
| Command | Description | |
|---------|-------------|-|
| [`localekit translate`](./cli/translate) | Translate missing localization keys | <Badge type="warning" text="Solo" /> |
| [`localekit export`](./cli/export) | Export localization file to another format | <Badge type="tip" text="Login" /> |Commands with no badge get an empty third column.
10. Engine & Model Icons
Copy translation engine icons and MLX model family icons from localekit-macos into docs/public/icons/ for use in documentation pages.
Engine icons (from LocaleKitCore/Resources/Media.xcassets/):
| Engine | Source file (2x) | Output |
|---|---|---|
| DeepL | deepL.imageset/deepl-color 4@2x.png | docs/public/icons/deepl.png |
| OpenAI | openAI.imageset/chatgpt (2).png | docs/public/icons/openai.png |
| MLX | mlx.imageset/mlx-logo 1.png | docs/public/icons/mlx.png |
| Apple Intelligence | AppleIntelligence.imageset/image 4@2x.png | docs/public/icons/apple-intelligence.png |
MLX model icons (from same xcassets):
| Model | Source file | Output |
|---|---|---|
| Qwen | qwen.imageset/Qwen_logo.svg | docs/public/icons/qwen.svg |
| Mistral | mistral.imageset/Mistral_AI_logo_(2025–).svg 1.png | docs/public/icons/mistral.png |
| Gemma | gemma.imageset/gemma-color 1.png | docs/public/icons/gemma.png |
Usage in docs:
A. Engine code groups (Section 7) — add icon before the tab label using inline HTML:
::: code-group
```bash [DeepL]
localekit translate --engine deepl --api-key $DEEPL_API_KEYlocalekit translate --engine openai --api-key $OPENAI_API_KEYlocalekit translate --engine mlx --mlx-model mlx-community/Qwen3-4B-4bit:::
B. **MLX models table** — generate a table on the `translate` and `sync` command pages listing all available MLX models with their icons, parsed from `MLXModelOption.swift`:
```markdown
### MLX Models
| | Model | Parameters | Size | RAM | Languages |
|-|-------|------------|------|-----|-----------|
| <img src="/icons/qwen.svg" width="20"> | Qwen3 4B | 4B | 2.5 GB | 8 GB | 119 |
| <img src="/icons/mistral.png" width="20"> | Mistral 7B | 7B | 4.1 GB | 8 GB | 15 |
| <img src="/icons/qwen.svg" width="20"> | Qwen3 8B | 8B | 5.0 GB | 16 GB | 119 |
| <img src="/icons/gemma.png" width="20"> | Gemma 3 12B | 12B | 8.0 GB | 16 GB | 35 |
| <img src="/icons/qwen.svg" width="20"> | Qwen3 30B-A3B | 30B (3B MoE) | 16.0 GB | 16 GB | 119 |
| <img src="/icons/qwen.svg" width="20"> | Qwen3 32B | 32B | 18.0 GB | 32 GB | 119 |Extraction: The generator parses MLXModelOption.swift for the allModels static array, extracting: id, displayName, parameterCount, activeParameters, minimumRAMGB, sizeOnDiskGB, languageCount, isMoE, and family. The family maps to the icon filename.
Default model indicator: Qwen3 4B is marked as default with a badge: <Badge type="tip" text="default" />
C. Engine overview on index page — add a visual engines section before the command tables:
## Translation Engines
| | Engine | Type | API Key |
|-|--------|------|---------|
| <img src="/icons/deepl.png" width="20"> | DeepL | Cloud | `DEEPL_API_KEY` |
| <img src="/icons/openai.png" width="20"> | OpenAI | Cloud | `OPENAI_API_KEY` |
| <img src="/icons/mlx.png" width="20"> | MLX | On-device (Apple Silicon) | — |
| <img src="/icons/apple-intelligence.png" width="20"> | Apple Intelligence | On-device (macOS 15.1+) | — |Icons are static assets (copied once, not generated). The copy step runs as part of the generation script if the icons don't already exist in docs/public/icons/.
11. Configuration Reference Page
Generate a .localekitrc.yml reference page at docs/cli/configuration.md from the example config file at ../localekit-macos/docs/localekitrc.example.yml.
Content:
- Full annotated YAML example (copied from the source file)
- Field-by-field reference table explaining each option
- Environment variable substitution syntax (
${ENV_VAR}) - Engine-specific settings (DeepL key, OpenAI key, MLX model)
- GitHub integration settings
Generated page structure:
# Configuration
LocaleKit is configured via a `.localekitrc.yml` file in your project root.
Create one with `localekit init` or manually.
## Example
```yaml
{full contents of localekitrc.example.yml}Reference
| Field | Type | Description | Default |
|---|---|---|---|
workspace | string | Project directory to scan | . |
sourceLanguage | string | Base language (BCP 47) | en-US |
targetLanguages | string[] | Target languages | — |
engine | string | Translation engine: deepl, openai, mlx | deepl |
deeplApiKey | string | DeepL API key (supports ${ENV_VAR}) | — |
openaiApiKey | string | OpenAI API key (supports ${ENV_VAR}) | — |
mlxModel | string | MLX model ID from Hugging Face | mlx-community/Qwen3-4B-4bit |
verbose | bool | Show detailed output | false |
dryRun | bool | Preview without writing files | false |
github.repo | string | Repository in owner/repo format | — |
github.baseBranch | string | Base branch for PRs | main |
github.token | string | GitHub token (or use GITHUB_TOKEN env) | — |
**Source:** The YAML example is read from `../localekit-macos/docs/localekitrc.example.yml`. The reference table is static content in the script (the example file contains all the documentation needed as YAML comments).
**Sidebar:** Add "Configuration" to the sidebar under a new "Setup" group, before the Localization commands.
## 12. Configuration Page Additions
In addition to the `.localekitrc.yml` reference (Section 11), the configuration page should include:
### A. Shell Completions
Shell completions (bash, zsh, fish) auto-complete command and flag names when pressing Tab.
**Homebrew users** get completions automatically — the formula has been updated to use `generate_completions_from_executable` which installs them on `brew install`. Change made in `localekit-macos/homebrew/localekit-cli.rb`.
**Manual install** users need to generate them. Document on the configuration page:
```markdown
## Shell Completions
Homebrew installs completions automatically. For manual installs:
::: code-group
```bash [Zsh]
localekit --generate-completion-script zsh > ~/.zsh/completions/_localekitlocalekit --generate-completion-script bash > /etc/bash_completion.d/localekitlocalekit --generate-completion-script fish > ~/.config/fish/completions/localekit.fish:::
This is static content in the generation script.
### B. Environment Variables Reference
Collected from all commands:
```markdown
## Environment Variables
| Variable | Used By | Description |
|----------|---------|-------------|
| `DEEPL_API_KEY` | translate, sync | DeepL API key |
| `OPENAI_API_KEY` | translate, sync | OpenAI API key |
| `LOCALEKIT_API_KEY` | translate, sync | Fallback API key (any engine) |
| `GITHUB_TOKEN` | sync | GitHub personal access token |C. Exit Codes
## Exit Codes
| Code | Meaning |
|------|---------|
| `0` | Success |
| `1` | Validation error, auth failure, or warnings in strict mode |
| `2` | Invalid command-line arguments |These are all static tables defined in the generation script.
13. Generator Improvements for Accuracy
Several accuracy improvements to the generation script output:
A. Apple Intelligence caveat
The CLITranslationEngine enum includes .appleIntelligence, but TranslateCommand and SyncCommand both throw:
"Apple Intelligence is not available in CLI mode. Use --engine deepl, openai, or mlx instead."
The engines table on the index page must note this: Apple Intelligence — macOS app only (not available in CLI).
The code groups on translate/sync should only show DeepL, OpenAI, and MLX — not Apple Intelligence.
B. JSON output schemas
Commands with --json output (scan, status, validate, diff, whoami) should have a "JSON Output" section showing the schema. The generation script can detect --json flags and append a static schema block per command. The schemas are defined as constants in the script (derived from reading the Swift code).
C. Snapshot file documentation
The translate command creates .localekit-snapshot.json and the diff command requires it. Add a note on the translate page:
After translating, a
.localekit-snapshot.jsonfile is saved. This is used bylocalekit diffto detect changes.
And on the diff page:
Requires a
.localekit-snapshot.jsonfile created by a previouslocalekit translaterun.
These notes are added by the generation script as static content, keyed by command name.
14. Sitemap
VitePress has built-in sitemap generation. Enable it only when a confirmed hostname is set via environment variable, to avoid publishing sitemaps with placeholder domains.
Implementation in config.ts:
...(process.env.SITE_URL ? { sitemap: { hostname: process.env.SITE_URL } } : {}),In Coolify, set SITE_URL=https://docs.localekit.app (or the actual domain). Locally and in CI without the variable, no sitemap is generated.
Files Changed
| File | Change Type |
|---|---|
docs/.vitepress/config.ts | Modified — font, nav source link, outline, sitemap, footer with version |
docs/.vitepress/theme/custom.css | Modified — Manrope font variable |
docs/.vitepress/generated-meta.ts | New (generated, committed) — CLI version + timestamp |
docs/.vitepress/generated-cli-sidebar.ts | Modified (generated) — new "Setup" group with configuration page |
docs/index.md | Modified (generated) — install, quick start, version badge, engines table, badge column |
docs/cli/*.md | Modified (generated) — auth badges, code groups + MLX models on translate/sync, JSON schemas, snapshot notes |
docs/cli/configuration.md | New (generated) — config reference, shell completions, env vars, exit codes |
docs/public/icons/*.png + *.svg | New (copied) — engine icons (deepl, openai, mlx, apple-intelligence) + model icons (qwen, mistral, gemma) |
docs/404.md | New (manual) — custom 404 page |
scripts/generate-cli-docs.mjs | Modified — version extraction, badges, code groups, MLX models parsing, config page, icon copy, improved index |
scripts/update-docs.sh | Modified — include generated-meta.ts + configuration.md in diff/stage paths |
package.json | Modified — include generated-meta.ts + configuration.md in check script paths |
.git/hooks/pre-commit | Modified — include generated-meta.ts + configuration.md in diff paths |
Files NOT Changed
Dockerfile,nginx.conf— no deployment changesdocs/.vitepress/theme/index.ts— no structural theme changes
Constraints
- All changes to generated files go through
generate-cli-docs.mjs— never edit generated files manually - The generation script must remain idempotent and deterministic (same input → same output, except for the date in
generatedAtwhich uses the generation date) - The pre-commit hook and
check:cli-docsscript must cover all generated files includinggenerated-meta.ts - Static content in the index (install, quick start) is defined as constants in the script, not parsed from Swift
