From bd75538df8c6abd47c2447f5660fcad096250280 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 2 Apr 2026 21:27:24 +0000 Subject: [PATCH 1/8] docs(design): add design doc for CLI and LLM-friendly installation Draft design for @videojs/cli package that solves interactive documentation degrading poorly for LLM consumers (issue #1185). Covers code generation extraction, HumanCase/LLMCase components, and CLI interface design. https://claude.ai/code/session_012GnierNzbMa91BrtdeXBqC --- .../site/cli-llm-friendly-installation.md | 229 ++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 internal/design/site/cli-llm-friendly-installation.md diff --git a/internal/design/site/cli-llm-friendly-installation.md b/internal/design/site/cli-llm-friendly-installation.md new file mode 100644 index 000000000..f479b35bc --- /dev/null +++ b/internal/design/site/cli-llm-friendly-installation.md @@ -0,0 +1,229 @@ +--- +status: draft +date: 2026-04-02 +--- + +# CLI for LLM-Friendly Installation + +A CLI tool (`@videojs/cli`) that generates installation code for Video.js 10, solving the problem of interactive documentation that degrades poorly for LLM consumers. + +## Problem + +The installation page (`site/src/content/docs/how-to/installation.mdx`) is a multi-path interactive guide. Users pick a framework, use case, skin, and renderer through React pickers, and code generation functions produce tailored installation snippets. This works well for humans in a browser. + +The LLM markdown pipeline (`llms-markdown.ts`) captures a single snapshot of the rendered HTML — the default Nanostores state (`html5-video` + `video` skin + `cdn`). Pickers render as bare labels, tabs flatten into unlabeled lists, and the branching logic is invisible. LLMs and other plain-text consumers see one confusing path through a multi-path guide. + +Related: videojs/v10#1185 + +## Solution + +Two changes: + +1. **`@videojs/cli`** — A new package that owns the code generation logic. The CLI takes the same choices as the installation page (framework, use case, skin, renderer, install method) and prints the corresponding code to stdout. The site imports these generators from the CLI package instead of owning them. + +2. **`HumanCase` / `LLMCase` components** — Astro components that conditionally show content to humans or LLMs using the existing `data-llms-ignore` system. The installation MDX wraps interactive pickers in `HumanCase` and CLI instructions in `LLMCase`. Same file, both audiences. + +## Quick Start + +### CLI — Interactive (humans, chatbot-assisted) + +```bash +npx @videojs/cli + +# Prompts: +# ? Framework: (html / react) +# ? Use case: (video / audio / background-video) +# ? Skin: (default / minimal) +# ? Renderer: (html5-video / hls) +# ? Install method: (cdn / npm / pnpm / yarn / bun) ← HTML only +``` + +### CLI — Flags (agentic LLMs) + +```bash +npx @videojs/cli --framework react --use-case video --renderer hls +``` + +### LLMCase in MDX + +```mdx + + + + + + + + + +To generate installation code tailored to your project, run: + +```bash +npx @videojs/cli +``` + +This walks you through the same choices available on the interactive version +of this page: framework, use case, skin, and renderer. + +If you already know your choices, pass them as flags: + +```bash +npx @videojs/cli --framework react --use-case video --skin default --renderer hls +``` + +**Choice reference:** + +| Flag | Options | Default | +|------|---------|---------| +| `--framework` | `html`, `react` | `html` | +| `--use-case` | `video`, `audio`, `background-video` | `video` | +| `--skin` | `default`, `minimal` | `default` | +| `--renderer` | `html5-video`, `html5-audio`, `hls`, `background-video` | depends on use case | +| `--install-method` | `cdn`, `npm`, `pnpm`, `yarn`, `bun` | `npm` (HTML only) | + +Not all combinations are valid. The CLI will error if you pick an incompatible +combination (e.g., `--use-case audio --renderer hls`). + +``` + +## API + +### Generator Functions + +Pure functions extracted from the current site components. No React, no Nanostores, no Node-specific APIs. + +```ts +// @videojs/cli/generators (or similar export path) + +function generateHTMLCode(useCase, skin, renderer, sourceUrl?): string; +function generateJS(useCase, skin, renderer): string; +function generateCdnCode(useCase, skin, renderer): string; +function generateReactCode(useCase, skin, renderer): string; +``` + +These are the same functions currently in `HTMLUsageCodeBlock.tsx`, `ReactCreateCodeBlock.tsx`, and `cdn-code.ts`, moved to `@videojs/cli` and re-exported. + +### Types + +The `UseCase`, `Skin`, `Renderer`, `InstallMethod` types and the `VALID_RENDERERS` constraint map currently live in `site/src/stores/installation.ts`. They move to `@videojs/cli` as the source of truth. The site re-exports or imports them from the CLI package. + +### CLI Binary + +``` +videojs-cli [flags] + +Flags: + --framework + --use-case + --skin + --renderer + --install-method (HTML framework only) + +With no flags: interactive prompts. +With all flags: prints code to stdout, no prompts. +With partial flags: errors, listing what's missing. +``` + +Invalid combinations produce a non-zero exit code and an error message explaining the constraint (e.g., "Renderer 'hls' is not valid for use case 'audio'. Valid renderers: html5-audio"). + +### HumanCase / LLMCase Components + +```astro + + +
+ +
+``` + +```astro + + + +``` + +`HumanCase` renders normally but marks content `data-llms-ignore="all"` so the markdown pipeline strips it. `LLMCase` renders with `hidden` (invisible to browsers) but without `data-llms-ignore`, so the pipeline captures it. + +## Behavior + +### Code Sharing + +The CLI package owns the generation logic. The site is a consumer: + +``` +@videojs/cli (packages/cli) +├── src/ +│ ├── generators/ # Pure code generation functions +│ │ ├── html.ts # generateHTMLCode, generateJS +│ │ ├── react.ts # generateReactCode +│ │ └── cdn.ts # generateCdnCode +│ ├── types.ts # UseCase, Skin, Renderer, InstallMethod, VALID_RENDERERS +│ └── bin.ts # CLI entry point (prompts, flag parsing, stdout) +``` + +Site components import generators: + +```ts +// site/src/components/installation/HTMLUsageCodeBlock.tsx +import { generateHTMLCode, generateJS } from '@videojs/cli/generators'; +import { useStore } from '@nanostores/react'; +import { renderer, skin, useCase } from '@/stores/installation'; + +export default function HTMLUsageCodeBlock() { + const $useCase = useStore(useCase); + // ... same as today, but the function comes from @videojs/cli + return ; +} +``` + +Site stores import types: + +```ts +// site/src/stores/installation.ts +import { atom } from 'nanostores'; +import type { Renderer, Skin, UseCase, InstallMethod } from '@videojs/cli'; + +export const renderer = atom('html5-video'); +// ... +``` + +### Interactive Mode + +When run with no flags, the CLI prompts through each choice in order. Choices constrain subsequent prompts (e.g., selecting `audio` use case filters the renderer list to `html5-audio`). Uses a prompting library like `@inquirer/prompts` or `@clack/prompts`. + +### Flags Mode + +When all flags are provided, the CLI validates the combination, generates code, and prints to stdout with no interactivity. This is the mode agentic LLMs use. A partial set of flags is an error — the CLI does not mix prompts and flags. + +### Discoverability + +Three places LLMs encounter the CLI: + +1. **`LLMCase` on the installation page** — the primary discovery point in framework-specific docs markdown. +2. **`llms.txt` header** — a brief mention that a CLI exists for generating installation code. +3. **Training data / web search** — the CLI's npm page and README surface in LLM training corpora over time. + +## Trade-offs + +| Gain | Cost | +|------|------| +| Single source of truth for code generation | New package to maintain | +| LLMs get actionable instructions instead of garbled UI | CLI must stay in sync with supported renderers/skins | +| Works for agentic LLMs (run it), chat LLMs (recommend it), and humans (prompted by chatbot) | Adds a dependency from site → CLI package | +| Doesn't block future CLI expansion (skin ejection, scaffolding) | Interactive prompting library adds weight to the package | + +## Prior Art + +- **`create-next-app`**, **`create-vite`**, **`npm create`** — Interactive project scaffolding CLIs. These go further (write files, install deps). Our MVP is stdout-only but the interaction pattern is familiar. +- **`llms.txt` convention** — Established pattern for making docs LLM-readable. Our `LLMCase` component extends this by allowing per-section LLM-specific content within existing pages. +- **Starlight / Astro docs** — Other doc frameworks generate `llms.txt` but don't address interactive content degradation. + +## Open Questions + +- **Prompt library choice** — `@inquirer/prompts` (widely used, stable) vs `@clack/prompts` (prettier output, smaller) vs something else? The choice affects package size and DX but not architecture. +- **Export path design** — Should generators be at `@videojs/cli/generators` or a different subpath? Needs to work with the package's `exports` map and not conflict with future subcommands. +- **Partial flags behavior** — Current spec says partial flags are an error. Should the CLI instead prompt only for missing flags? This is friendlier for humans but complicates the "no interactivity with flags" contract for agents. +- **`--source-url` flag** — The site lets users paste a source URL that gets embedded in generated code. Should the CLI support this too? It's not a "choice" in the same way as the others — it's freeform input. +- **Output format** — Should the CLI support `--format json` for machine consumption? The MVP is plain text, but structured output could be useful for tooling later. From 3c822b4cb4c49bfabdbd65f0a0bd5feb5ab4ca42 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 2 Apr 2026 21:38:11 +0000 Subject: [PATCH 2/8] docs(design): trim CLI design doc to focus on decisions, add alternatives https://claude.ai/code/session_012GnierNzbMa91BrtdeXBqC --- .../site/cli-llm-friendly-installation.md | 167 ++++-------------- 1 file changed, 35 insertions(+), 132 deletions(-) diff --git a/internal/design/site/cli-llm-friendly-installation.md b/internal/design/site/cli-llm-friendly-installation.md index f479b35bc..2ef753e33 100644 --- a/internal/design/site/cli-llm-friendly-installation.md +++ b/internal/design/site/cli-llm-friendly-installation.md @@ -5,13 +5,13 @@ date: 2026-04-02 # CLI for LLM-Friendly Installation -A CLI tool (`@videojs/cli`) that generates installation code for Video.js 10, solving the problem of interactive documentation that degrades poorly for LLM consumers. +A CLI tool (`@videojs/cli`) that generates installation code, solving the problem of interactive documentation that degrades for LLM consumers. This is the MVP scope — the same package will later support skin ejection and other workflows. ## Problem -The installation page (`site/src/content/docs/how-to/installation.mdx`) is a multi-path interactive guide. Users pick a framework, use case, skin, and renderer through React pickers, and code generation functions produce tailored installation snippets. This works well for humans in a browser. +The installation page is a multi-path interactive guide. Users pick a framework, use case, skin, and renderer through React pickers, and code generation functions produce tailored snippets. This works well for humans in a browser. -The LLM markdown pipeline (`llms-markdown.ts`) captures a single snapshot of the rendered HTML — the default Nanostores state (`html5-video` + `video` skin + `cdn`). Pickers render as bare labels, tabs flatten into unlabeled lists, and the branching logic is invisible. LLMs and other plain-text consumers see one confusing path through a multi-path guide. +The LLM markdown pipeline captures a single snapshot of the rendered HTML — the default Nanostores state. Pickers render as bare labels, tabs flatten into unlabeled lists, and the branching logic is invisible. LLMs see one confusing path through a multi-path guide. Related: videojs/v10#1185 @@ -19,18 +19,17 @@ Related: videojs/v10#1185 Two changes: -1. **`@videojs/cli`** — A new package that owns the code generation logic. The CLI takes the same choices as the installation page (framework, use case, skin, renderer, install method) and prints the corresponding code to stdout. The site imports these generators from the CLI package instead of owning them. +1. **`@videojs/cli`** — A new package at `packages/cli` that owns the code generation logic. It takes the same choices as the installation page and prints corresponding code to stdout. The site imports these generators instead of owning them — no drift because it's the same code path. Supports interactive prompts (no flags) and pure flag-driven output. -2. **`HumanCase` / `LLMCase` components** — Astro components that conditionally show content to humans or LLMs using the existing `data-llms-ignore` system. The installation MDX wraps interactive pickers in `HumanCase` and CLI instructions in `LLMCase`. Same file, both audiences. +2. **`HumanCase` / `LLMCase` components** — Astro components using the existing `data-llms-ignore` system. The installation MDX wraps interactive pickers in `HumanCase` and CLI instructions in `LLMCase`. Same file, both audiences. ## Quick Start -### CLI — Interactive (humans, chatbot-assisted) +### Interactive (humans, chatbot-assisted) ```bash npx @videojs/cli -# Prompts: # ? Framework: (html / react) # ? Use case: (video / audio / background-video) # ? Skin: (default / minimal) @@ -38,7 +37,7 @@ npx @videojs/cli # ? Install method: (cdn / npm / pnpm / yarn / bun) ← HTML only ``` -### CLI — Flags (agentic LLMs) +### Flags (agentic LLMs) ```bash npx @videojs/cli --framework react --use-case video --renderer hls @@ -51,7 +50,6 @@ npx @videojs/cli --framework react --use-case video --renderer hls - @@ -62,55 +60,20 @@ To generate installation code tailored to your project, run: npx @videojs/cli ``` -This walks you through the same choices available on the interactive version -of this page: framework, use case, skin, and renderer. - If you already know your choices, pass them as flags: ```bash npx @videojs/cli --framework react --use-case video --skin default --renderer hls ``` - -**Choice reference:** - -| Flag | Options | Default | -|------|---------|---------| -| `--framework` | `html`, `react` | `html` | -| `--use-case` | `video`, `audio`, `background-video` | `video` | -| `--skin` | `default`, `minimal` | `default` | -| `--renderer` | `html5-video`, `html5-audio`, `hls`, `background-video` | depends on use case | -| `--install-method` | `cdn`, `npm`, `pnpm`, `yarn`, `bun` | `npm` (HTML only) | - -Not all combinations are valid. The CLI will error if you pick an incompatible -combination (e.g., `--use-case audio --renderer hls`). ``` ## API -### Generator Functions - -Pure functions extracted from the current site components. No React, no Nanostores, no Node-specific APIs. - -```ts -// @videojs/cli/generators (or similar export path) +### CLI -function generateHTMLCode(useCase, skin, renderer, sourceUrl?): string; -function generateJS(useCase, skin, renderer): string; -function generateCdnCode(useCase, skin, renderer): string; -function generateReactCode(useCase, skin, renderer): string; ``` - -These are the same functions currently in `HTMLUsageCodeBlock.tsx`, `ReactCreateCodeBlock.tsx`, and `cdn-code.ts`, moved to `@videojs/cli` and re-exported. - -### Types - -The `UseCase`, `Skin`, `Renderer`, `InstallMethod` types and the `VALID_RENDERERS` constraint map currently live in `site/src/stores/installation.ts`. They move to `@videojs/cli` as the source of truth. The site re-exports or imports them from the CLI package. - -### CLI Binary - -``` -videojs-cli [flags] +npx @videojs/cli [flags] Flags: --framework @@ -119,111 +82,51 @@ Flags: --renderer --install-method (HTML framework only) -With no flags: interactive prompts. -With all flags: prints code to stdout, no prompts. -With partial flags: errors, listing what's missing. -``` - -Invalid combinations produce a non-zero exit code and an error message explaining the constraint (e.g., "Renderer 'hls' is not valid for use case 'audio'. Valid renderers: html5-audio"). - -### HumanCase / LLMCase Components - -```astro - - -
- -
-``` - -```astro - - - +No flags → interactive prompts. +All flags → prints code to stdout. +Partial flags → error listing what's missing. ``` -`HumanCase` renders normally but marks content `data-llms-ignore="all"` so the markdown pipeline strips it. `LLMCase` renders with `hidden` (invisible to browsers) but without `data-llms-ignore`, so the pipeline captures it. +Invalid combinations produce a non-zero exit code and an error explaining the constraint. -## Behavior - -### Code Sharing - -The CLI package owns the generation logic. The site is a consumer: - -``` -@videojs/cli (packages/cli) -├── src/ -│ ├── generators/ # Pure code generation functions -│ │ ├── html.ts # generateHTMLCode, generateJS -│ │ ├── react.ts # generateReactCode -│ │ └── cdn.ts # generateCdnCode -│ ├── types.ts # UseCase, Skin, Renderer, InstallMethod, VALID_RENDERERS -│ └── bin.ts # CLI entry point (prompts, flag parsing, stdout) -``` +Each dimension has a default value. Choices constrain subsequent options (e.g., `audio` use case filters renderers to `html5-audio`). -Site components import generators: - -```ts -// site/src/components/installation/HTMLUsageCodeBlock.tsx -import { generateHTMLCode, generateJS } from '@videojs/cli/generators'; -import { useStore } from '@nanostores/react'; -import { renderer, skin, useCase } from '@/stores/installation'; - -export default function HTMLUsageCodeBlock() { - const $useCase = useStore(useCase); - // ... same as today, but the function comes from @videojs/cli - return ; -} -``` +### Generator Functions -Site stores import types: +Pure functions — no React, no Nanostores, no Node APIs. These are the same functions currently in the site's code block components, extracted to `@videojs/cli` as the source of truth. ```ts -// site/src/stores/installation.ts -import { atom } from 'nanostores'; -import type { Renderer, Skin, UseCase, InstallMethod } from '@videojs/cli'; - -export const renderer = atom('html5-video'); -// ... +function generateHTMLCode(useCase, skin, renderer, sourceUrl?): string; +function generateJS(useCase, skin, renderer): string; +function generateCdnCode(useCase, skin, renderer): string; +function generateReactCode(useCase, skin, renderer): string; ``` -### Interactive Mode +The site components import these and wire Nanostores state as arguments. The CLI calls them with parsed flags. Same functions, different input sources. -When run with no flags, the CLI prompts through each choice in order. Choices constrain subsequent prompts (e.g., selecting `audio` use case filters the renderer list to `html5-audio`). Uses a prompting library like `@inquirer/prompts` or `@clack/prompts`. +### HumanCase / LLMCase -### Flags Mode +`HumanCase` renders normally but marks content `data-llms-ignore="all"` — the markdown pipeline strips it. `LLMCase` renders with `hidden` (invisible in browsers) but without `data-llms-ignore` — the pipeline captures it. -When all flags are provided, the CLI validates the combination, generates code, and prints to stdout with no interactivity. This is the mode agentic LLMs use. A partial set of flags is an error — the CLI does not mix prompts and flags. +## Alternatives Considered -### Discoverability +- **CSS visibility toggle** — Render all variants in the HTML, toggle with CSS so the markdown pipeline captures everything. Simple, but the combinatorial explosion (framework × use case × skin × renderer × install method) makes the output unwieldy and gets worse as options grow. -Three places LLMs encounter the CLI: +- **Separate LLM installation guide** — Purpose-built markdown for LLMs. Optimized for the consumer, but two documents to maintain with guaranteed drift. -1. **`LLMCase` on the installation page** — the primary discovery point in framework-specific docs markdown. -2. **`llms.txt` header** — a brief mention that a CLI exists for generating installation code. -3. **Training data / web search** — the CLI's npm page and README surface in LLM training corpora over time. +- **Expand all variants in the markdown pipeline** — Teach `llms-markdown.ts` to understand the picker components and render every combination under structured headers. Keeps one source of truth, but the output is long and the pipeline needs to understand component semantics it currently ignores. -## Trade-offs +- **One page per combination** — Generate separate pages like `installation/react-video.md`, `installation/html-audio.md`. Each is short and linear, but page count grows multiplicatively and most combinations aren't worth their own page. -| Gain | Cost | -|------|------| -| Single source of truth for code generation | New package to maintain | -| LLMs get actionable instructions instead of garbled UI | CLI must stay in sync with supported renderers/skins | -| Works for agentic LLMs (run it), chat LLMs (recommend it), and humans (prompted by chatbot) | Adds a dependency from site → CLI package | -| Doesn't block future CLI expansion (skin ejection, scaffolding) | Interactive prompting library adds weight to the package | +- **Base example + modification deltas** — Show one canonical installation, describe each axis as a diff. Compact and mirrors how developers think, but privileges one combination as "default" and gets hard to follow beyond 2-3 axes. -## Prior Art +- **Structured data (JSON/YAML)** — Expose the installation matrix as machine-parseable data. Most machine-friendly, but it's a data sheet, not a guide — not useful without an agent that knows what to do with it. -- **`create-next-app`**, **`create-vite`**, **`npm create`** — Interactive project scaffolding CLIs. These go further (write files, install deps). Our MVP is stdout-only but the interaction pattern is familiar. -- **`llms.txt` convention** — Established pattern for making docs LLM-readable. Our `LLMCase` component extends this by allowing per-section LLM-specific content within existing pages. -- **Starlight / Astro docs** — Other doc frameworks generate `llms.txt` but don't address interactive content degradation. +The CLI approach wins because it serves all three consumer types (agentic LLMs run it, chat LLMs recommend it, humans run it when told to), avoids drift by sharing code with the site, and doesn't fight the combinatorial problem — it lets the user narrow their path interactively. ## Open Questions -- **Prompt library choice** — `@inquirer/prompts` (widely used, stable) vs `@clack/prompts` (prettier output, smaller) vs something else? The choice affects package size and DX but not architecture. -- **Export path design** — Should generators be at `@videojs/cli/generators` or a different subpath? Needs to work with the package's `exports` map and not conflict with future subcommands. -- **Partial flags behavior** — Current spec says partial flags are an error. Should the CLI instead prompt only for missing flags? This is friendlier for humans but complicates the "no interactivity with flags" contract for agents. -- **`--source-url` flag** — The site lets users paste a source URL that gets embedded in generated code. Should the CLI support this too? It's not a "choice" in the same way as the others — it's freeform input. -- **Output format** — Should the CLI support `--format json` for machine consumption? The MVP is plain text, but structured output could be useful for tooling later. +- **Prompt library** — `@inquirer/prompts` vs `@clack/prompts` vs something else? +- **Partial flags** — Current spec says partial flags error. Should the CLI instead prompt for only the missing flags? +- **`--source-url` flag** — The site lets users paste a source URL that gets embedded in generated code. Should the CLI support this too? +- **Output format** — Should the CLI support `--format json` for machine consumption down the road? From 7d282fd74506e96d20067454010a5833453117c3 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 2 Apr 2026 21:39:25 +0000 Subject: [PATCH 3/8] docs(design): use `create` subcommand instead of root flags https://claude.ai/code/session_012GnierNzbMa91BrtdeXBqC --- internal/design/site/cli-llm-friendly-installation.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/design/site/cli-llm-friendly-installation.md b/internal/design/site/cli-llm-friendly-installation.md index 2ef753e33..56dff17bf 100644 --- a/internal/design/site/cli-llm-friendly-installation.md +++ b/internal/design/site/cli-llm-friendly-installation.md @@ -28,7 +28,7 @@ Two changes: ### Interactive (humans, chatbot-assisted) ```bash -npx @videojs/cli +npx @videojs/cli create # ? Framework: (html / react) # ? Use case: (video / audio / background-video) @@ -40,7 +40,7 @@ npx @videojs/cli ### Flags (agentic LLMs) ```bash -npx @videojs/cli --framework react --use-case video --renderer hls +npx @videojs/cli create --framework react --use-case video --renderer hls ``` ### LLMCase in MDX @@ -57,13 +57,13 @@ npx @videojs/cli --framework react --use-case video --renderer hls To generate installation code tailored to your project, run: ```bash -npx @videojs/cli +npx @videojs/cli create ``` If you already know your choices, pass them as flags: ```bash -npx @videojs/cli --framework react --use-case video --skin default --renderer hls +npx @videojs/cli create --framework react --use-case video --skin default --renderer hls ``` ``` @@ -73,7 +73,7 @@ npx @videojs/cli --framework react --use-case video --skin default --renderer hl ### CLI ``` -npx @videojs/cli [flags] +npx @videojs/cli create [flags] Flags: --framework From 783b2ddbb3e4965427717a97e351e5d28a3b08d2 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 2 Apr 2026 21:47:13 +0000 Subject: [PATCH 4/8] docs(design): framework required, other flags default https://claude.ai/code/session_012GnierNzbMa91BrtdeXBqC --- .../design/site/cli-llm-friendly-installation.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/internal/design/site/cli-llm-friendly-installation.md b/internal/design/site/cli-llm-friendly-installation.md index 56dff17bf..ab2f16262 100644 --- a/internal/design/site/cli-llm-friendly-installation.md +++ b/internal/design/site/cli-llm-friendly-installation.md @@ -76,21 +76,18 @@ npx @videojs/cli create --framework react --use-case video --skin default --rend npx @videojs/cli create [flags] Flags: - --framework - --use-case - --skin - --renderer - --install-method (HTML framework only) + --framework (required) + --use-case (default: video) + --skin (default: default) + --renderer (default: depends on use case) + --install-method (default: npm, HTML only) No flags → interactive prompts. -All flags → prints code to stdout. -Partial flags → error listing what's missing. +--framework provided → prints code to stdout, defaults for the rest. ``` Invalid combinations produce a non-zero exit code and an error explaining the constraint. -Each dimension has a default value. Choices constrain subsequent options (e.g., `audio` use case filters renderers to `html5-audio`). - ### Generator Functions Pure functions — no React, no Nanostores, no Node APIs. These are the same functions currently in the site's code block components, extracted to `@videojs/cli` as the source of truth. From 5f09e6eef49c39a487f68f64d203a742b004bb78 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 2 Apr 2026 21:50:19 +0000 Subject: [PATCH 5/8] docs(design): tighten CLI design doc Cut implementation details (generator functions, HumanCase/LLMCase mechanics, MDX examples). Trimmed alternatives from six to three. Sharpened prose per writing style guide. https://claude.ai/code/session_012GnierNzbMa91BrtdeXBqC --- .../site/cli-llm-friendly-installation.md | 112 ++++-------------- 1 file changed, 22 insertions(+), 90 deletions(-) diff --git a/internal/design/site/cli-llm-friendly-installation.md b/internal/design/site/cli-llm-friendly-installation.md index ab2f16262..bc84a9532 100644 --- a/internal/design/site/cli-llm-friendly-installation.md +++ b/internal/design/site/cli-llm-friendly-installation.md @@ -3,75 +3,26 @@ status: draft date: 2026-04-02 --- -# CLI for LLM-Friendly Installation +# CLI for LLM-friendly installation -A CLI tool (`@videojs/cli`) that generates installation code, solving the problem of interactive documentation that degrades for LLM consumers. This is the MVP scope — the same package will later support skin ejection and other workflows. +Generate installation code from the command line — the same code the installation page produces, without the interactive UI that breaks in plain text. -## Problem +This is the MVP scope for `@videojs/cli`. The same package will later support skin ejection and other workflows. -The installation page is a multi-path interactive guide. Users pick a framework, use case, skin, and renderer through React pickers, and code generation functions produce tailored snippets. This works well for humans in a browser. +## Problem -The LLM markdown pipeline captures a single snapshot of the rendered HTML — the default Nanostores state. Pickers render as bare labels, tabs flatten into unlabeled lists, and the branching logic is invisible. LLMs see one confusing path through a multi-path guide. +The installation page walks users through framework, use case, skin, and renderer choices via React pickers. Each combination produces different code. This works in a browser, but the LLM markdown pipeline only captures a single default snapshot. Pickers render as bare labels, tabs flatten into unlabeled lists, and the branching logic disappears. LLMs see one confusing path through a multi-path guide. Related: videojs/v10#1185 ## Solution -Two changes: - -1. **`@videojs/cli`** — A new package at `packages/cli` that owns the code generation logic. It takes the same choices as the installation page and prints corresponding code to stdout. The site imports these generators instead of owning them — no drift because it's the same code path. Supports interactive prompts (no flags) and pure flag-driven output. - -2. **`HumanCase` / `LLMCase` components** — Astro components using the existing `data-llms-ignore` system. The installation MDX wraps interactive pickers in `HumanCase` and CLI instructions in `LLMCase`. Same file, both audiences. - -## Quick Start +**`@videojs/cli create`** — a `create` subcommand that takes the same choices as the installation page and prints the corresponding code to stdout. The CLI owns the code generation functions. The site imports them — no drift because both run the same code path. -### Interactive (humans, chatbot-assisted) - -```bash -npx @videojs/cli create - -# ? Framework: (html / react) -# ? Use case: (video / audio / background-video) -# ? Skin: (default / minimal) -# ? Renderer: (html5-video / hls) -# ? Install method: (cdn / npm / pnpm / yarn / bun) ← HTML only -``` - -### Flags (agentic LLMs) - -```bash -npx @videojs/cli create --framework react --use-case video --renderer hls -``` - -### LLMCase in MDX - -```mdx - - - - - - - - -To generate installation code tailored to your project, run: - -```bash -npx @videojs/cli create -``` - -If you already know your choices, pass them as flags: - -```bash -npx @videojs/cli create --framework react --use-case video --skin default --renderer hls -``` - -``` +**`HumanCase` / `LLMCase` components** — Astro components that show different content to browsers and the LLM markdown pipeline. The installation MDX wraps interactive pickers in `HumanCase` and CLI instructions in `LLMCase`. Same file, both audiences. Three consumer types are covered: agentic LLMs run the CLI directly, chat LLMs recommend it to the user, and humans run it when prompted. ## API -### CLI - ``` npx @videojs/cli create [flags] @@ -79,51 +30,32 @@ Flags: --framework (required) --use-case (default: video) --skin (default: default) - --renderer (default: depends on use case) + --renderer (default: per use case) --install-method (default: npm, HTML only) - -No flags → interactive prompts. ---framework provided → prints code to stdout, defaults for the rest. ``` -Invalid combinations produce a non-zero exit code and an error explaining the constraint. +No flags starts interactive prompts. With `--framework`, the CLI prints code to stdout and defaults the rest. Invalid combinations exit non-zero with an error explaining the constraint. -### Generator Functions - -Pure functions — no React, no Nanostores, no Node APIs. These are the same functions currently in the site's code block components, extracted to `@videojs/cli` as the source of truth. +```bash +# Interactive +npx @videojs/cli create -```ts -function generateHTMLCode(useCase, skin, renderer, sourceUrl?): string; -function generateJS(useCase, skin, renderer): string; -function generateCdnCode(useCase, skin, renderer): string; -function generateReactCode(useCase, skin, renderer): string; +# Flags — defaults everything except framework and renderer +npx @videojs/cli create --framework react --renderer hls ``` -The site components import these and wire Nanostores state as arguments. The CLI calls them with parsed flags. Same functions, different input sources. - -### HumanCase / LLMCase - -`HumanCase` renders normally but marks content `data-llms-ignore="all"` — the markdown pipeline strips it. `LLMCase` renders with `hidden` (invisible in browsers) but without `data-llms-ignore` — the pipeline captures it. - -## Alternatives Considered - -- **CSS visibility toggle** — Render all variants in the HTML, toggle with CSS so the markdown pipeline captures everything. Simple, but the combinatorial explosion (framework × use case × skin × renderer × install method) makes the output unwieldy and gets worse as options grow. - -- **Separate LLM installation guide** — Purpose-built markdown for LLMs. Optimized for the consumer, but two documents to maintain with guaranteed drift. - -- **Expand all variants in the markdown pipeline** — Teach `llms-markdown.ts` to understand the picker components and render every combination under structured headers. Keeps one source of truth, but the output is long and the pipeline needs to understand component semantics it currently ignores. +## Alternatives considered -- **One page per combination** — Generate separate pages like `installation/react-video.md`, `installation/html-audio.md`. Each is short and linear, but page count grows multiplicatively and most combinations aren't worth their own page. +- **CSS visibility toggle** — Render all variants in HTML, toggle visibility with CSS so the markdown pipeline captures everything. The combinatorial explosion (framework × use case × skin × renderer × install method) makes the output unwieldy, and it gets worse as we add options. -- **Base example + modification deltas** — Show one canonical installation, describe each axis as a diff. Compact and mirrors how developers think, but privileges one combination as "default" and gets hard to follow beyond 2-3 axes. +- **Separate LLM guide** — Write a purpose-built markdown page for LLMs. Two documents to maintain, guaranteed drift. -- **Structured data (JSON/YAML)** — Expose the installation matrix as machine-parseable data. Most machine-friendly, but it's a data sheet, not a guide — not useful without an agent that knows what to do with it. +- **Expand variants in the markdown pipeline** — Teach `llms-markdown.ts` to understand the picker components and render every combination under structured headers. The pipeline would need to understand component semantics it currently ignores, and the output would be long. -The CLI approach wins because it serves all three consumer types (agentic LLMs run it, chat LLMs recommend it, humans run it when told to), avoids drift by sharing code with the site, and doesn't fight the combinatorial problem — it lets the user narrow their path interactively. +The CLI avoids the combinatorial problem entirely — it lets the consumer narrow their own path. -## Open Questions +## Open questions - **Prompt library** — `@inquirer/prompts` vs `@clack/prompts` vs something else? -- **Partial flags** — Current spec says partial flags error. Should the CLI instead prompt for only the missing flags? -- **`--source-url` flag** — The site lets users paste a source URL that gets embedded in generated code. Should the CLI support this too? -- **Output format** — Should the CLI support `--format json` for machine consumption down the road? +- **`--source-url` flag** — The site lets users paste a source URL that gets embedded in generated code. Should the CLI support this? +- **Output format** — Should the CLI support `--format json` for machine consumption later? From f571eef8b0a621f82d3f8b6193198104997645c8 Mon Sep 17 00:00:00 2001 From: Darius Cepulis Date: Thu, 2 Apr 2026 16:55:55 -0500 Subject: [PATCH 6/8] wip: edits --- .../design/site/cli-llm-friendly-installation.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/internal/design/site/cli-llm-friendly-installation.md b/internal/design/site/cli-llm-friendly-installation.md index bc84a9532..f5016ba1b 100644 --- a/internal/design/site/cli-llm-friendly-installation.md +++ b/internal/design/site/cli-llm-friendly-installation.md @@ -5,9 +5,9 @@ date: 2026-04-02 # CLI for LLM-friendly installation -Generate installation code from the command line — the same code the installation page produces, without the interactive UI that breaks in plain text. +Generate installation code from the command line. It's docs/installation.md, but without the interactive UI that breaks in plain text. -This is the MVP scope for `@videojs/cli`. The same package will later support skin ejection and other workflows. +This means... it's finally time for `@videojs/cli`. The same package will later support skin ejection and other workflows. ## Problem @@ -19,7 +19,7 @@ Related: videojs/v10#1185 **`@videojs/cli create`** — a `create` subcommand that takes the same choices as the installation page and prints the corresponding code to stdout. The CLI owns the code generation functions. The site imports them — no drift because both run the same code path. -**`HumanCase` / `LLMCase` components** — Astro components that show different content to browsers and the LLM markdown pipeline. The installation MDX wraps interactive pickers in `HumanCase` and CLI instructions in `LLMCase`. Same file, both audiences. Three consumer types are covered: agentic LLMs run the CLI directly, chat LLMs recommend it to the user, and humans run it when prompted. +**`HumanCase` / `LLMCase` MDX components** — Astro components that show different content to browsers and the LLM markdown pipeline. installation.mdx wraps interactive pickers in `HumanCase` and CLI instructions in `LLMCase`. Same file, both audiences. Three consumer types are covered: humans still have their react-powered interactive web page, agentic LLMs run the CLI directly, chat LLMs recommend the CLI to the user. ## API @@ -31,7 +31,7 @@ Flags: --use-case (default: video) --skin (default: default) --renderer (default: per use case) - --install-method (default: npm, HTML only) + --install-method (default: npm) ``` No flags starts interactive prompts. With `--framework`, the CLI prints code to stdout and defaults the rest. Invalid combinations exit non-zero with an error explaining the constraint. @@ -54,8 +54,11 @@ npx @videojs/cli create --framework react --renderer hls The CLI avoids the combinatorial problem entirely — it lets the consumer narrow their own path. -## Open questions +## Open questions for now - **Prompt library** — `@inquirer/prompts` vs `@clack/prompts` vs something else? - **`--source-url` flag** — The site lets users paste a source URL that gets embedded in generated code. Should the CLI support this? + +## Open questions for later +- **Mux Uploader** — idk how we'd even reproduce this in a CLI but it would be so cool - **Output format** — Should the CLI support `--format json` for machine consumption later? From 27f4c3ba0769c1006f49605bf14a3315480a4a36 Mon Sep 17 00:00:00 2001 From: Darius Cepulis Date: Fri, 3 Apr 2026 09:10:25 -0500 Subject: [PATCH 7/8] docs(design): address PR review feedback on CLI design doc Rename --use-case to --preset, --renderer to --media. Promote --source-url from open question to API section. Add broader --framework scope as open question for later. Note clack preference. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../design/site/cli-llm-friendly-installation.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/internal/design/site/cli-llm-friendly-installation.md b/internal/design/site/cli-llm-friendly-installation.md index f5016ba1b..3a1da12e6 100644 --- a/internal/design/site/cli-llm-friendly-installation.md +++ b/internal/design/site/cli-llm-friendly-installation.md @@ -28,20 +28,23 @@ npx @videojs/cli create [flags] Flags: --framework (required) - --use-case (default: video) + --preset (default: video) --skin (default: default) - --renderer (default: per use case) + --media (default: per preset) + --source-url (default: per media) --install-method (default: npm) ``` +When no `--source-url` is provided, the CLI uses a default demo URL matching the media type (HLS gets an `.m3u8`, others get `.mp4`). When a URL is provided, the CLI auto-detects the media type from the file extension (`.m3u8` → HLS, `.mp4`/`.webm` → HTML5 Video, `.mp3`/`.wav` → HTML5 Audio) — matching the installation page's detection behavior. A poster URL is included in defaults. + No flags starts interactive prompts. With `--framework`, the CLI prints code to stdout and defaults the rest. Invalid combinations exit non-zero with an error explaining the constraint. ```bash # Interactive npx @videojs/cli create -# Flags — defaults everything except framework and renderer -npx @videojs/cli create --framework react --renderer hls +# Flags — defaults everything except framework and media +npx @videojs/cli create --framework react --media hls ``` ## Alternatives considered @@ -56,9 +59,9 @@ The CLI avoids the combinatorial problem entirely — it lets the consumer narro ## Open questions for now -- **Prompt library** — `@inquirer/prompts` vs `@clack/prompts` vs something else? -- **`--source-url` flag** — The site lets users paste a source URL that gets embedded in generated code. Should the CLI support this? +- **Prompt library** — `@inquirer/prompts` vs `@clack/prompts` vs something else? Rahim likes clack so leaning that way, but needs more investigation. ## Open questions for later +- **Broader `--framework` scope** — Should `--framework` expand beyond `html`/`react` to include app frameworks (Next, Astro, SvelteKit, etc.)? Would affect scaffolding and might need a separate flag for html vs react when targeting framework-agnostic tools like Astro. - **Mux Uploader** — idk how we'd even reproduce this in a CLI but it would be so cool - **Output format** — Should the CLI support `--format json` for machine consumption later? From b9855809e0eaa6d09dc6e273d0ee084700e630c1 Mon Sep 17 00:00:00 2001 From: Darius Cepulis Date: Fri, 3 Apr 2026 10:00:52 -0500 Subject: [PATCH 8/8] wip: oh crap it's a docs cli --- .../site/cli-llm-friendly-installation.md | 91 ++++++++++++++++--- 1 file changed, 77 insertions(+), 14 deletions(-) diff --git a/internal/design/site/cli-llm-friendly-installation.md b/internal/design/site/cli-llm-friendly-installation.md index 3a1da12e6..18aabbd75 100644 --- a/internal/design/site/cli-llm-friendly-installation.md +++ b/internal/design/site/cli-llm-friendly-installation.md @@ -3,31 +3,31 @@ status: draft date: 2026-04-02 --- -# CLI for LLM-friendly installation +# CLI for LLM-friendly installation docs -Generate installation code from the command line. It's docs/installation.md, but without the interactive UI that breaks in plain text. +Generate installation code from the command line. It's docs/installation.md, but without the interactive React UI that breaks in plain text. This means... it's finally time for `@videojs/cli`. The same package will later support skin ejection and other workflows. ## Problem -The installation page walks users through framework, use case, skin, and renderer choices via React pickers. Each combination produces different code. This works in a browser, but the LLM markdown pipeline only captures a single default snapshot. Pickers render as bare labels, tabs flatten into unlabeled lists, and the branching logic disappears. LLMs see one confusing path through a multi-path guide. +The installation page walks users through framework, preset, skin, and media choices via React pickers. Each combination produces different code. This works in a browser, but the LLM markdown pipeline only captures a single default snapshot. Pickers render as bare labels, tabs flatten into unlabeled lists, and the branching logic disappears. LLMs see one confusing path through a multi-path guide. Related: videojs/v10#1185 ## Solution -**`@videojs/cli create`** — a `create` subcommand that takes the same choices as the installation page and prints the corresponding code to stdout. The CLI owns the code generation functions. The site imports them — no drift because both run the same code path. +**`@videojs/cli docs how-to/installation`** — a command that takes the same choices as the installation page and prints the corresponding code to stdout. **`HumanCase` / `LLMCase` MDX components** — Astro components that show different content to browsers and the LLM markdown pipeline. installation.mdx wraps interactive pickers in `HumanCase` and CLI instructions in `LLMCase`. Same file, both audiences. Three consumer types are covered: humans still have their react-powered interactive web page, agentic LLMs run the CLI directly, chat LLMs recommend the CLI to the user. ## API ``` -npx @videojs/cli create [flags] +npx @videojs/cli docs how-to/installation [flags] Flags: - --framework (required) + --framework (see "framework resolution" below.) --preset (default: video) --skin (default: default) --media (default: per preset) @@ -41,12 +41,79 @@ No flags starts interactive prompts. With `--framework`, the CLI prints code to ```bash # Interactive -npx @videojs/cli create +npx @videojs/cli docs how-to/installation # Flags — defaults everything except framework and media -npx @videojs/cli create --framework react --media hls +npx @videojs/cli docs how-to/installation --framework react --media hls ``` +## Single source of truth +If this command is serving the same content as installation.mdx... how do we keep the two in sync? Honestly, that's a tricky question. Obviously we have a single source of truth, but where is that truth? + +I'm thinking that the codegen is going to live in the site and be imported by the CLI. After all, that's what this CLI is doing. Taking content from the site and displaying it in the CLI. + +And then... it's neat that this CLI can generate code examples, but what of the content around the code examples? I'm a bit fuzzier on this, but I'm imagining the CLI will take installation.md and string-replace the static code examples with the generated ones. + +## Wait, I noticed you called this @videojs/cli docs... + +PLOT TWIST. + +Yeah. So we had a few conversations around this and there was this desire to scope creep. To write to the directory. Stuff like that. But really, the only problem I'm trying to solve right now is... how do I serve _this_ doc to an LLM? + +Calling this utility @videojs/cli docs how-to/installation really clarifies things for me. Obvious scope, obvious implementation, obvious consumption to the user. + +Aaaand... I mean, we already have markdown docs lying around... it seems trivial to just... copy them over here, right? Why not serve all the docs through the cli? It'll be nice that they're versioned and local. + +### @videojs/cli docs API + +#### Reading a doc + +``` +npx @videojs/cli docs [--framework ] +``` + +The slug mirrors the site's URL structure. For example, the page at `/docs/framework/react/how-to/installation/` is: + +``` +npx @videojs/cli docs how-to/installation --framework react +``` + +Most pages serve their markdown directly. Pages with interactive content (like installation) override the default behavior and accept additional flags. + +#### Framework resolution + +Every doc requires a framework. Resolution order: + +1. **`--framework` flag** — overrides saved preference, doesn't change it +2. **Saved preference** — set via `config set` +3. **Interactive prompt** — if nothing above resolves, the CLI asks and suggests saving the preference: + +``` +💡 Tip: run `npx @videojs/cli config set framework XYZ` to save this preference +``` + +#### Listing sections + +``` +npx @videojs/cli docs --list +``` + +Lists available doc pages, built from the site's sidebar config. Follows framework resolution rules above + +#### Config + +``` +npx @videojs/cli config set +npx @videojs/cli config get +npx @videojs/cli config list +``` + +Persists to `~/.videojs/config.json`. Currently the only setting is `framework`. + +## Anything else? + +I'm thinking of using bombshell-dev/clack, /args/ and /tab because it's a trendy combo and Rahim likes it. Idk. We can throw it out later. This seems portable. + ## Alternatives considered - **CSS visibility toggle** — Render all variants in HTML, toggle visibility with CSS so the markdown pipeline captures everything. The combinatorial explosion (framework × use case × skin × renderer × install method) makes the output unwieldy, and it gets worse as we add options. @@ -57,11 +124,7 @@ npx @videojs/cli create --framework react --media hls The CLI avoids the combinatorial problem entirely — it lets the consumer narrow their own path. -## Open questions for now - -- **Prompt library** — `@inquirer/prompts` vs `@clack/prompts` vs something else? Rahim likes clack so leaning that way, but needs more investigation. - ## Open questions for later -- **Broader `--framework` scope** — Should `--framework` expand beyond `html`/`react` to include app frameworks (Next, Astro, SvelteKit, etc.)? Would affect scaffolding and might need a separate flag for html vs react when targeting framework-agnostic tools like Astro. +- **Broader `--framework` scope** — Should `--framework` expand beyond `html`/`react` to include app frameworks (Next, Astro, SvelteKit, etc.)? That's a good conversation that affects the docs, too, so I'm going to leave that aside for now. +- **MCP** — is a thing - **Mux Uploader** — idk how we'd even reproduce this in a CLI but it would be so cool -- **Output format** — Should the CLI support `--format json` for machine consumption later?