diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..6cb76f4
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,37 @@
+name: CI
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+ workflow_dispatch:
+
+jobs:
+ build-test:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ global-json-file: global.json
+
+ - name: Restore
+ run: dotnet restore shelldocs.slnx
+
+ - name: Build
+ run: dotnet build shelldocs.slnx --configuration Release --no-restore
+
+ - name: Test
+ run: dotnet test shelldocs.slnx --configuration Release --no-build --verbosity normal
+
+ # Smoke test: verify the CLI packs cleanly as a global tool
+ - name: Pack CLI
+ run: dotnet pack src/ShellDocs.CLI --configuration Release --output nupkgs
+
+ - name: Verify CLI installs + runs
+ run: |
+ dotnet tool install --global --add-source ./nupkgs ShellDocs.CLI --prerelease
+ shelldocs --help
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..266d540
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,63 @@
+# .NET build output
+[Bb]in/
+[Oo]bj/
+[Rr]elease/
+[Dd]ebug/
+*.user
+*.suo
+*.userosscache
+*.sln.docstates
+*.dll
+*.pdb
+*.exe
+*.cache
+
+# NuGet
+*.nupkg
+*.snupkg
+project.lock.json
+project.assets.json
+packages/
+!.nuget/packages/
+.nuget/
+
+# Test results
+[Tt]est[Rr]esult*/
+[Cc]overage*/
+
+# IDE
+.vs/
+.vscode/
+.idea/
+*.swp
+*.swo
+
+# JetBrains Rider
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# OS
+.DS_Store
+Thumbs.db
+
+# Node (for Tailwind CLI + Shiki)
+node_modules/
+package-lock.json
+yarn.lock
+pnpm-lock.yaml
+
+# ShellDocs — local build artifacts
+publish/
+dist/
+.shelldocs/
+*.shellui-classes-generated
+
+# Environment
+.env
+.env.*
+!.env.example
+
+# Logs
+*.log
+logs/
diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 0000000..6e9259b
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,46 @@
+
+
+
+ net10.0
+ latest
+ enable
+ enable
+ false
+ Nullable
+ true
+ $(NoWarn);CS1591
+
+
+
+
+ true
+
+
+
+
+ ShellUI
+ ShellUI
+ Copyright © 2026 ShellUI
+ MIT
+ https://github.com/shellui-dev/shelldocs
+ https://github.com/shellui-dev/shelldocs
+ git
+ blazor;docs;documentation;framework;shellui;shadcn;fumadocs;tailwind
+ README.md
+ true
+ snupkg
+ true
+ true
+
+
+
+
+ false
+
+
+
+
+
+
+
+
diff --git a/Directory.Packages.props b/Directory.Packages.props
new file mode 100644
index 0000000..b1efe97
--- /dev/null
+++ b/Directory.Packages.props
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..a70742b
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 ShellUI
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
index 364802f..6f55a6b 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,92 @@
-# shelldocs
-shelldocs framework for writing docs using shellui
+# ShellDocs
+
+**The docs framework for .NET.** Beautiful, animated, Cmd+K-searchable documentation sites, powered by Blazor and Tailwind. Compose with ShellUI (or any Blazor component library) — like fumadocs composes with shadcn/ui.
+
+> Status: **`0.1.0-alpha` in progress.** Not yet published to NuGet. See [ROADMAP](docs/ROADMAP.md).
+
+## Why ShellDocs
+
+Every .NET UI library ends up hand-rolling their own docs site. MudBlazor, Radzen, AvaloniaUI — each spent months rebuilding a sidebar, a search box, a code block, a theme toggle, from scratch. None of it is reusable.
+
+ShellDocs is the "just use this" answer. It's the docs framework for the whole .NET ecosystem.
+
+- **Markdown authoring** with YAML frontmatter, inline Razor tags, and live component previews (`` ```razor:preview ``)
+- **File-based routing** — drop a `.md` in `content/` and it's a page
+- **Cmd+K search** with a build-time client-side index — no backend needed
+- **Blazor-native** — components render as real Razor, not iframes, not screenshots
+- **Composable with any Blazor component library** — ShellUI, MudBlazor, Radzen, your own
+- **Tailwind CSS v4** — same aesthetic as ShellUI + shadcn, same theme tokens for interop
+- **Animated** — page transitions, sidebar collapses, scroll-spy, `prefers-reduced-motion` aware
+- **Static site output** — deploy to GitHub Pages, Vercel, Netlify, Cloudflare, anywhere
+
+## Quick start
+
+```bash
+# Create a new Blazor WASM app
+dotnet new blazorwasm -n MyDocs
+cd MyDocs
+
+# Install the ShellDocs CLI
+dotnet tool install -g ShellDocs.CLI
+
+# Initialize the docs site
+shelldocs init
+
+# Author content in Markdown
+shelldocs new page introduction
+
+# Develop with hot-reload
+shelldocs dev
+
+# Ship it
+shelldocs build
+```
+
+## Coexists with ShellUI (and any Blazor UI library)
+
+ShellDocs uses the same Tailwind v4 setup and CSS variable contract as ShellUI. Both libraries share the same theme tokens (`--background`, `--foreground`, `--primary`, `--border`, `--radius`, etc.), so you can drop them into the same page and they compose seamlessly — the fumadocs + shadcn pattern, ported to .NET.
+
+```razor
+@* Your docs page — ShellUI components inline in Markdown *@
+A ShellUI button
+A ShellDocs callout
+```
+
+Under the hood ShellDocs takes a hard dependency on `ShellUI.Components` for base primitives (`Button`, `Dialog`, `Command`, `Sidebar`, etc.). Zero style clash.
+
+## Package family
+
+| Package | Purpose |
+|---|---|
+| [`ShellDocs.CLI`](src/ShellDocs.CLI) | Global tool — `shelldocs init`, `shelldocs new`, `shelldocs dev`, `shelldocs build` |
+| [`ShellDocs.Components`](src/ShellDocs.Components) | RCL — `DocsLayout`, `DocsSidebar`, `CodeBlock`, `SearchDialog`, `TableOfContents`, etc. |
+| [`ShellDocs.Markdown`](src/ShellDocs.Markdown) | Markdig pipeline — frontmatter, `razor:preview` fences, inline Razor tags |
+| [`ShellDocs.Core`](src/ShellDocs.Core) | Navigation graph, search index model, routing helpers. Blazor-agnostic. |
+| [`ShellDocs.Templates`](src/ShellDocs.Templates) | Content used by `ShellDocs.CLI` scaffolding |
+
+Optional / v2:
+
+- **`ShellDocs.Xml`** — extract `` from XML doc comments
+- **`ShellDocs.Themes.Fuma`**, **`ShellDocs.Themes.Nextra`** — theme presets
+- **`ShellDocs.OpenApi`** — OpenAPI spec → API reference pages
+
+## Documentation
+
+- [Design](docs/DESIGN.md) — what ShellDocs is, positioning, primitives, ecosystem story
+- [Roadmap](docs/ROADMAP.md) — branch-by-branch implementation plan
+- [Architecture](docs/ARCHITECTURE.md) — technical architecture: package boundaries, service registration, markdown pipeline, navigation graph, search index
+
+Once we ship `0.2.0-alpha`, official docs will live at **[shelldocs.dev](https://shelldocs.dev)** (dogfooded on ShellDocs itself).
+
+## Related projects
+
+- [ShellUI](https://github.com/shellui-dev/shellui) — the Blazor component library ShellDocs is built with
+- [shellui.dev](https://github.com/shellui-dev/shellui.dev) *(coming soon)* — ShellUI's own docs site, built with ShellDocs
+
+## Contributing
+
+`0.1.0-alpha` is scaffolding-first — architecture and API surface are still moving. Once we hit `0.2.0-alpha`, we'll open up contributions with a proper `CONTRIBUTING.md`.
+
+## License
+
+[MIT](LICENSE) — do whatever you want, no warranty.
diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md
new file mode 100644
index 0000000..3538774
--- /dev/null
+++ b/docs/ARCHITECTURE.md
@@ -0,0 +1,451 @@
+# ShellDocs Architecture
+
+Technical architecture. Consumers won't read this; contributors and future-you will.
+
+For high-level design see [DESIGN.md](DESIGN.md); for what ships when see [ROADMAP.md](ROADMAP.md).
+
+---
+
+## High-level dataflow
+
+```
+┌────────────────────────────────────────────────────────────────────────┐
+│ Build time │
+│ │
+│ content/**/*.md ──────► ShellDocs.Markdown ──────► Rendered pages │
+│ │ (Markdig) │ │
+│ │ │ │
+│ ▼ ▼ │
+│ Frontmatter ────► NavigationGraph ────► SearchIndexBuilder │
+│ (ShellDocs.Core) (ShellDocs.Core) │
+│ │ │
+│ ▼ │
+│ search-index.json │
+│ (wwwroot/) │
+└────────────────────────────────────────────────────────────────────────┘
+
+┌────────────────────────────────────────────────────────────────────────┐
+│ Runtime (browser, Blazor WASM) │
+│ │
+│ URL /docs/button │
+│ │ │
+│ ▼ │
+│ Router ──► DocsPage ──► NavigationGraph.ResolveByUrl │
+│ │ │ │
+│ │ └──► NavigationNode │
+│ │ │
+│ ▼ │
+│ MarkdownRenderer ──► MarkupString + component-slot list │
+│ │ │
+│ │ slots contain: … │
+│ │ │
+│ ▼ │
+│ DynamicComponent renders each slot via TypeRegistry │
+└────────────────────────────────────────────────────────────────────────┘
+```
+
+---
+
+## Package boundaries
+
+### `ShellDocs.Core`
+
+**Purpose:** framework-agnostic building blocks. Zero dependency on Blazor.
+
+**Public API:**
+- `NavigationNode` — POCO with `Url`, `Title`, `Description`, `Category`, `Order`, `Headings`, `Path`, `Children`
+- `NavigationGraph` — tree wrapper with `ResolveByUrl(string)`, `GetPrevNext(NavigationNode)`, `GetBreadcrumb(NavigationNode)`, `Flatten()`
+- `NavigationGraphBuilder` — takes `contentRoot` path + `FrontmatterParser`, returns `NavigationGraph`
+- `FrontmatterParser` — YamlDotNet-backed, returns `Dictionary`
+- `SearchIndexEntry` — POCO for one page's search entry
+- `SearchIndexBuilder` — walks `NavigationGraph` + rendered content, emits `IEnumerable`
+
+**Depends on:** Markdig (for AST types only — no rendering), YamlDotNet, `System.Text.Json`
+
+**Why separate:** static site generators, external tooling, or non-Blazor consumers could reuse the graph + index logic without pulling in Blazor.
+
+### `ShellDocs.Markdown`
+
+**Purpose:** turn `.md` files into Razor-renderable output with typed component slots.
+
+**Public API:**
+- `MarkdownPipelineFactory` — configures a Markdig pipeline with all custom extensions
+- `MarkdownRenderer` — takes markdown text or file path, returns `RenderedDocument`
+- `RenderedDocument { MarkupString Html, List Slots, DocumentFrontmatter Frontmatter, List Headings }`
+- `ComponentSlot { Guid Id, Type ComponentType, Dictionary Parameters, RenderFragment? ChildContent }`
+- `TypeRegistry` — maps `string tagName` → `Type componentType`; consumers register their types
+
+**Depends on:** `ShellDocs.Core`, Markdig, YamlDotNet
+
+**Key design decisions:**
+- **Two-pass rendering.** First pass: Markdig turns markdown into HTML + placeholder `` markers for component tags. Second pass: `MarkdownContent` component walks its own DOM (or better: uses a `RenderTreeBuilder` on the AST directly) and swaps placeholders for `` calls.
+- **`razor:preview` blocks are two things.** Markdown fence with language `razor:preview` → a `` slot with two children: a live-rendered `` for the "Preview" tab and a `` for the "Code" tab.
+- **Inline tags are strict.** ` ` in markdown must match a registered type. Unknown tags render as escaped text with a build-time warning (not a runtime crash).
+
+### `ShellDocs.Components`
+
+**Purpose:** the UI. RCL — everyone's entry point.
+
+**Public API:** the primitives listed in [DESIGN.md](DESIGN.md) — `DocsLayout`, `DocsHeader`, `DocsSidebar`, `CodeBlock`, `SearchDialog`, etc.
+
+**Depends on:** `ShellDocs.Core`, `ShellDocs.Markdown`, `ShellUI.Components`
+
+**Key design decisions:**
+- **`AddShellDocs()` service extension.** Consumer's `Program.cs` calls one method to register `NavigationGraph`, `MarkdownRenderer`, `TypeRegistry`, `IJSRuntime` interop wrappers, current theme.
+- **Cascading values everywhere.** `NavigationGraph`, current theme, and current page context are cascaded from `DocsLayout` so child components can consume them without prop-drilling.
+- **`` for component rendering.** Standard Blazor primitive — takes a `Type` + `Dictionary` params. Works with any registered component.
+- **No JS beyond what's necessary.** Shiki (highlighting), Motion One (animation fallback), IntersectionObserver (scroll-spy). Everything else pure Blazor.
+
+### `ShellDocs.CLI`
+
+**Purpose:** developer ergonomics.
+
+**Public API:** commands, not a library.
+- `shelldocs init [--yes] [--theme ]`
+- `shelldocs new page `
+- `shelldocs new component-page `
+- `shelldocs dev [--port ]`
+- `shelldocs build [--output ]`
+- `shelldocs preview [--variant ]`
+
+**Depends on:** `System.CommandLine`, `Spectre.Console`, `ShellDocs.Templates`
+
+**Key design decisions:**
+- **`init` is idempotent.** Detects existing setup and skips already-done steps. Fresh consumers get everything; existing consumers can rerun to pull in new defaults.
+- **`dev` is `dotnet watch` + markdown watcher.** Two file watchers: `dotnet-watch` handles `.razor` / `.cs` reload; a second watcher watches `content/**/*.md` and pings the running app via a well-known endpoint to invalidate the navigation graph.
+- **`build` is `dotnet publish` + post-processing.** Publish, then rewrite base-href, generate search index, copy `index.html` → `404.html`. Same pattern the ShellUI `fix/preview-app` branch uses.
+
+### `ShellDocs.Templates`
+
+**Purpose:** file content used by `ShellDocs.CLI`.
+
+**Public API:** static classes with `Content` string properties, mirroring the pattern from `ShellUI.Templates`.
+
+**Depends on:** nothing (or `ShellDocs.Core` for the `NavigationNode` POCO if templates need it).
+
+**Why separate from CLI:** allows the templates to be updated (and versioned) independently. Also allows the CLI to be a small binary while templates carry the bulk of the bytes.
+
+### `ShellDocs.Xml` (v2)
+
+**Purpose:** extract API reference from XML doc comments.
+
+**Public API:**
+- MSBuild task ` `
+- Emits JSON per public type: `{ Name, Namespace, Summary, Properties: [{ Name, Type, Summary, Default }], Methods: [...] }`
+- ` ` reads the JSON at render time
+
+**Depends on:** `Microsoft.CodeAnalysis` (Roslyn), `System.Xml.Linq`
+
+**Deferred to Phase 4.** Hand-authored `` unblocks Phase 2 shipping.
+
+---
+
+## Service registration
+
+`AddShellDocs(options)` wires up everything.
+
+```csharp
+public static IServiceCollection AddShellDocs(
+ this IServiceCollection services,
+ Action configure)
+{
+ var options = new ShellDocsOptions();
+ configure(options);
+ services.AddSingleton(options);
+
+ // Core — nav graph is built once at startup
+ services.AddSingleton(sp =>
+ NavigationGraphBuilder.Build(options.ContentRoot));
+
+ // Markdown pipeline is singleton — construction is expensive
+ services.AddSingleton();
+ services.AddScoped();
+
+ // Type registry is populated during Register* calls
+ services.AddSingleton(sp =>
+ {
+ var registry = new TypeRegistry();
+ foreach (var type in options.RegisteredComponents) registry.Register(type);
+ return registry;
+ });
+
+ // Theme applied as cascading value in DocsLayout
+ services.AddSingleton(options.Theme);
+
+ return services;
+}
+```
+
+`ShellDocsOptions` — plain POCO with fluent-friendly config:
+
+```csharp
+public class ShellDocsOptions
+{
+ public string ContentRoot { get; set; } = "content";
+ public string SiteName { get; set; } = "";
+ public string? GitHubRepo { get; set; }
+ public ShellDocsTheme Theme { get; set; } = ShellDocsTheme.Shadcn;
+ public List RegisteredComponents { get; } = new();
+ public bool EnableSearch { get; set; } = true;
+ public string SearchIndexPath { get; set; } = "search-index.json";
+ // ... more knobs
+
+ public ShellDocsOptions RegisterComponent() where T : ComponentBase
+ {
+ RegisteredComponents.Add(typeof(T));
+ return this;
+ }
+}
+```
+
+Fluent API supports method chaining in `Program.cs`.
+
+---
+
+## Markdown pipeline internals
+
+### Custom Markdig extensions
+
+Three extensions register on the Markdig pipeline:
+
+**1. Frontmatter extension**
+
+Uses `Markdig.Extensions.Yaml.YamlFrontMatterExtension` (built-in). Wraps its output as `DocumentFrontmatter` in the `RenderedDocument`.
+
+**2. `razor:preview` fence extension**
+
+Extends `FencedCodeBlockRenderer` — inspects the info string. If it starts with `razor:preview`, replaces the standard code-block output with a placeholder ` ` and adds a `PreviewSlot` to the rendered document.
+
+At render time, `MarkdownContent` walks its markup and for each `data-shelldocs-preview` span, injects a `` with the preview slot.
+
+**3. Inline component tag extension**
+
+Custom `InlineParser` on Markdig — matches ` ` at the block or inline level. Rejects if `TagName` isn't in `TypeRegistry`. Emits a placeholder ` ` and adds a `ComponentSlot` to the rendered document.
+
+Same render-time swap logic as `razor:preview`.
+
+### Why placeholders + slot list, not direct Razor generation
+
+Generating Razor source code from markdown at build time is possible but adds tooling complexity. Markdown-to-HTML + slot list at render time keeps everything in the runtime and lets us change the wrapper components without rebuilding the source.
+
+Trade-off: DOM walking at render time has a per-page cost (~1ms for a large page). Acceptable.
+
+---
+
+## Navigation graph internals
+
+### Build process
+
+`NavigationGraphBuilder.Build(contentRoot)`:
+
+1. Recursively walk `contentRoot`
+2. For each `.md` file: parse frontmatter, create a `NavigationNode` with `Url = path minus root + filename`, populate from frontmatter
+3. For each folder: check for `meta.json`, build children in specified order; fall back to alphabetical
+4. Cross-link `Parent` and `Children`
+5. Compute derived properties: `NextNode`, `PreviousNode` (in flatten order)
+6. Return `NavigationGraph` root
+
+Cache result — rebuild only when `dev` mode detects a change.
+
+### Runtime queries
+
+`NavigationGraph.ResolveByUrl("/docs/button")`:
+- Walk the tree matching path segments
+- O(depth) — usually 2–3 segments
+- Return `null` if not found (page shows 404)
+
+`NavigationGraph.GetPrevNext(node)`:
+- Precomputed at build; O(1) lookup
+
+`NavigationGraph.GetBreadcrumb(node)`:
+- Walk up `Parent` chain; O(depth)
+
+### `meta.json` schema
+
+```json
+{
+ "title": "Components",
+ "pages": [
+ "button",
+ "input",
+ "---",
+ {
+ "title": "Data Display",
+ "pages": ["table", "card", "badge"]
+ }
+ ]
+}
+```
+
+- Strings: page slug matches filename minus `.md`
+- `"---"`: renders as a section divider in the sidebar
+- Objects: nested subsection with its own title and pages
+- Nested folders can have their own `meta.json` for further nesting
+
+Unknown page slugs (typo in `meta.json`) emit a build-time warning but don't crash.
+
+---
+
+## Search index
+
+### Build time
+
+`SearchIndexBuilder.Build(graph, renderer)`:
+
+For each node in the graph:
+1. Render the page's markdown (via `MarkdownRenderer`)
+2. Extract all `` and `` headings (already in `RenderedDocument.Headings`)
+3. Extract first 200 chars of body per heading (for excerpt)
+4. Build `SearchIndexEntry { Url, Title, Description, Category, Headings, Excerpt }`
+
+Serialize the list to `search-index.json`, written to output `wwwroot/`.
+
+### Runtime
+
+`SearchDialog` component on first open (lazy):
+1. `HttpClient.GetFromJsonAsync("search-index.json")`
+2. Store in memory for subsequent opens
+
+On each keystroke:
+1. Fuzzy match against `Title` + `Headings.Text` + `Excerpt`
+2. Score = Levenshtein + prefix bonus + heading-match bonus
+3. Top N results rendered inline in the modal
+
+No debounce needed for docs sites this size. ~500 entries client-filtered in <1ms.
+
+### Scaling out
+
+For 1000+ pages, the client-side fuzzy match starts to lag on slow devices. Escape hatch: `options.SearchProvider = SearchProvider.Orama` swaps to an Orama-backed backend. Not v1; escape hatch design only.
+
+---
+
+## Component rendering (``)
+
+Standard Blazor primitive — takes `Type` + `IReadOnlyDictionary?`.
+
+`MarkdownContent` component:
+
+```razor
+@foreach (var slot in Document.Slots)
+{
+
+
+ @slot.ChildContent
+
+
+}
+```
+
+Then the plain HTML with `data-slot` placeholders is emitted alongside; the DOM ends up interleaved. Details in the [markdown pipeline notes](#markdown-pipeline-internals).
+
+**Parameter serialization:** frontmatter values are strings from YAML. `TypeRegistry` inspects each component's `[Parameter]` properties to know the target type and coerces (int, bool, enum, string). Complex types (records, DTOs) need JSON literals in the markdown.
+
+---
+
+## Theme layer
+
+### Layer 1 — presets
+
+Each theme is a package that ships:
+- A CSS file with custom properties (`--color-bg`, `--color-accent`, `--font-heading`, `--radius`, etc.)
+- Optional component style overrides (`.docs-sidebar-item.active { … }`)
+- Registered via `options.Theme = ShellDocsTheme.Fuma`
+
+`DocsLayout` applies the theme's CSS by injecting the stylesheet link into the `` or by cascading a `ThemeContext` that child components consume.
+
+### Layer 2 — full customization
+
+Every custom property is overridable in the consumer's `wwwroot/*.css`. Cascade order: theme preset → consumer CSS. Standard shadcn escape hatch.
+
+Every component parameter is public. Consumer can wrap `` in a component of their own with different behaviour — same override pattern as shadcn's copy-and-edit philosophy.
+
+---
+
+## Static site generation
+
+`shelldocs build`:
+
+1. `dotnet publish -c Release -o ` — Blazor's WASM AOT publish
+2. Run `SearchIndexBuilder` on the content, write `search-index.json` to `output/wwwroot/`
+3. Rewrite ` ` in `index.html` to ` ` if `basePath` supplied
+4. Copy `index.html` → `404.html` (GH Pages SPA fallback)
+5. Copy any content-referenced static assets (images embedded in markdown)
+6. Exit
+
+Optionally, in a future version: prerender each route to a static `.html` file for SEO / first-paint. Requires Blazor's prerendering support — feasible in Server hosting mode, harder in WASM. Deferred.
+
+---
+
+## Dev server (`shelldocs dev`)
+
+Two processes:
+
+**1. `dotnet watch run`** on the consumer project. Hot-reloads on `.razor` / `.cs` changes.
+
+**2. Markdown file watcher** (`FileSystemWatcher` on `content/**/*.md`) — spawns from the same CLI process. On change:
+- Rebuild `NavigationGraph`
+- POST to a well-known endpoint on the running app (`/_shelldocs/reload-graph`)
+- The endpoint invokes a `NavigationGraph`-refresh service (registered by `AddShellDocs()` in dev mode)
+
+Alternative: SignalR channel between CLI and app. Overkill for v1.
+
+---
+
+## Testing strategy
+
+Same three-layer approach as ShellUI:
+
+**1. Unit tests** (`ShellDocs.Tests`)
+- xUnit
+- Markdig extensions in isolation
+- `NavigationGraphBuilder` on synthetic content trees
+- `TypeRegistry` coercion
+- `SearchIndexBuilder` output shape
+
+**2. Template compile tests**
+- Every CLI template's `Content` is Roslyn-parsed to catch escape-quote regressions
+
+**3. Live↔template sync tests**
+- The scaffold generated by `shelldocs init` matches what the CLI templates say it should
+
+**4. E2E in CI**
+- `shelldocs init` a Blazor WASM project in a temp dir
+- `shelldocs build` it
+- Verify output has expected files, valid HTML, search index present
+
+---
+
+## Cross-cutting concerns
+
+### Bundle size
+
+Priorities:
+- Base ShellDocs.Components: target <100KB gzipped
+- With Shiki full theme set: +~2MB (opt-out via config to a Prism-based highlighter, <50KB)
+- With Motion One fallback: +~10KB gzipped
+
+Every JS interop file gets budget scrutiny.
+
+### Accessibility
+
+- All primitives ship with correct ARIA roles + labels
+- Keyboard nav complete (Tab / Shift+Tab / Enter / Esc across all interactives)
+- Focus management on modal open/close
+- Skip-to-content link in `DocsLayout`
+- `prefers-reduced-motion` respected everywhere animations run
+
+### Internationalization (i18n)
+
+**Not v1.** Design left open by making content routing extension-friendly — a future `ShellDocs.I18n` package could add locale-aware content resolution without breaking `NavigationGraph`'s shape.
+
+---
+
+## What we're NOT building (deliberately)
+
+- **A markdown editor.** Consumer authors in whatever they use (VSCode, Rider, whatever).
+- **A CMS.** Content is `.md` files in a git repo. That's the interface.
+- **A server backend.** ShellDocs is static-only; the search index is client-side.
+- **A hosted service.** No shelldocs.dev SaaS; it's a NuGet package family.
+- **A design system.** ShellUI is that. ShellDocs uses ShellUI; doesn't compete.
+
+Scope discipline. These are all things fumadocs also didn't build — and it stayed lean and usable.
diff --git a/docs/DESIGN.md b/docs/DESIGN.md
new file mode 100644
index 0000000..a255cc2
--- /dev/null
+++ b/docs/DESIGN.md
@@ -0,0 +1,438 @@
+# ShellDocs — Design Doc
+
+Living design doc. Updated as decisions land.
+
+---
+
+## TL;DR
+
+**ShellDocs is a docs framework for .NET, like [fumadocs](https://fumadocs.dev) for Node/React.**
+
+Ship it as NuGet packages + a CLI so any .NET user can:
+
+```bash
+dotnet new blazorwasm -n MyDocs
+cd MyDocs
+dotnet tool install -g ShellDocs.CLI
+shelldocs init
+```
+
+…and end up with a sleek, animated, Cmd+K-searchable docs site with markdown authoring and live Razor component previews. First class targets: ShellUI, MudBlazor, Radzen, MAUI Community Toolkit — any Blazor UI library that needs docs. Long-term consumer-agnostic: docs sites for regular libraries, guides, blog-style content.
+
+The framework is **opinionated by default, composable underneath.** Reasonable defaults get you a beautiful site in 5 minutes; primitives are exposed if you want to build something custom.
+
+---
+
+## Positioning — how ShellDocs relates to existing options
+
+| Tool | Ecosystem | What it is | Why not just use this |
+|---|---|---|---|
+| **fumadocs** | Node / Next.js | Docs framework — MDX + primitives + CLI | Different runtime; .NET users need to context-switch |
+| **Docfx** | .NET / Microsoft | XML-doc + conceptual docs generator, ASP.NET template | Powerful but dated aesthetic, opinionated in a Microsoft-y way, not Blazor-native |
+| **Statiq** | .NET | Static site generator toolkit | Lower-level; you build the site yourself |
+| **shadcn/ui docs** | Node / Next.js | Custom Next.js app, not extracted as a framework | Not reusable — only shadcn ships from it |
+| **MudBlazor docs** | .NET / Blazor | Custom Blazor Server app | Not extracted; every Blazor library rebuilds this from scratch |
+
+**The gap:** every .NET UI library ends up hand-rolling their own docs site (see MudBlazor.com, radzen.com, mudblazor.com). None are extractable as reusable frameworks. **ShellDocs = the "just use this" answer for .NET docs sites.**
+
+Design north star: **fumadocs' polish + shadcn's composability + .NET's runtime.**
+
+---
+
+## Package family
+
+`shellui-dev/shelldocs` monorepo ships six NuGet packages:
+
+| Package | Role | Analog in fumadocs |
+|---|---|---|
+| **`ShellDocs.Core`** | Navigation graph, search index model, routing helpers | fumadocs-core |
+| **`ShellDocs.Markdown`** | Markdig pipeline + frontmatter + Razor component embedding | fumadocs-mdx |
+| **`ShellDocs.Components`** | RCL — UI primitives (DocsSidebar, CodeBlock, SearchDialog, etc.) | fumadocs-ui |
+| **`ShellDocs.CLI`** | `shelldocs init`, `shelldocs new page`, `shelldocs dev`, `shelldocs build` | create-fuma-app + tooling |
+| **`ShellDocs.Templates`** | Content used by CLI (starter markdown, meta.json, .csproj patches) | starter templates |
+| **`ShellDocs.Xml`** *(v2)* | Extract API reference from XML doc comments, generate `` markup | fumadocs-typescript |
+
+Optional / future:
+
+| Package | Role |
+|---|---|
+| `ShellDocs.OpenApi` | Turn OpenAPI spec into API reference pages |
+| `ShellDocs.Themes.Fuma` | Fumadocs-inspired theme preset |
+| `ShellDocs.Themes.Nextra` | Nextra-inspired theme preset |
+
+Package families keep each concern small and versioned independently. Users install only what they need. `ShellDocs.CLI` is the entry point that pulls the rest.
+
+---
+
+## CLI UX
+
+Modeled on `shellui` — same feel, same commands:
+
+```bash
+# Bootstrap a docs project into any Blazor WASM project
+shelldocs init
+ → Adds ShellDocs.Components + ShellDocs.Markdown packages
+ → Creates content/docs/, content/components/ folders with sample .md files
+ → Creates Layout/DocsLayout.razor + Pages/DocsPage.razor
+ → Patches Program.cs to wire the Markdown pipeline + navigation graph
+ → Writes meta.json for sidebar structure
+ → Copies default theme CSS
+
+# Add a doc page from a template
+shelldocs new page installation
+shelldocs new component-page button
+
+# Local dev with hot reload for markdown files
+shelldocs dev
+ → Watches content/**/*.md, rebuilds nav graph on change, hot-reloads Blazor
+
+# Build with static site generation for deployment
+shelldocs build
+ → Generates search-index.json, prerenders every route to /wwwroot,
+ outputs static site ready for GH Pages / Vercel / Netlify / whatever
+
+# Preview any component in isolation
+shelldocs preview Button --variant Destructive
+```
+
+Same install path as `shellui`: `dotnet tool install -g ShellDocs.CLI`.
+
+---
+
+## Architecture — how ShellDocs wraps a Blazor app
+
+ShellDocs assumes the host is a **Blazor WebAssembly** app. It layers on top via three mechanisms:
+
+**1. Markdown pipeline** (`ShellDocs.Markdown`)
+
+`Program.cs` registers a Markdig-based renderer configured with:
+- YAML frontmatter parsing (YamlDotNet)
+- Custom fenced-code handling — ` ```razor:preview ` becomes a `` + `` pair
+- Custom link resolution — `[Button](@component:button)` maps to `/components/button`
+- Inline Razor tags — ` ` in markdown gets rendered via `` at render time
+
+**2. Navigation graph** (`ShellDocs.Core`)
+
+At startup, walks `content/**/*.md`, reads frontmatter, builds a tree keyed by URL. Each node has: title, description, category, order, section headings. Used by:
+- `` to render grouped nav
+- `` to compute previous/next links
+- `` to feed the client-side index
+- SPA routing to map `/docs/introduction` → `content/docs/introduction.md`
+
+**3. Component primitives** (`ShellDocs.Components`)
+
+Standard RCL. Consumer references it, uses `` in their MainLayout, and the framework handles the rest.
+
+Minimal `Program.cs` for a ShellDocs consumer:
+
+```csharp
+var builder = WebAssemblyHostBuilder.CreateDefault(args);
+builder.RootComponents.Add("#app");
+
+builder.Services.AddShellDocs(options =>
+{
+ options.ContentRoot = "content";
+ options.SiteName = "ShellUI";
+ options.GitHubRepo = "shellui-dev/shellui";
+ options.Theme = ShellDocsTheme.Fuma;
+});
+
+await builder.Build().RunAsync();
+```
+
+Three lines of config, everything else discoverable from convention.
+
+---
+
+## Primitives shipped in `ShellDocs.Components`
+
+| Component | Purpose |
+|---|---|
+| **`DocsLayout`** | Full-page shell: header + sidebar + main + TOC + footer — the primary chrome |
+| **`DocsHeader`** | Top nav: logo, primary nav, search trigger, theme toggle, GitHub link |
+| **`DocsSidebar`** | Left-rail grouped nav, auto-derived from nav graph, collapsible sections, active highlighting |
+| **`DocsBreadcrumb`** | Section > subsection > current-page trail |
+| **`TableOfContents`** | Right-rail auto-generated from ``/``, scroll-spy via IntersectionObserver |
+| **`PrevNextNav`** | Bottom-of-page previous/next links, footer-anchored |
+| **`SearchDialog`** | Cmd+K modal — reads generated `search-index.json`, fuzzy matches title + heading + excerpt. Composes existing `` from ShellUI |
+| **`CodeBlock`** | Syntax-highlighted code — copy button, filename tab, line highlighting, language badge. **Shiki** via WASM (VSCode-parity highlighting) |
+| **`DocsTabs`** | Multi-tab code examples (`npm` / `yarn` / `pnpm` / `standalone`) — remembers selection across tab groups on the same page via shared context |
+| **`FileTree`** | Static filesystem visualization for project structure explainers |
+| **`Steps`** | Vertical numbered steps for onboarding flows |
+| **`TypeTable`** | Props table (name / type / default / description) — hand-authored initially, auto-generated from XML docs in `ShellDocs.Xml` |
+| **`LinkCard`** | Card-shaped link with title / description / icon — for "Next steps" grids |
+| **`ComponentPreview`** | Live preview of any component by name + props, with source-view toggle. Renders via `` |
+| **`Callout`** | Info / warning / tip / danger box. May be a `` variant from ShellUI + docs styling |
+
+All animated with mount transitions, hover states, smooth theme switching. Reduced-motion respected via `prefers-reduced-motion`.
+
+---
+
+## Content model
+
+Every doc page is a `.md` file with YAML frontmatter under `content/`:
+
+```markdown
+---
+title: Button
+description: Interactive button component with type-safe variants
+category: Form
+order: 10
+---
+
+# Button
+
+
+Button uses ShellUI's `Shell.Cn` for class composition.
+
+
+## Installation
+
+Install with the CLI:
+
+\`\`\`bash
+dotnet shellui add button
+\`\`\`
+
+## Usage
+
+\`\`\`razor:preview
+Delete
+\`\`\`
+
+## API Reference
+
+
+
+
+
+
+```
+
+Two extensions to standard markdown:
+
+1. **`razor:preview` fenced blocks** — render as ` `. Preview and code stay in sync automatically.
+
+2. **Inline component tags** — ``, ``, `` and any registered component render as real Razor via ``. Consumer registers additional component types in options:
+
+ ```csharp
+ options.RegisterComponent();
+ options.RegisterComponent();
+ options.RegisterComponent(); // for library authors documenting their own components
+ ```
+
+---
+
+## Navigation & meta.json
+
+Sidebar order is derived from a `meta.json` file per folder:
+
+```json
+{
+ "title": "Components",
+ "pages": [
+ "button",
+ "input",
+ "---",
+ {
+ "title": "Data Display",
+ "pages": ["table", "card", "badge"]
+ }
+ ]
+}
+```
+
+Falls back to alphabetical if no `meta.json` present. Nested folders get their own `meta.json`. `---` renders a section divider.
+
+---
+
+## Search
+
+Build-time indexer walks `content/**/*.md`, produces `wwwroot/search-index.json`:
+
+```json
+[
+ {
+ "url": "/components/button",
+ "title": "Button",
+ "description": "Interactive button component…",
+ "category": "Components",
+ "headings": [
+ { "level": 2, "text": "Installation", "id": "installation" },
+ { "level": 2, "text": "Usage", "id": "usage" }
+ ],
+ "excerpt": "Button uses ShellUI's Shell.Cn for class composition. Install with the CLI…"
+ }
+]
+```
+
+`` fetches once on Cmd+K, does client-side fuzzy match (Fuse.js-equivalent). No server, no infrastructure, works offline. Docs sites this size don't need a real search backend.
+
+For larger docs sites (100+ pages), swap in Orama or Meilisearch via a config option — the primitive is search-provider-agnostic.
+
+---
+
+## Theming
+
+Two-layer approach:
+
+**Layer 1: theme presets** — `ShellDocs.Themes.*` packages, each preset is a set of CSS custom properties + component style overrides. Consumer picks one in `Program.cs`:
+
+```csharp
+options.Theme = ShellDocsTheme.Fuma; // fumadocs-inspired
+options.Theme = ShellDocsTheme.Nextra; // nextra-inspired
+options.Theme = ShellDocsTheme.Shadcn; // shadcn-inspired (default)
+```
+
+**Layer 2: full customization** — every CSS variable and every component parameter is overridable. Ejecting from a theme means writing your own CSS + variant. Same escape hatch shadcn provides.
+
+Dark mode: automatic via `prefers-color-scheme`, persistent via localStorage, toggleable via `` in header. Theme selection also respected on iframe embeds via `?theme=` query param.
+
+---
+
+## Animation
+
+Sleek defaults, `prefers-reduced-motion` respected everywhere:
+
+- **Page transitions** — fade + slight translate on route change (150ms)
+- **Sidebar collapse** — height animation, chevron rotation (200ms)
+- **TOC scroll-spy** — active heading indicator slides between items (spring-based)
+- **Search dialog** — scale + fade in from center (100ms)
+- **CodeBlock copy button** — checkmark morph on success (150ms + 1s hold)
+- **Sidebar item hover** — background fade + subtle scale
+- **Mobile drawer** — slide from left with backdrop blur
+
+Framework choice: **CSS transitions + view-transitions API** where available, JS-based (Motion One) fallback for animations that need spring physics. No React-style animation library — keep the bundle lean.
+
+---
+
+## Deployment stories
+
+Any static host works — ShellDocs generates a static site via `shelldocs build`:
+
+| Target | Notes |
+|---|---|
+| **GitHub Pages** | `shelldocs build` outputs `wwwroot/`, workflow pushes to `gh-pages` branch. Base-href rewritten to `//` at build time. |
+| **Vercel** | Detects Blazor WASM. `shelldocs build` output goes to `.output/public/`. |
+| **Netlify** | Same as Vercel. |
+| **Cloudflare Pages** | Same. |
+| **Static file host** | Copy `wwwroot/` to any CDN. |
+| **Custom domain** | CNAME to your host. Base href becomes `/`. |
+
+Server-side rendering is not supported in v1 — Blazor WASM only. May revisit for Blazor Server + prerendering later (Phase 5).
+
+---
+
+## Ecosystem story
+
+```
+ shelldocs.dev
+ (ShellDocs' own docs
+ — dogfooded)
+ │
+ │ uses
+ ▼
+ ShellDocs
+ ▲
+ │ consumes
+ │
+ ┌──────────────┼──────────────┐
+ │ │ │
+ shellui.dev mudblazor's avalonia's
+ (ShellUI docs) (hypothetical) (hypothetical)
+```
+
+- **`shellui-dev/shelldocs`** — the framework
+- **`shellui-dev/shellui.dev`** — ShellUI's docs site, built with ShellDocs (proves out the framework, sets the aesthetic bar)
+- **`shellui-dev/shelldocs.dev`** — ShellDocs' own docs site, also built with ShellDocs (dogfood)
+- **Other adopters** — Anyone building a .NET UI library gets a docs site by adopting ShellDocs
+
+Long-term: if ShellDocs is good, it becomes the default "how do you build a docs site for a .NET library" answer, the same way fumadocs became that for the Next.js world.
+
+---
+
+## The Avalonia / cross-framework question
+
+**v1 is Blazor-only.** ShellDocs renders in the browser via Blazor WASM. Live component previews are real Blazor renders.
+
+**For Avalonia (or MAUI, etc.) library docs** three routes:
+
+1. **Screenshot previews** — pre-generate images at build time, doc pages show image + code. Loses "live", keeps parity for the framework-agnostic content sections.
+2. **Iframe to a running Avalonia app** — back to the iframe workaround, but now for cross-framework only.
+3. **Wait for Avalonia's browser target to stabilize** — Avalonia already ships web builds. When mature, `IComponentPreviewer` interface in ShellDocs could have an `AvaloniaPreviewer` implementation.
+
+Design principle: **don't design for Avalonia now, but keep an escape hatch.** `IComponentPreviewer` abstraction (Blazor is one implementation) leaves room without adding complexity to v1.
+
+---
+
+## Phased delivery
+
+**Phase 0 — Setup** *(this)*
+- Design doc (this file). Alignment on framework framing.
+- Domain: register `shelldocs.dev`
+
+**Phase 1 — Core framework** *(4–6 weeks)*
+- Create `shellui-dev/shelldocs` repo
+- Ship `ShellDocs.Core` + `ShellDocs.Markdown` + minimal `ShellDocs.Components` (DocsLayout, DocsSidebar, DocsHeader, CodeBlock, MarkdownRenderer)
+- Ship `ShellDocs.CLI` with `init`, `dev`, `build`
+- One theme preset (Shadcn — matches ShellUI aesthetic)
+- Release as `0.1.0-alpha` on NuGet
+
+**Phase 2 — Primitive completeness** *(2–4 weeks)*
+- Add remaining primitives: `SearchDialog`, `TableOfContents`, `PrevNextNav`, `DocsTabs`, `TypeTable`, `LinkCard`, `Callout`, `Steps`, `FileTree`, `ComponentPreview`
+- Search index build tool
+- Animation polish pass — mount transitions, page transitions, scroll-spy
+- Release as `0.2.0-alpha`
+
+**Phase 3 — Dogfood via shellui.dev** *(2–4 weeks)*
+- Bootstrap `shellui-dev/shellui.dev` repo using ShellDocs `0.2.0-alpha`
+- Author real content — introduction, installation, theming, all 68 components
+- Deploy to GH Pages, CNAME to `shellui.dev`
+- Feedback loop drives ShellDocs `0.3.0` — every rough edge shellui.dev hits becomes a ShellDocs improvement
+
+**Phase 4 — ShellDocs' own site** *(2 weeks)*
+- Bootstrap `shellui-dev/shelldocs.dev` using ShellDocs
+- Full docs for ShellDocs itself
+- Deploy to `shelldocs.dev`
+- ShellDocs `1.0.0-rc` — API stable
+
+**Phase 5 — Ecosystem push**
+- Additional theme presets (Fuma, Nextra)
+- `ShellDocs.Xml` — auto-`TypeTable` from XML doc comments
+- Migration guides for existing docs sites (mudblazor → shelldocs, etc.)
+- Blog post + Twitter push
+- Reach out to MudBlazor / Radzen / AvaloniaUI teams
+
+---
+
+## Open questions
+
+- **Shiki vs. Prism for CodeBlock.** Shiki gives VSCode-parity syntax highlighting but ships a ~2MB WASM regex engine. Prism is lighter (~50KB) but syntax fidelity is patchy for Razor/C#. **Lean:** Shiki, ship a smaller Prism-based fallback for low-bandwidth via config.
+- **Blazor Server support.** v1 is Blazor WASM. Blazor Server support = adding a mode flag, mostly working, but page navigation animations and code-splitting behave differently. Revisit Phase 5.
+- **CLI vs. `dotnet new` template.** Should `shelldocs init` also be exposed as `dotnet new shelldocs`? Probably yes — both entry points converge on same scaffolding.
+- **Theme distribution.** Should themes ship as separate NuGet packages (small, opt-in) or bundled in `ShellDocs.Components` (one install, more bytes)? **Lean:** separate packages — matches shadcn's per-component philosophy.
+- **XML doc comment extraction.** Automating `` from XML docs is the killer feature vs. hand-authoring. But it requires the consumer's build to emit XML docs and expose the referenced assemblies. Non-trivial. Phase 5+.
+- **Interactive playgrounds** (like MDN's live sandbox). Nice-to-have. Requires a compiler-in-browser (Roslyn WASM) or server round-trip. Deprioritized until it's clearly needed.
+
+---
+
+## Naming, domains, mental model
+
+- **ShellDocs** — the framework (the code, the repo, the NuGet packages)
+- **`shelldocs.dev`** — the framework's own marketing/docs site
+- **`shellui.dev`** — ShellUI's docs site, built with ShellDocs
+- **`shellui-dev/shelldocs`** — the framework's GitHub repo
+- **`shellui-dev/shellui.dev`** — ShellUI docs site's repo
+- **`shellui-dev/shelldocs.dev`** — ShellDocs marketing site's repo (may just be inside the shelldocs repo as `examples/shelldocs.dev`)
+
+All three repos in the same org. Domains bought separately once names are locked.
+
+---
+
+## Cross-references
+
+- [ROADMAP.md](ROADMAP.md) — branch-by-branch implementation plan
+- [ARCHITECTURE.md](ARCHITECTURE.md) — technical architecture
+- [fumadocs](https://fumadocs.dev) — closest analog in another ecosystem
+- [Docfx](https://dotnet.github.io/docfx/) — .NET's incumbent, what we're competing against on aesthetic + composability
+- [shadcn/ui docs source](https://github.com/shadcn-ui/ui/tree/main/apps/www) — reference for content structure
diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md
new file mode 100644
index 0000000..1c706e8
--- /dev/null
+++ b/docs/ROADMAP.md
@@ -0,0 +1,327 @@
+# ShellDocs Roadmap
+
+Branch-by-branch implementation plan. Living doc — updated as branches ship.
+
+See [DESIGN.md](DESIGN.md) for the high-level design and [ARCHITECTURE.md](ARCHITECTURE.md) for technical details.
+
+---
+
+## Release timeline
+
+| Version | Target | Theme |
+|---|---|---|
+| `0.1.0-alpha` | Phase 1 end | Core framework: markdown pipeline + navigation graph + minimal chrome + CLI + one theme |
+| `0.2.0-alpha` | Phase 2 end | Primitive completeness: search, TOC, nav, code tabs, TypeTable, animations |
+| `0.3.0-alpha` | Phase 3 end | Hardened through building shellui.dev; consumer-driven fixes |
+| `0.4.0-beta` | Phase 4 end | ShellDocs' own docs (shelldocs.dev) shipped; API stabilization |
+| `1.0.0-rc` | Phase 4 end | Public release candidate |
+| `1.0.0` | Phase 5 | Stable |
+
+---
+
+## Package family — what each branch ships to
+
+| Package | Purpose |
+|---|---|
+| `ShellDocs.Core` | Navigation graph, search index model, routing helpers |
+| `ShellDocs.Markdown` | Markdig pipeline + frontmatter + Razor component embedding |
+| `ShellDocs.Components` | RCL — UI primitives (DocsLayout, CodeBlock, SearchDialog, etc.) |
+| `ShellDocs.CLI` | `shelldocs init`, `shelldocs new`, `shelldocs dev`, `shelldocs build` |
+| `ShellDocs.Templates` | Content for CLI scaffolding — starter markdown, meta.json, .csproj patches |
+| `ShellDocs.Xml` | v2 — extract `` from XML doc comments |
+
+Each branch below annotates which package it touches. Multi-package branches call out cross-package changes.
+
+---
+
+## Phase 1 — Core framework (~4–6 weeks)
+
+Goal: a consumer can `shelldocs init` an empty Blazor WASM project and get a working docs site with sidebar, header, code blocks, and one theme.
+
+### `chore/repo-scaffolding`
+Bootstrap the monorepo.
+
+- `.sln` with the six package projects (`ShellDocs.Core`, `ShellDocs.Markdown`, `ShellDocs.Components`, `ShellDocs.CLI`, `ShellDocs.Templates`, plus `ShellDocs.Tests`)
+- `.csproj` files with correct `TargetFramework`, `IsPackable`, `PackageId`
+- `.gitignore`, `Directory.Build.props`, `Directory.Packages.props` for central package management
+- `.github/workflows/ci.yml` — build + test on every push
+- `.github/workflows/release.yml` — pack + push to NuGet on tag
+- Nothing shipped; groundwork only
+
+### `feat/core-navigation-graph`
+Ships to `ShellDocs.Core`.
+
+- `NavigationGraph` — tree of `NavigationNode { Url, Title, Description, Category, Order, Headings, Path }`
+- `NavigationGraphBuilder` — walks a content root, reads frontmatter, builds the tree
+- `meta.json` reader — folder-level sidebar ordering + section dividers
+- Route resolution — `NavigationGraph.ResolveByUrl("/docs/button")` → node
+- Unit tests: markdown → tree, meta.json ordering, deep-nested folders
+
+### `feat/markdown-pipeline`
+Ships to `ShellDocs.Markdown`.
+
+- Markdig extension for YAML frontmatter (YamlDotNet)
+- Markdig extension for `razor:preview` fenced blocks — emits placeholder that renderer swaps for `` component
+- Markdig extension for inline Razor tags (` ` mid-markdown)
+- `MarkdownRenderer` component — takes a `.md` file path, returns rendered `MarkupString` + list of embedded component slots
+- Type registry — `RegisterComponent()` API for consumer to expose their components to inline tags
+- Unit tests: frontmatter parsing, fenced block replacement, tag resolution, unknown-tag graceful degradation
+
+### `feat/components-shell`
+Ships to `ShellDocs.Components`.
+
+- `DocsLayout` — full-page grid: header + sidebar + main + TOC placeholder + footer
+- `DocsHeader` — logo, primary nav, search-button placeholder, theme toggle, GitHub link
+- `DocsSidebar` — grouped nav from navigation graph, collapsible sections, active highlighting
+- `MarkdownContent` — renders a doc page from a `.md` path via `MarkdownRenderer`
+- One theme preset baked in (`Shadcn`)
+- No search, no TOC, no code highlighting yet — those come in later branches
+
+### `feat/codeblock-shiki`
+Ships to `ShellDocs.Components`.
+
+- `CodeBlock` component — takes `Language`, `Code`, `Filename`, `HighlightLines`
+- Shiki via WASM (bundle configurable — full theme set is ~2MB, subset ~200KB)
+- Copy button (uses `Shell.Cn` + ShellUI's clipboard interop pattern)
+- Filename tab (renders as pill above the block)
+- Line-highlight styling via CSS
+- Handles `razor:preview` blocks — code visible in Preview + Code tabs (`` primitive comes in Phase 2)
+
+### `feat/cli-init`
+Ships to `ShellDocs.CLI` + `ShellDocs.Templates`.
+
+- `shelldocs init` — detects Blazor WASM project, adds package references, generates `content/`, `Layout/DocsLayout.razor`, patches `Program.cs` to register services, writes default `meta.json`
+- Non-interactive mode (`--yes`) — defaults for CI
+- Idempotent — running twice is a no-op
+- Templates for `Program.cs` snippets, starter `.md` content, `meta.json` skeleton
+- Similar structure to `ShellUI.CLI` from ShellUI project
+
+### `feat/cli-dev-build`
+Ships to `ShellDocs.CLI`.
+
+- `shelldocs dev` — starts `dotnet watch run` with markdown file watcher, hot-reload triggers navigation graph rebuild on `.md` change
+- `shelldocs build` — runs `dotnet publish`, then post-processes: base-href rewrite, SPA 404 fallback, search index generation (search stub for now)
+- Configurable output directory
+- Reused between hosts (GH Pages, Vercel, Netlify, static)
+
+### `chore/release-0.1.0-alpha`
+- Version bump across all packages
+- Release notes
+- Push to NuGet
+- Announce internally; no external marketing yet
+
+**Milestone:** A consumer can spin up a docs site with sidebar + header + markdown-driven content + one theme. Search + TOC + rich primitives still missing.
+
+---
+
+## Phase 2 — Primitive completeness (~2–4 weeks)
+
+Goal: everything from DESIGN.md's primitives table shipped. Real docs sites become viable.
+
+### `feat/search-primitives`
+Ships to `ShellDocs.Core` + `ShellDocs.Components`.
+
+- `SearchIndexBuilder` in `ShellDocs.Core` — walks nav graph, emits `search-index.json`
+- Wired into `shelldocs build` — index emitted alongside published site
+- `SearchDialog` component — Cmd+K modal, composes ShellUI's ``, fetches index, client-side fuzzy match (Fuse.js-equivalent — probably home-grown, ~200 LOC)
+- Header search button opens the dialog
+- Keyboard nav in dialog (up/down/enter/esc)
+
+### `feat/toc-primitive`
+Ships to `ShellDocs.Components`.
+
+- `TableOfContents` — right-rail nav, generated from `` and `` in current page
+- Scroll-spy via `IntersectionObserver` (JS interop)
+- Smooth-scroll on click
+- Auto-hides on mobile / narrow screens
+
+### `feat/nav-primitives`
+Ships to `ShellDocs.Components`.
+
+- `PrevNextNav` — auto-derived from nav graph adjacency, rendered at page bottom
+- `DocsBreadcrumb` — composes ShellUI's `` with docs presets
+
+### `feat/content-primitives`
+Ships to `ShellDocs.Components`.
+
+- `DocsTabs` — multi-tab code containers (`npm` / `yarn` / `pnpm` / `standalone` / `bash` presets)
+- `Callout` — Info / Warning / Tip / Danger box (may reuse ShellUI `` with docs styling wrapper)
+- `LinkCard` — card-shaped link with title / description / icon for "Next steps" grids
+- `FileTree` — static folder / file visualization
+- `Steps` — vertical numbered steps for onboarding flows
+
+### `feat/api-reference-primitives`
+Ships to `ShellDocs.Components`.
+
+- `TypeTable` — props table with ` ` child components
+- `ComponentPreview` — live component render by name + prop dictionary, source-view toggle
+- Uses `` for runtime component rendering
+- Type registry from `ShellDocs.Markdown` reused
+
+### `feat/animation-polish`
+Ships to `ShellDocs.Components`.
+
+- Page transitions: fade + slight translate on route change (150ms)
+- Sidebar section collapse: height animation, chevron rotation (200ms)
+- TOC scroll-spy: active indicator slides between items (spring-based)
+- Search dialog: scale + fade in from center (100ms)
+- CodeBlock copy button: checkmark morph on success (150ms + 1s hold)
+- Mobile drawer: slide from left with backdrop blur
+- `prefers-reduced-motion` respected everywhere
+- View-transitions API where supported, Motion One fallback
+
+### `chore/release-0.2.0-alpha`
+- Version bump, notes, NuGet push
+- Ready for dogfood via shellui.dev
+
+**Milestone:** ShellDocs is feature-complete for a full-featured docs site. Real content authoring can begin.
+
+---
+
+## Phase 3 — Dogfood via `shellui.dev` (~2–4 weeks)
+
+This phase happens in the `shellui-dev/shellui.dev` repo (separate from `shellui-dev/shelldocs`). Branches in that repo consume ShellDocs `0.2.0-alpha` from NuGet.
+
+Every rough edge that shellui.dev hits becomes a ShellDocs improvement, backported as patch releases (`0.2.1`, `0.2.2`, ...). Once shellui.dev is complete and smooth, ShellDocs tags `0.3.0-alpha` reflecting the hardening.
+
+Branches expected in `shellui.dev`:
+- `chore/scaffold` — `shelldocs init` a new Blazor WASM project
+- `content/introduction` — landing + introduction + installation content
+- `content/components` — ~68 component reference pages
+- `content/theming` — theming guide, tweakcn walkthrough
+- `content/cli` — CLI reference
+- `content/blocks` — layout blocks (dashboard-01, dashboard-02, ...)
+- `chore/gh-pages-deploy` — CI + CNAME to `shellui.dev`
+
+Branches expected back in `shelldocs`:
+- `fix/hardening-*` — a handful of small branches for edge cases discovered by shellui.dev
+- `chore/release-0.3.0-alpha` — reflects hardening
+
+**Milestone:** shellui.dev live at `shellui.dev`. Community-visible proof point.
+
+---
+
+## Phase 4 — ShellDocs' own site + API stability (~2 weeks)
+
+### `chore/shelldocs-dev-bootstrap` *(in `shelldocs.dev` repo, or `examples/shelldocs.dev/` in shelldocs monorepo)*
+- Bootstrap the ShellDocs docs site using ShellDocs itself
+- Author full ShellDocs docs: getting started, CLI reference, primitives reference, theming guide, migration guides
+- CNAME to `shelldocs.dev`
+
+### `feat/xml-doc-extraction`
+Ships to new package `ShellDocs.Xml`.
+
+- MSBuild task: extract XML doc comments from a project, emit JSON per public type
+- ` ` — auto-generates from the JSON
+- Optional — hand-authored `` children still supported
+
+### `chore/release-1.0.0-rc`
+- Version bump, notes, NuGet push
+- API frozen — breaking changes require major version bump from here
+
+### `chore/release-1.0.0`
+- After `rc` bakes for 2+ weeks with no critical issues
+- Announce publicly: blog post, Twitter, submit to /r/dotnet, /r/csharp, /r/blazor
+- Reach out to MudBlazor / Radzen / AvaloniaUI teams about adoption
+
+**Milestone:** ShellDocs 1.0. A stable framework anyone can adopt.
+
+---
+
+## Phase 5 — Ecosystem push (ongoing)
+
+### `feat/theme-fuma`
+Ships to new package `ShellDocs.Themes.Fuma`.
+
+- Fumadocs-inspired theme preset — different color palette, different heading treatment, different card styling
+- Preview at `shelldocs.dev/themes/fuma`
+
+### `feat/theme-nextra`
+Ships to new package `ShellDocs.Themes.Nextra`.
+
+- Nextra-inspired preset
+
+### `feat/blazor-server-support`
+Ships to `ShellDocs.Core` + `ShellDocs.Components`.
+
+- Mode flag on `AddShellDocs()` — `HostingMode.Server` vs. `HostingMode.WebAssembly`
+- Server mode gives up code-splitting benefits but wins on load time
+- Different JS interop patterns for animations under Server
+
+### `feat/openapi-reference`
+Ships to new package `ShellDocs.OpenApi`.
+
+- OpenAPI spec → API reference page generator
+- For consumers documenting REST APIs alongside their .NET client libraries
+
+### `feat/interactive-playground`
+- Roslyn WASM-based code sandbox for live component-code editing
+- Big lift — only if community demand justifies it
+
+---
+
+## Component index — which branch ships which primitive
+
+| Primitive | Branch |
+|---|---|
+| `DocsLayout` | `feat/components-shell` (Phase 1) |
+| `DocsHeader` | `feat/components-shell` (Phase 1) |
+| `DocsSidebar` | `feat/components-shell` (Phase 1) |
+| `MarkdownContent` | `feat/components-shell` (Phase 1) |
+| `CodeBlock` | `feat/codeblock-shiki` (Phase 1) |
+| `SearchDialog` | `feat/search-primitives` (Phase 2) |
+| `TableOfContents` | `feat/toc-primitive` (Phase 2) |
+| `PrevNextNav` | `feat/nav-primitives` (Phase 2) |
+| `DocsBreadcrumb` | `feat/nav-primitives` (Phase 2) |
+| `DocsTabs` | `feat/content-primitives` (Phase 2) |
+| `Callout` | `feat/content-primitives` (Phase 2) |
+| `LinkCard` | `feat/content-primitives` (Phase 2) |
+| `FileTree` | `feat/content-primitives` (Phase 2) |
+| `Steps` | `feat/content-primitives` (Phase 2) |
+| `TypeTable` | `feat/api-reference-primitives` (Phase 2) |
+| `ComponentPreview` | `feat/api-reference-primitives` (Phase 2) |
+
+---
+
+## Dependencies on ShellUI
+
+ShellDocs depends on `ShellUI.Components` for base primitives:
+
+| ShellUI primitive | Used by |
+|---|---|
+| `` | `` copy action, `` triggers, `` |
+| `` | `` |
+| `` | `` (modal wrapper) |
+| `` | `` (search interaction) |
+| `` | `` |
+| `` | `` |
+| `` | `` (or standalone) |
+| `` | `` |
+| `` | `` |
+| `` primitives | `` (composes SidebarProvider/Trigger/Content) |
+| `Shell.Cn` | Throughout |
+
+**Locked ShellUI version:** ShellDocs targets `ShellUI.Components >= 0.5.0` (the version that ships `feat/data-selection-suite` — CommandPalette is required). Bumps require a ShellDocs major/minor.
+
+---
+
+## Effort estimates (rough)
+
+| Phase | Elapsed weeks | Notes |
+|---|---|---|
+| 1 — Core framework | 4–6 | Includes learning-curve on Markdig, Shiki-WASM, CLI patterns |
+| 2 — Primitives | 2–4 | Mostly wiring — patterns from Phase 1 reused |
+| 3 — Dogfood via shellui.dev | 2–4 | Content authoring is the bulk; ShellDocs fixes are incidental |
+| 4 — ShellDocs' own site + 1.0 rc | 2 | Content authoring for ShellDocs docs |
+| 5 — Ecosystem push | Ongoing | Not blocking |
+
+**Total to 1.0-rc: ~10–16 weeks.** Solo-hackable if focused; halved with two people.
+
+---
+
+## Open questions to resolve early
+
+- **Domain registration** — grab `shelldocs.dev` before Phase 1 ends
+- **Package prefix** — `ShellDocs.*` locked in? Anyone else on NuGet using it? Verify before first publish
+- **License** — MIT to match ShellUI (default assumption unless there's reason otherwise)
+- **Contribution model** — CONTRIBUTING.md drafted before Phase 2 finishes so external contributors have a path
diff --git a/global.json b/global.json
new file mode 100644
index 0000000..7c8e277
--- /dev/null
+++ b/global.json
@@ -0,0 +1,7 @@
+{
+ "sdk": {
+ "version": "10.0.301",
+ "rollForward": "latestFeature",
+ "allowPrerelease": false
+ }
+}
diff --git a/shelldocs.slnx b/shelldocs.slnx
new file mode 100644
index 0000000..2922ba4
--- /dev/null
+++ b/shelldocs.slnx
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ShellDocs.CLI/Program.cs b/src/ShellDocs.CLI/Program.cs
new file mode 100644
index 0000000..9883404
--- /dev/null
+++ b/src/ShellDocs.CLI/Program.cs
@@ -0,0 +1,105 @@
+using System.CommandLine;
+using Spectre.Console;
+
+namespace ShellDocs.CLI;
+
+/* CLI entry point. Real command handlers land in feat/cli-init and feat/cli-dev-build.
+ This scaffolding wires up the command tree so `shelldocs --help` produces the right shape. */
+internal class Program
+{
+ // ANSI Shadow figlet — same font ShellUI uses so the family reads as one thing.
+ private const string Logo = @"
+ ███████╗██╗ ██╗███████╗██╗ ██╗ ██████╗ ██████╗ ██████╗███████╗
+ ██╔════╝██║ ██║██╔════╝██║ ██║ ██╔══██╗██╔═══██╗██╔════╝██╔════╝
+ ███████╗███████║█████╗ ██║ ██║ ██║ ██║██║ ██║██║ ███████╗
+ ╚════██║██╔══██║██╔══╝ ██║ ██║ ██║ ██║██║ ██║██║ ╚════██║
+ ███████║██║ ██║███████╗███████╗███████╗██████╔╝╚██████╔╝╚██████╗███████║
+ ╚══════╝╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═════╝ ╚═════╝ ╚═════╝╚══════╝
+";
+
+ private static int Main(string[] args)
+ {
+ var root = new RootCommand("ShellDocs — the docs framework for .NET.");
+ root.Subcommands.Add(CreateInitCommand());
+ root.Subcommands.Add(CreateNewCommand());
+ root.Subcommands.Add(CreateDevCommand());
+ root.Subcommands.Add(CreateBuildCommand());
+ root.Subcommands.Add(CreatePreviewCommand());
+ return root.Parse(args).Invoke();
+ }
+
+ private static Command CreateInitCommand()
+ {
+ var yes = new Option("--yes") { Description = "Non-interactive mode with default options." };
+ var theme = new Option("--theme")
+ {
+ Description = "Theme preset: shadcn, fuma, nextra.",
+ DefaultValueFactory = _ => "shadcn"
+ };
+ var cmd = new Command("init", "Initialize ShellDocs in a Blazor WASM project — adds packages, generates content/ and Layout/, patches Program.cs.")
+ {
+ yes, theme
+ };
+ cmd.SetAction(_ =>
+ {
+ AnsiConsole.Markup($"[blue]{Logo}[/]");
+ AnsiConsole.MarkupLine("[dim] the docs framework for .NET[/]");
+ AnsiConsole.WriteLine();
+ AnsiConsole.MarkupLine("[yellow]shelldocs init[/] — not yet implemented (feat/cli-init).");
+ });
+ return cmd;
+ }
+
+ private static Command CreateNewCommand()
+ {
+ var kind = new Argument("kind") { Description = "Template kind: page, component-page." };
+ var name = new Argument("name") { Description = "File name for the new page." };
+ var cmd = new Command("new", "Scaffold a new doc page from a template.") { kind, name };
+ cmd.SetAction(pr =>
+ {
+ AnsiConsole.MarkupLine($"[yellow]shelldocs new {pr.GetValue(kind)} {pr.GetValue(name)}[/] — not yet implemented (feat/cli-init).");
+ });
+ return cmd;
+ }
+
+ private static Command CreateDevCommand()
+ {
+ var port = new Option("--port")
+ {
+ Description = "Port to bind on.",
+ DefaultValueFactory = _ => 5000
+ };
+ var cmd = new Command("dev", "Start dev server with hot-reload for .razor / .cs / .md changes.") { port };
+ cmd.SetAction(_ =>
+ {
+ AnsiConsole.MarkupLine("[yellow]shelldocs dev[/] — not yet implemented (feat/cli-dev-build).");
+ });
+ return cmd;
+ }
+
+ private static Command CreateBuildCommand()
+ {
+ var output = new Option("--output")
+ {
+ Description = "Output directory.",
+ DefaultValueFactory = _ => "publish"
+ };
+ var cmd = new Command("build", "Produce a static site ready for GH Pages / Vercel / Netlify.") { output };
+ cmd.SetAction(_ =>
+ {
+ AnsiConsole.MarkupLine("[yellow]shelldocs build[/] — not yet implemented (feat/cli-dev-build).");
+ });
+ return cmd;
+ }
+
+ private static Command CreatePreviewCommand()
+ {
+ var name = new Argument("name") { Description = "Component name to preview." };
+ var cmd = new Command("preview", "Render a single component in isolation for design review.") { name };
+ cmd.SetAction(pr =>
+ {
+ AnsiConsole.MarkupLine($"[yellow]shelldocs preview {pr.GetValue(name)}[/] — not yet implemented.");
+ });
+ return cmd;
+ }
+}
diff --git a/src/ShellDocs.CLI/ShellDocs.CLI.csproj b/src/ShellDocs.CLI/ShellDocs.CLI.csproj
new file mode 100644
index 0000000..425e586
--- /dev/null
+++ b/src/ShellDocs.CLI/ShellDocs.CLI.csproj
@@ -0,0 +1,21 @@
+
+
+
+ Exe
+ true
+ true
+ shelldocs
+ ShellDocs.CLI
+ Global tool for ShellDocs — the docs framework for .NET. Commands: init, new, dev, build, preview.
+ ShellDocs.CLI
+ shelldocs
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ShellDocs.Components/ServiceCollectionExtensions.cs b/src/ShellDocs.Components/ServiceCollectionExtensions.cs
new file mode 100644
index 0000000..3ce46f2
--- /dev/null
+++ b/src/ShellDocs.Components/ServiceCollectionExtensions.cs
@@ -0,0 +1,39 @@
+using Microsoft.Extensions.DependencyInjection;
+using ShellDocs.Core;
+
+namespace ShellDocs.Components;
+
+/// Registers ShellDocs services with the consumer's DI container.
+/// Consumer's Program.cs calls this once — everything else is discovered by convention.
+public static class ServiceCollectionExtensions
+{
+ public static IServiceCollection AddShellDocs(
+ this IServiceCollection services,
+ Action? configure = null)
+ {
+ var options = new ShellDocsOptions();
+ configure?.Invoke(options);
+ services.AddSingleton(options);
+
+ // Real service wiring lands in feat/core-navigation-graph + feat/markdown-pipeline.
+ // Scaffolding: keep the surface consumers will call, no implementation yet.
+ return services;
+ }
+}
+
+/// Fluent options bag consumers configure in Program.cs.
+public class ShellDocsOptions
+{
+ public string ContentRoot { get; set; } = "content";
+ public string SiteName { get; set; } = "";
+ public string? GitHubRepo { get; set; }
+ public bool EnableSearch { get; set; } = true;
+ public string SearchIndexPath { get; set; } = "search-index.json";
+ public List RegisteredComponents { get; } = new();
+
+ public ShellDocsOptions RegisterComponent() where T : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ RegisteredComponents.Add(typeof(T));
+ return this;
+ }
+}
diff --git a/src/ShellDocs.Components/ShellDocs.Components.csproj b/src/ShellDocs.Components/ShellDocs.Components.csproj
new file mode 100644
index 0000000..51e3192
--- /dev/null
+++ b/src/ShellDocs.Components/ShellDocs.Components.csproj
@@ -0,0 +1,22 @@
+
+
+
+ true
+ ShellDocs.Components
+ Blazor RCL — DocsLayout, DocsSidebar, DocsHeader, CodeBlock, SearchDialog, TableOfContents, and every other primitive that makes a ShellDocs site look sleek.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ShellDocs.Components/_Imports.razor b/src/ShellDocs.Components/_Imports.razor
new file mode 100644
index 0000000..612f80f
--- /dev/null
+++ b/src/ShellDocs.Components/_Imports.razor
@@ -0,0 +1,9 @@
+@using System.Net.Http
+@using System.Net.Http.Json
+@using Microsoft.AspNetCore.Components
+@using Microsoft.AspNetCore.Components.Forms
+@using Microsoft.AspNetCore.Components.Routing
+@using Microsoft.AspNetCore.Components.Web
+@using Microsoft.JSInterop
+@using ShellDocs.Components
+@using ShellDocs.Core
diff --git a/src/ShellDocs.Components/wwwroot/shelldocs.js b/src/ShellDocs.Components/wwwroot/shelldocs.js
new file mode 100644
index 0000000..3514324
--- /dev/null
+++ b/src/ShellDocs.Components/wwwroot/shelldocs.js
@@ -0,0 +1,9 @@
+// ShellDocs JS interop — mirrors the ShellUI pattern:
+// window.ShellDocs monolith for classic consumption + ES module exports for dynamic import.
+// Real implementation lands with the primitives that need JS (SearchDialog hotkey, scroll-spy, etc.)
+
+window.ShellDocs = window.ShellDocs || {};
+
+Object.assign(window.ShellDocs, {
+ // Populated in Phase 1 branches. Kept here as the extension point.
+});
diff --git a/src/ShellDocs.Core/NavigationNode.cs b/src/ShellDocs.Core/NavigationNode.cs
new file mode 100644
index 0000000..d3cad6b
--- /dev/null
+++ b/src/ShellDocs.Core/NavigationNode.cs
@@ -0,0 +1,17 @@
+namespace ShellDocs.Core;
+
+/// One page in the ShellDocs navigation graph. Built from a .md file's frontmatter + path.
+public class NavigationNode
+{
+ public required string Url { get; init; }
+ public required string Title { get; init; }
+ public string? Description { get; init; }
+ public string? Category { get; init; }
+ public int Order { get; init; }
+ public string? Path { get; init; }
+ public IReadOnlyList Headings { get; init; } = Array.Empty();
+ public NavigationNode? Parent { get; internal set; }
+ public IReadOnlyList Children { get; internal set; } = Array.Empty();
+}
+
+public record Heading(int Level, string Text, string Id);
diff --git a/src/ShellDocs.Core/ShellDocs.Core.csproj b/src/ShellDocs.Core/ShellDocs.Core.csproj
new file mode 100644
index 0000000..768f355
--- /dev/null
+++ b/src/ShellDocs.Core/ShellDocs.Core.csproj
@@ -0,0 +1,15 @@
+
+
+
+ true
+ ShellDocs.Core
+ Navigation graph, search index model, and routing helpers for ShellDocs — the docs framework for .NET.
+
+
+
+
+
+
+
+
+
diff --git a/src/ShellDocs.Markdown/MarkdownPipelineFactory.cs b/src/ShellDocs.Markdown/MarkdownPipelineFactory.cs
new file mode 100644
index 0000000..997ee0b
--- /dev/null
+++ b/src/ShellDocs.Markdown/MarkdownPipelineFactory.cs
@@ -0,0 +1,15 @@
+using Markdig;
+
+namespace ShellDocs.Markdown;
+
+/// Configures a Markdig pipeline with ShellDocs' custom extensions:
+/// YAML frontmatter, razor:preview fenced blocks, inline Razor component tags.
+public static class MarkdownPipelineFactory
+{
+ // Real implementation lands in feat/markdown-pipeline. This stub gets us compiling.
+ public static MarkdownPipeline Create() =>
+ new MarkdownPipelineBuilder()
+ .UseAdvancedExtensions()
+ .UseYamlFrontMatter()
+ .Build();
+}
diff --git a/src/ShellDocs.Markdown/ShellDocs.Markdown.csproj b/src/ShellDocs.Markdown/ShellDocs.Markdown.csproj
new file mode 100644
index 0000000..8e517c7
--- /dev/null
+++ b/src/ShellDocs.Markdown/ShellDocs.Markdown.csproj
@@ -0,0 +1,15 @@
+
+
+
+ true
+ ShellDocs.Markdown
+ Markdig pipeline for ShellDocs — frontmatter parsing, razor:preview fenced blocks, inline Razor component tags.
+
+
+
+
+
+
+
+
+
diff --git a/src/ShellDocs.Templates/ShellDocs.Templates.csproj b/src/ShellDocs.Templates/ShellDocs.Templates.csproj
new file mode 100644
index 0000000..1b97b38
--- /dev/null
+++ b/src/ShellDocs.Templates/ShellDocs.Templates.csproj
@@ -0,0 +1,9 @@
+
+
+
+ true
+ ShellDocs.Templates
+ Templates used by the ShellDocs CLI to scaffold new doc projects and pages. Not intended for direct consumption.
+
+
+
diff --git a/src/ShellDocs.Templates/StarterPageTemplate.cs b/src/ShellDocs.Templates/StarterPageTemplate.cs
new file mode 100644
index 0000000..71f6018
--- /dev/null
+++ b/src/ShellDocs.Templates/StarterPageTemplate.cs
@@ -0,0 +1,17 @@
+namespace ShellDocs.Templates;
+
+/// Starter markdown emitted by `shelldocs new page`.
+/// Real templates land alongside the CLI init/new commands.
+public static class StarterPageTemplate
+{
+ public static string Content(string title, string description) => $$"""
+ ---
+ title: {{title}}
+ description: {{description}}
+ ---
+
+ # {{title}}
+
+ Start writing.
+ """;
+}
diff --git a/tests/ShellDocs.Tests/ScaffoldingTests.cs b/tests/ShellDocs.Tests/ScaffoldingTests.cs
new file mode 100644
index 0000000..a27e6a8
--- /dev/null
+++ b/tests/ShellDocs.Tests/ScaffoldingTests.cs
@@ -0,0 +1,35 @@
+using ShellDocs.Core;
+using ShellDocs.Markdown;
+using ShellDocs.Templates;
+using Xunit;
+
+namespace ShellDocs.Tests;
+
+// Smoke tests — verify each package's public surface loads and its trivial APIs behave.
+// Real tests land branch-by-branch.
+public class ScaffoldingTests
+{
+ [Fact]
+ public void NavigationNode_HoldsRequiredFields()
+ {
+ var node = new NavigationNode { Url = "/docs/hello", Title = "Hello" };
+ Assert.Equal("/docs/hello", node.Url);
+ Assert.Equal("Hello", node.Title);
+ }
+
+ [Fact]
+ public void MarkdownPipelineFactory_ProducesUsablePipeline()
+ {
+ var pipeline = MarkdownPipelineFactory.Create();
+ Assert.NotNull(pipeline);
+ }
+
+ [Fact]
+ public void StarterPageTemplate_EmitsFrontmatterAndBody()
+ {
+ var content = StarterPageTemplate.Content("Introduction", "Getting started with ShellDocs");
+ Assert.Contains("title: Introduction", content);
+ Assert.Contains("description: Getting started with ShellDocs", content);
+ Assert.Contains("# Introduction", content);
+ }
+}
diff --git a/tests/ShellDocs.Tests/ShellDocs.Tests.csproj b/tests/ShellDocs.Tests/ShellDocs.Tests.csproj
new file mode 100644
index 0000000..ee33a79
--- /dev/null
+++ b/tests/ShellDocs.Tests/ShellDocs.Tests.csproj
@@ -0,0 +1,21 @@
+
+
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+