## Summary A complete public CodeNomad help site in the app's ten languages, published on GitHub Pages (https://neuralnomadsai.github.io/CodeNomad/) and opened from the app. - **Content:** 25 pages in 8 sections (Start, Workflows, OpenCode setup, Remote access, Customize, Extensions, Desktop, Help), written for OpenCode power users and covering the current version only. It includes everything user-relevant from `README.md`, `packages/server/README.md` (server, network, auth, TLS, Remote Control) and the user-facing dev-docs, with flags, defaults, labels and safety boundaries checked against source. - **Languages:** en, fr, de, es, he (RTL), ja, ne, ru, tr, zh-Hans. Interface labels reuse each locale's own app strings; native desktop menu names, code, commands, flags, paths and anchors stay unchanged. - **Site:** `scripts/build-help.mjs` renders `docs/help/<locale>/<slug>.md` with translated chrome (`docs/help/i18n/`), stable `{#id}` anchors identical across locales, same-article language links with hreflang, a root language chooser, and a first-party offline per-locale search (Ctrl/⌘+K, substring matching for CJK, Devanagari and Hebrew, hidden without JS). No analytics or remote resources. - **Validation:** `npm run test:help` fails on any missing page or string, heading drift, broken link/anchor/asset or invalid search target. `.github/workflows/help-pages.yml` validates PRs and deploys only from `dev`. - **App entry points:** one `open-help` command for the palette and a new **CodeNomad Help** item at the top of the Electron and Tauri Help menus. It opens the help in the invoking window's UI language through the existing external opener, falls back to the root URL for windows without the handler, and reports failures without replay. - Documents the strict boolean environment-variable rule from #959 and the updater entry points from #960. ## Review Delivered as a CodeNomad mission with independent review loops, each to zero findings: - English content audit (5 passes, 14 fixes) and technical gatekeeper (2 passes) before translation. - After translation: QA, UX review, and a final multilingual gatekeeper (35 translation/label findings fixed, then verified), plus a visual fix for the search focus ring and a verified sync with #960. ## Validation - `npm run test:help`: 9/9 (25 pages × 10 locales, strict, including negative tests); `npm run build:help`: 250 pages. - `node scripts/test-help-browser.mjs`: 44/44; Playwright: 500 page visits at 390 and 1280 px, all locales, no overflow, no external requests. - UI help-command and desktop-updates browser tests 19/19; help URL unit tests; Electron menu tests; UI and Electron typechecks; Tauri `cargo test` 272/272.
8.7 KiB
Public user help
The guide covers current CodeNomad with OpenCode V2, not the old runtime or every upstream configuration option. Assume readers already know OpenCode: document CodeNomad's controls, workflow differences and state/scope boundaries instead of teaching agents, prompts, Git or MCP. Keep pages focused and link to the official V2 docs for native configuration details.
Sources and navigation
docs/help/site.json: the ten app locales and the ordered section/page list. Section ids arestart,workflows,opencode-setup,remote-access,customize,extensions,desktop,help. The approved 25 pages each appear once;indexcomes first.docs/help/<locale>/<page>.md: one H1 supplies the title and navigation label. Locales areen,fr,de,es,he,ja,ne,ru,tr,zh-Hans.docs/help/i18n/<locale>.json: translated site chrome and section labels. Keep the same keys in every language. Page titles belong in Markdown, not here.docs/help/help.css: square, responsive chrome, light/dark palettes and logical properties for Hebrew RTL. No application styles/runtime are imported.
Every H2/H3 (and deeper heading, if used) needs an explicit ASCII kebab-case id:
## Answer requests {#answer-requests}
### Permissions {#permissions}
[Another page](permissions.md#answer-requests)
[This page](#permissions)

The builder strips the suffix and assigns the id. Do not translate or reorder
ids: every translated page must have exactly the English ordered (level, id) list.
The single H1 is the page title, without an explicit id; an H1 {#id} is an error,
never silently discarded. Link to an H2 section instead.
Ids are unique within a page; content, help-query and help-results are reserved
for site chrome. Avoid raw
HTML headings or images: Markdown supplies the metadata needed for validation.
Inter-page Markdown links become same-locale HTML links with their anchors
intact. HTTPS links stay unchanged. Relative repository-reference links outside
the guide become GitHub links; relative images are copied once into shared
assets/media/, not fetched from remote hosts. Use paths relative to the source
page, including the locale directory.
Translation workflow
Write/update English first, then copy the page to the other locale directories
and translate its prose, H1 and link labels while preserving filenames, heading
ids and local link targets. Use the app's own terminology where relevant.
Add a new page to site.json and provide it in every locale.
Missing translations still build: the selected language's chrome remains, a
translated notice explains the fallback, and the English article has lang="en"
and dir="ltr", including within Hebrew pages. The page's language menu and
hreflang alternates retain its identity in every language. An absent translation
offers a contribution link for that locale; existing pages link to their editor.
Fallback is not validation success. The full check fails for missing translations,
heading-id drift, unresolved links/anchors/images, duplicate or missing heading
ids and invalid page structure. --locale en checks English alone while the
translation work is pending; it does not claim the other locales are ready.
Build and check
npm ci --ignore-scripts
npm run test:help -- --locale en
npm run test:help
npm run build:help
node --import tsx --test packages/ui/src/lib/help-url.test.ts
node scripts/test-help-browser.mjs
Output is dist/help/<locale>/<page>.html, with index.html also serving each
locale directory. Shared assets live under dist/help/assets/. Serve dist/help
with any static HTTP server; no backend, credentials or OpenCode service is
needed. The builder uses the existing marked dependency. To exercise a
throwaway source tree without editing real content:
node scripts/build-help.mjs <output-directory> --content <source-directory>
node scripts/test-help.mjs --locale en --content <source-directory>
The source override needs its own site.json and locale directories; site CSS,
logo and chrome strings still come from this repository. Builder failures are
fatal except absent translations (warnings); heading drift is fatal in both build
and validation. Rebuilds delete only paths recorded by the previous build in
.help-output.json, preserving unrelated files in a caller-supplied output directory.
Tests create and remove only their own temporary directories.
The optional Playwright check renders English, Hebrew, Nepali, Japanese and Chinese
at desktop/intermediate/mobile widths in light/dark mode, checks project-site links,
search states/keyboard/IME, skip-link focus and the script-free fallback, and writes captures to %TEMP%/codenomad-help/ (the OS
temporary directory on other systems). It accepts the same --content override.
Locale navigation and articles need no JavaScript. The root chooser has a tiny inline script,
hash-authorized by its CSP, to select the best supported navigator.languages
match (including zh-* → zh-Hans and iw → he). Plain language links work
with scripting disabled. There are no analytics, remote fonts or remote runtime
requests. Navigation/alternate links work under the GitHub project-site path.
The only other script is first-party docs/help/help-search.js, copied unchanged
to assets and allowed by article CSP (script-src 'self', connect-src 'self').
It loads only the current locale's build-time search-index.json; entries contain
article title, explicit heading id/text and a short section excerpt. Tests resolve
every result to its real HTML anchor. Normalized substring matching supports CJK,
Devanagari and Hebrew without libraries or remote requests. Ctrl/Cmd+K focuses,
arrows select, Enter follows the real link, Escape dismisses/restores focus;
composition and browser Ctrl/Cmd+F are untouched. Empty/no-results/load-failure
states are localized. Search is hidden without JS. Desktop navigation and outline
use CSS-exclusive wide views; narrow layouts use native collapsed disclosures,
so responsive defaults require no extra script. Tables/code scroll locally, inline
code/key chords isolate LTR, and selected rows follow the app's 40%/50% accent-ink tint.
Application entry points
Electron and both Tauri Help-menu branches put CodeNomad Help first, before
the existing update/About items. Native menu labels remain English. The hosts
send open-help to the primary renderer; its existing palette-command dispatch
executes the localized Open help command and uses the current UI locale.
Browser and remote users can run the same command from the palette.
packages/ui/src/lib/help-url.ts owns the base URL and locale→path mapping;
openExternalUrl opens the system browser on native hosts (Electron's existing
new-window policy handles window.open and reports asynchronous opener failures
through a visible host error) or a separate browser tab. Tauri remote windows
have no generic opener/native capability: their owned new-window/navigation policy
hands only credential-free HTTPS URLs under https://neuralnomadsai.github.io/CodeNomad/
on port 443 to the system browser, denying other external targets and native guests.
New-window callbacks recheck the registered window generation before opening.
Help never
navigates the application renderer. Preferences/remote/loading windows without
a primary menu listener fall back to the root chooser. The custom Windows
titlebar's help menu still opens the same native submenu.
Malformed locale tags are rejected before prefix mapping. Opening failures use
localized renderer alerts or a native host error; actions are never replayed.
window.open returning null with noopener is not evidence of failure.
Search suppresses Chromium/WebKit's native search-cancel affordance; the single labelled Clear button retains its 44px touch target.
Publish on GitHub Pages
Pages is enabled with GitHub Actions as the source at https://neuralnomadsai.github.io/CodeNomad/. README continues to link here; the root detects the browser language, while application entry points choose the UI locale directly.
.github/workflows/help-pages.yml checks and builds help on pull requests, but
deploys only dev pushes/manual runs from dev. The build job is read-only;
deployment uses pages: write and id-token: write. Help sources, screenshots,
images, help scripts, shared URL module, manifests/lockfile and .node-version
trigger the workflow. No extra hosting secret is needed.
The full multilingual check intentionally blocks publishing incomplete translations.
The site follows dev, not a versioned archive. Update the guide alongside
user-visible behavior changes. Documentation hosting remains separate from
desktop updater work.