Back to sh0
sh0

Documentation as Product

How we documented 30 CLI commands across a marketing page, dashboard page, and 4 doc pages in 5 languages -- treating documentation as a product feature, not an afterthought.

Thales & Claude | March 27, 2026 7 min sh0
clidocumentationmarketingdashboardsveltei18ndeveloper-experience

The CLI was done. Thirty commands across six categories, audited through six independent sessions, every Critical and Important finding fixed. The code worked.

But working code that no one knows how to use is the same as code that does not exist.

Phase 5 treated documentation as a product deliverable, not an afterthought. Three surfaces, four doc pages, five languages, one session. Here is how we approached it and why documentation strategy matters as much as implementation strategy.

Three Surfaces, Three Audiences

sh0's CLI documentation lives in three places, each serving a different audience:

1. The Marketing Page (sh0.dev/cli)

Audience: Developers evaluating sh0 for the first time.

Goal: Show, do not tell. The marketing page does not explain command flags or error codes. It shows the terminal experience -- what the developer types and what they see -- and makes a promise: "This is what your deployment workflow looks like with sh0."

The hero section features sh0 push:

$ sh0 push
  Pushing my-saas-app
  Detected nodejs (Next.js) -- 92/100 health
  156 files (4.7 MB) packaged
  Uploading OK 1.2s
  Building OK 45.8s
  [ok] Live in 48.3s
  -> https://my-saas-app.sh0.app

Below the hero, a five-step workflow shows the full development cycle: Initialize, Push, Watch, Manage, Open. Each step is one command, one terminal snippet, one sentence explaining what it does.

The command reference section groups all 31 commands by category with one-line descriptions. No flags, no arguments, no examples. Just enough to answer "can sh0 do X?" -- and a link to the docs for how.

2. The Dashboard Page (/cli in the sh0 dashboard)

Audience: Existing sh0 users who want to use the CLI.

Goal: Get them from zero to productive in one page. The dashboard CLI page assumes the developer already understands sh0's concepts (apps, deployments, domains, projects). It focuses on the mechanical questions: How do I install the CLI? How do I authenticate? What commands are available?

The page opens with connection status -- whether the dashboard can detect a running CLI. Below that, the install command (curl -fsSL https://get.sh0.dev | bash), followed by an authentication section showing sh0 login.

The command reference is more detailed than the marketing page: it includes icons for each category, brief descriptions, and the exact command syntax. Twenty-nine commands in a scannable list.

The entire page is localized in five languages: English, French, Spanish, Portuguese, and Swahili.

3. The Documentation Pages (sh0.dev/docs/cli/)

Audience: Developers actively using the CLI who need reference material.

Goal: Complete, accurate, and searchable. Four pages cover the full CLI:

PageContent
OverviewArchitecture, core workflows, getting started
InstallationPlatform-specific install, configuration, environment variables
Push & DeployFull sh0 push reference, .sh0ignore, link files, watch mode
CommandsComplete command reference with all flags, arguments, and examples

The Commands page is the densest -- it documents every flag for every command, including commands from Phase 2-4 that were initially missing from the docs.

The Documentation Debt Problem

Phase 5 ran twice. The first pass happened after Phase 1, documenting only the initial commands: push, login, whoami, and the pre-existing CLI. When Phases 2, 3, and 4 added 15 new commands, the documentation was immediately stale.

The second pass updated all five files to include every command. The diff was significant:

SurfaceBefore (Phase 1 docs)After (Phase 5 update)
Marketing page commands1931
Dashboard commands1429
Docs overview workflows34
Docs commands referencePartialComplete
Undocumented commands100

Ten commands -- init, link, open, config, watch, restart, stop, start, delete, domains -- were completely undocumented between Phase 1 docs and the Phase 5 update. Five more were partially documented (missing flags or incomplete descriptions).

This is the documentation debt pattern: each implementation phase moves faster than the documentation can keep up. The solution is not to document incrementally (which fragments the effort and risks inconsistency) but to batch documentation updates and apply them comprehensively.

The i18n Strategy

The dashboard CLI page ships in five languages. The translation approach follows sh0's existing i18n pattern: a TypeScript object with language keys and string values, selected by the user's locale preference.

typescriptconst translations = {
    en: {
        title: "CLI",
        subtitle: "Control your server from the terminal",
        install_title: "Installation",
        // ...
    },
    fr: {
        title: "CLI",
        subtitle: "Controlez votre serveur depuis le terminal",
        install_title: "Installation",
        // ...
    },
    // es, pt, sw
};

Command names and terminal output are not translated -- sh0 push is sh0 push in every language. Only the surrounding UI text (headings, descriptions, instructions) is localized. This is a deliberate decision: CLI tools are inherently English-language artifacts, and attempting to translate command syntax creates confusion rather than accessibility.

The five target languages reflect sh0's market focus: English (global), French (West and Central Africa), Spanish (growing tech sector), Portuguese (Brazil, Lusophone Africa), Swahili (East Africa).

The Navigation Architecture

Adding a CLI section to the documentation required updating the navigation structure. sh0's docs use a centralized navigation config:

typescript// docs-navigation.ts
export const sections = [
    { title: "Getting Started", items: [...] },
    { title: "AI Assistant", items: [...] },
    { title: "CLI", items: [           // New section
        { title: "Overview", href: "/docs/cli/overview" },
        { title: "Installation", href: "/docs/cli/installation" },
        { title: "Push & Deploy", href: "/docs/cli/push-deploy" },
        { title: "Commands", href: "/docs/cli/commands" },
    ]},
    { title: "API Reference", items: [...] },
    // ...
];

The CLI section sits between "AI Assistant" and "API Reference" in the sidebar. This placement is intentional: the CLI is a more advanced topic than the AI assistant (which requires zero setup) but less specialized than the API reference (which is for integration developers).

The docs index page also received a CLI card -- a visual entry point that matches the style of the existing cards for Getting Started, Deployments, and other sections.

What Good CLI Documentation Looks Like

After building documentation for 30 commands across three surfaces, a pattern emerged for what makes CLI documentation useful:

1. Show the terminal output, not just the command.

Bad: "sh0 push deploys your application."

Good: `` $ sh0 push Pushing my-app Detected nodejs (Next.js) -- 85/100 health 42 files (2.3 MB) packaged -> https://my-app.sh0.app ``

The terminal output tells the developer what to expect. The command alone tells them what to type.

2. Group by workflow, not by alphabet.

Bad: config, cron, delete, deploy, domains, env, export...

Good: Deploy (push, init, link, watch, deploy) -> Lifecycle (restart, stop, start, delete) -> Config (login, whoami, config) -> Management (domains, env, logs, ssh)

Alphabetical order is for reference. Workflow order is for learning.

3. Put the dangerous commands last and mark them.

The delete command appears at the end of the App Lifecycle section, with explicit notes about the confirmation requirement. Destructive commands should never be the first thing a developer sees in a category.

4. One example per command, not five.

The Push & Deploy doc page has extensive examples for sh0 push because it is the primary command. The restart command has one example because one is sufficient. Documentation depth should be proportional to command complexity.

The Build Verification

Both codebases were built after the documentation update:

bash# Website
cd sh0-website && npm run build  # Pass

# Dashboard
cd sh0-core/dashboard && npm run build  # Pass

Documentation pages are Svelte components, not static markdown. They go through the same build process as the application. A broken import, a mismatched i18n key, or a syntax error in a code block will fail the build.

This is one advantage of using a component framework for documentation: the compiler catches documentation bugs.


Next in the series: 16 Commands in One Day: The Complete CLI Story -- How we went from "sh0 needs a push command" to 16 new commands, 2 server endpoints, 6 audit sessions, and zero known bugs -- in a single day.

Share this article:

Responses

Write a response
0/2000
Loading responses...

Related Articles