Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,31 @@ All notable changes to ShellDocs land here. Format follows [Keep a Changelog](ht

## [Unreleased]

## [0.1.18-alpha] — 2026-10-19

Colour presets, `shelldocs preview` for checking a static export locally, package pages on NuGet that render properly, plus fixes for sub-path links, folder titles and entities in component attributes.

### Added

- **`shelldocs preview`** ([#43](https://github.com/shellui-dev/shelldocs/issues/43)). Serves the output of `shelldocs build` (`publish/`, or `--output`) on `http://localhost:5050` (`--port`) the way static hosts do: folders serve their `index.html`, unknown URLs get `404.html` with a 404, and an export built with `--base-href` is served under that path (read from the export, or pass `--base-href`). Responses aren't cached, so a rebuild shows on reload. The old `preview <name>` stub is gone. The CLI now needs the ASP.NET Core runtime, which any machine building a Blazor site already has.
- **Colour presets** ([#44](https://github.com/shellui-dev/shelldocs/issues/44)). `o.Theme = ShellDocsTheme.Harbor` (or `shelldocs init --theme harbor`) swaps the neutral palette for a tinted one: `Harbor` (blue), `Lagoon` (teal), `Forest` (green), `Savanna` (amber on sand), `Ember` (red-orange) or `Jacaranda` (purple). Each covers light and dark mode, tints backgrounds, borders and muted text, and colours the active sidebar item, focus rings, links and other accents, with text at 4.5:1 or better. The default, `Graphite`, is the existing palette. Presets are CSS in `tokens.css` keyed on a `data-shelldocs-theme` attribute the layouts render, so they work in static exports and your own token overrides still win.
- **`CONTRIBUTING.md`** ([#45](https://github.com/shellui-dev/shelldocs/issues/45)): setup, trying a change in the example site and a static export, the static-host rule, and how commits and changelog entries are laid out.

### Fixed

- **NuGet package pages showed raw HTML.** All six packages shipped the GitHub README, whose centred header and badges are HTML that nuget.org prints as text. Each package now has its own Markdown README, and `scripts/pack-dry-run` fails on HTML in a package README. The PowerShell version of that script also runs on Windows PowerShell 5.1 again.
- **A folder's `meta.json` `title` was ignored** ([#41](https://github.com/shellui-dev/shelldocs/issues/41)). The folder's section in the sidebar, breadcrumb and search took its title from the folder name (`maui` → "Maui"). It now uses the folder's own `meta.json` `title` when set, and falls back to the name otherwise. Sites whose folders set a `title` will see it, e.g. a top-level `docs/meta.json` titled "Documentation" now reads that way instead of "Docs".
- **HTML entities in component attributes showed literally** ([#42](https://github.com/shellui-dev/shelldocs/issues/42)). `<Callout Title="Tom &amp; Jerry" />` in Markdown or a `razor:preview` fence now passes "Tom & Jerry", as Razor does. `@` expressions, directive attributes (`@onclick`, `@bind-…`) and code spans inside a value stay as written.
- **Links broke on sites served from a sub-path** ([#40](https://github.com/shellui-dev/shelldocs/issues/40)). Sidebar, breadcrumb, header, prev/next, content and favicon links are root-relative (`/docs/introduction`), which ignores `<base href>`, so an export built with `--base-href /my-repo/` linked outside the site. `shelldocs build --base-href` now also puts the base in front of root-relative `href`, `src` and `data-src` values in every exported page.

### Changed

- **`ShellDocsTheme.Shadcn`, `Fuma` and `Nextra` are obsolete** aliases of `Graphite`. They never changed the palette; `Fuma` and `Nextra` promised a look that a palette can't give. `shelldocs init --theme` takes the new preset names.

### Removed

- **`SearchState`, `SidebarCollapseState` and `MobileNavState`** ([#46](https://github.com/shellui-dev/shelldocs/issues/46)). Search, the sidebar collapse and the mobile drawer run in `shelldocs.js`, so nothing used these services; `AddShellDocs` no longer registers them. Code that injects one needs its own copy.

## [0.1.17-alpha] — 2026-10-14

llms.txt for AI agents, and five fixes found while writing the ShellDocs docs site.
Expand Down
59 changes: 59 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Contributing to ShellDocs

Thanks for helping. Bug reports, fixes and docs improvements are all welcome. For anything bigger than a fix, open an issue first so we can agree on the shape before you write it.

ShellDocs is in alpha: minor versions may break APIs until `1.0`.

## Setup

You need the .NET 10 SDK (the version is pinned in `global.json`).

```bash
dotnet build shelldocs.slnx
dotnet test shelldocs.slnx
```

CI runs the same two commands in Release, and a pull request should pass both with no new warnings.

## Trying a change

`examples/ShellDocs.Preview` is a docs site wired to the projects in this repo, so changes show up without packing anything:

```bash
dotnet run --project examples/ShellDocs.Preview
```

Anything in the chrome or in `shelldocs.js` also has to work in a static export. Build one with the CLI from source into the example's `publish/` (ignored by git) and serve it:

```bash
dotnet run --project src/ShellDocs.CLI -- build --dir examples/ShellDocs.Preview
dotnet run --project src/ShellDocs.CLI -- preview --dir examples/ShellDocs.Preview
```

Add `--base-href /sub/` to the build to check a site served from a sub-path.

## The static-host rule

Static exports have no Blazor runtime, so `@onclick` handlers and component state do nothing there. Chrome that must work on a static host follows one pattern:

- the server renders the initial state into `data-*` attributes and classes;
- `shelldocs.js` handles the interaction with delegated, document-level listeners;
- state that a Blazor circuit replaces when it starts is restored by `shelldocs.js`.

`docs/ARCHITECTURE.md` describes how each piece of chrome does this. Interactive Blazor is fine for demos and previews, which are allowed to need a running app.

## Commits and pull requests

- Branch off `main` and open the pull request against it.
- Use [Conventional Commits](https://www.conventionalcommits.org/): `fix(markdown): …`, `feat(cli): …`, `docs: …`, `chore: …`.
- One logical change per commit, and each commit builds and passes the tests on its own.
- Add tests for what you fix or add (`tests/ShellDocs.Tests`).
- Add a line to `CHANGELOG.md` under `[Unreleased]`, saying what changed for someone using ShellDocs.
- Update `README.md` or `docs/ARCHITECTURE.md` when behaviour they describe changes.
- Keep code comments to what isn't obvious from the code.

Releases are cut by the maintainers (see `docs/RELEASING.md`).

## License

By contributing you agree that your contributions are licensed under the [MIT License](LICENSE).
6 changes: 4 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

<!-- Package metadata (applies to any project with IsPackable=true) -->
<PropertyGroup>
<Version>0.1.17-alpha</Version>
<Version>0.1.18-alpha</Version>
<Authors>ShellUI</Authors>
<Company>ShellUI</Company>
<Copyright>Copyright © 2026 ShellUI</Copyright>
Expand All @@ -39,7 +39,9 @@
</PropertyGroup>

<ItemGroup Condition="'$(IsPackable)' == 'true'">
<None Include="$(MSBuildThisFileDirectory)README.md" Pack="true" PackagePath="\" />
<!-- Each package ships its own Markdown README: nuget.org shows raw HTML, so the
GitHub README (centred <picture> header) can't be the package page. -->
<None Include="$(MSBuildProjectDirectory)\README.md" Pack="true" PackagePath="\" />
<None Include="$(MSBuildThisFileDirectory)assets\icon.png" Pack="true" PackagePath="\" Visible="false" />
</ItemGroup>

Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ shelldocs add guide getting-started
# Run with hot reload on http://localhost:5000
shelldocs dev

# Prerender a static site into publish/
# Prerender a static site into publish/, then serve it as a static host would
shelldocs build
shelldocs preview
```

Already have a Blazor project? Run `shelldocs init --attach` inside it: it adds the packages and content, and writes `SHELLDOCS_SETUP.md` with the `Program.cs` / `App.razor` snippets instead of editing your code.
Expand All @@ -51,14 +52,15 @@ Already have a Blazor project? Run `shelldocs init --attach` inside it: it adds
- **File-based navigation.** Drop a `.md` in `content/docs/` and it's a page. Sidebar, breadcrumb, prev/next and TOC come from the folder tree; `meta.json` controls order, dividers, subsections and hidden pages.
- **`Cmd+K` search** across titles, headings and page text, with body snippets. The index is built at startup and searched in the browser, so there's no external service and it works in the static export too.
- **llms.txt for AI agents.** `o.EnableLlmsTxt()` serves `/llms.txt`, `/llms-full.txt` and every page as Markdown at its URL + `.md`, plus `AGENTS.md`, `CLAUDE.md`, Copilot and Cursor instruction files, and adds a **Copy page / View as Markdown / Open in Claude / Open in ChatGPT** menu by the title. See [AI agents](#ai-agents-llmstxt).
- **Colour presets.** `o.Theme = ShellDocsTheme.Harbor`: Graphite (default), Harbor, Lagoon, Forest, Savanna, Ember or Jacaranda, in light and dark. Or override the tokens yourself.
- **Blazor-native.** Your components render as real Razor components, not iframes.
- **Composable.** Bring your own component library (ShellUI, MudBlazor, Radzen, hand-rolled) and register it in one line:
```csharp
o.RegisterComponentsFromAssembly<MyLib.Button>();
```
Your components win name collisions with ShellDocs' built-ins, which stay available as `<DocsCard>`, `<DocsCallout>`, `<DocsTabs>`, and so on.
- **Content primitives.** `Callout`, `Card` / `CardGrid` / `LinkCard`, `Steps`, `FileTree`, `Tabs`, `CodeGroup`, `TypeTable` / `AutoTypeTable`, `ComponentPreview`, `DemoPreview`.
- **Static export.** `shelldocs build` prerenders every page to static HTML for GitHub Pages, Cloudflare Pages, Netlify or S3. Optional flags rewrite `<base href>` and root-relative links for a sub-path (`--base-href`), add a SPA `404.html` (`--spa-fallback`), and write sitemap / robots / `og:` meta (`--site-url`). Navigation, sidebar sections and collapse, the mobile menu, selectors, tabs, preview toolbars, the TOC, code copy, the theme toggle and search work there through `shelldocs.js`. Only stateful demos need a running Blazor app. Unknown pages answer 404 (`<DocsNotFound />` in the docs page) and `build` writes the same view as `404.html`.
- **Static export.** `shelldocs build` prerenders every page to static HTML for GitHub Pages, Cloudflare Pages, Netlify or S3. Optional flags rewrite `<base href>` and root-relative links for a sub-path (`--base-href`), add a SPA `404.html` (`--spa-fallback`), and write sitemap / robots / `og:` meta (`--site-url`). Navigation, sidebar sections and collapse, the mobile menu, selectors, tabs, preview toolbars, the TOC, code copy, the theme toggle and search work there through `shelldocs.js`. Only stateful demos need a running Blazor app. Unknown pages answer 404 (`<DocsNotFound />` in the docs page) and `build` writes the same view as `404.html`. `shelldocs preview` serves the export locally, under the `--base-href` path if it has one, to check it before deploying.

## Versioned docs

Expand Down Expand Up @@ -170,7 +172,7 @@ The Markdown is the page source with ShellDocs tags turned into Markdown: demos

## Contributing

The alpha is API-fluid: we're taking freedom to break minor versions until `1.0`. Bug reports and dogfood-driven fixes are welcome via issues. A proper `CONTRIBUTING.md` lands with the `0.2.0-alpha` cut.
The alpha is API-fluid: we're taking freedom to break minor versions until `1.0`. Bug reports and fixes are welcome; see [CONTRIBUTING.md](CONTRIBUTING.md) for setup, the static-host rule and how commits are laid out.

## License

Expand Down
11 changes: 7 additions & 4 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ The `shelldocs` global tool and the file content it writes. See [CLI](#cli).
`AddShellDocs` (in `ServiceCollectionExtensions.cs`):

1. Builds `ShellDocsOptions` and runs the consumer's `configure` callback.
2. Registers the scoped chrome state (`MobileNavState`, `ThemeState`, `SearchState`, `SidebarCollapseState`, `CodeGroupSyncState`, `DocsPageState`).
2. Registers the scoped chrome state (`ThemeState`, `CodeGroupSyncState`, `DocsPageState`).
3. Adds every component in `ShellDocs.Components.Content` as a built-in.
4. Registers singletons: `TypeRegistry` (built lazily from the options, collisions logged), `MarkdownRenderer`, `NavigationGraph` (empty graph if `ContentRoot` doesn't exist), `SearchIndex`, `DocsVersionResolver`.

Expand Down Expand Up @@ -144,6 +144,7 @@ Component child markup is rendered recursively. Inline tags in prose take markdo

- Every `.md` file is a page; `index.md` takes the folder's URL. Frontmatter supplies `title` (else derived from the slug), `description`, `category`, `order`.
- Every subfolder is a section titled from its name. Folder names keep their dots (`v0.2.1`).
- A folder's section takes the `title` from its own `meta.json`, else one made from the folder name.
- Without `meta.json`: subfolders first, then pages by `order` and title.
- With `meta.json`: `pages` sets the order for what it lists: a slug, `"---"` for a divider, or `{ "title", "pages" }` for a subsection. Unlisted files and folders are appended alphabetically, and unknown slugs are ignored. `hidden` entries route but stay out of the sidebar and prev/next.

Expand Down Expand Up @@ -242,17 +243,19 @@ Chrome that must work without a Blazor runtime follows one contract:

## Theming

One neutral, shadcn-shaped palette of CSS variables in `ShellDocs.Tokens/tokens.css` (`:root` and `:root.dark`). Component styles are scoped CSS reading those variables, plus `shelldocs-theme.css` for global prose, code-block and Shiki styling. Restyle by overriding variables in a stylesheet loaded after `tokens.css`. `ShellDocsOptions.Theme` exists but doesn't switch palettes yet.
A neutral, shadcn-shaped palette of CSS variables in `ShellDocs.Tokens/tokens.css` (`:root` and `:root.dark`), called Graphite. Component styles are scoped CSS reading those variables, plus `shelldocs-theme.css` for global prose, code-block and Shiki styling. Restyle by overriding variables in a stylesheet loaded after `tokens.css`.

Colour presets (`ShellDocsOptions.Theme`: Harbor, Lagoon, Forest, Savanna, Ember, Jacaranda) are further blocks in `tokens.css`. `DocsLayout` and `HomeLayout` put `data-shelldocs-theme="harbor"` on their shell (nothing for Graphite), and `:root:has(:where([data-shelldocs-theme="harbor"]))` / `:root.dark:has(…)` set every colour token from it. The `:where()` keeps those rules at the specificity of `:root` / `:root.dark`, so a later stylesheet still overrides them, and the variables sit on `:root`, so the body, previews and the search dialog cloned onto `<body>` follow too. Each preset tints the neutrals with its hue and sets `--primary`, `--accent` / `--accent-foreground` (the active sidebar item) and `--ring`; text pairs are at least 4.5:1 in light and dark.

---

## CLI

- `shelldocs init [path] [--attach] [--dir] [--yes] [--theme]` — create mode runs `dotnet new blazor` (default `docs/<CwdName>.Docs`), adds the packages at the CLI's own version, writes starter content and patches `Program.cs` / `App.razor`. Attach mode augments an existing project and writes `SHELLDOCS_SETUP.md` instead of editing code. Both are idempotent.
- `shelldocs init [path] [--attach] [--dir] [--yes] [--theme graphite|harbor|…]` — create mode runs `dotnet new blazor` (default `docs/<CwdName>.Docs`), adds the packages at the CLI's own version, writes starter content and patches `Program.cs` / `App.razor`. Attach mode augments an existing project and writes `SHELLDOCS_SETUP.md` instead of editing code. Both are idempotent.
- `shelldocs add <component|guide|page> <name> [--force]` — scaffolds a page into `content/docs/`.
- `shelldocs dev [--port 5000]` — `dotnet watch run`, with `content/**/*.md` added to the watch set.
- `shelldocs build [--output publish] [--base-href] [--spa-fallback] [--site-url]` — see below.
- `shelldocs preview` — reserved, not implemented.
- `shelldocs preview [--output publish] [--port 5050] [--base-href]` — serves an export with Kestrel as static hosts do: a file, else the folder's `index.html`, else `{path}.html`, else `404.html` with a 404. The base path defaults to the export's `<base href>`; responses are `no-cache` so a rebuild shows on reload.

### Static site generation

Expand Down
2 changes: 1 addition & 1 deletion docs/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Living design doc. Updated as decisions land.

> **Status:** this is the original product design. Several parts landed differently — search builds its index in memory and needs a running Blazor app, previews use a Preview | Code toolbar, there is a single token palette (no Fuma / Nextra presets yet), and ShellDocs doesn't depend on `ShellUI.Components`. For what's actually built see [ARCHITECTURE.md](ARCHITECTURE.md) and the [CHANGELOG](../CHANGELOG.md).
> **Status:** this is the original product design. Several parts landed differently — search builds its index in memory and needs a running Blazor app, previews use a Preview | Code toolbar, colour presets (Harbor, Lagoon, …) replaced the Fuma / Nextra theme idea, and ShellDocs doesn't depend on `ShellUI.Components`. For what's actually built see [ARCHITECTURE.md](ARCHITECTURE.md) and the [CHANGELOG](../CHANGELOG.md).

---

Expand Down
5 changes: 4 additions & 1 deletion docs/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ Ships to `ShellDocs.Components` + `ShellDocs.Templates` + `ShellDocs.CLI` + `She
**Authoring fix (`ShellDocs.Markdown`)**
- `SlotExtractor.ReplaceComponentTags` no longer `.Trim()`s the raw child content of inline component tags. The Trim was stripping the first line's indent and defeating `SlotRenderer.Dedent` — Markdig then interpreted the remaining 4-space-indented lines as an indented code block. Symptom was the same "literal `<pre>` around placeholder divs" bug that had already been fixed for `razor:preview` fences; the inline-tag code path was still hitting it.

### ✅ Hardening releases (`0.1.3`–`0.1.17-alpha`) — shipped
### ✅ Hardening releases (`0.1.3`–`0.1.18-alpha`) — shipped
Driven by building the ShellUI docs on ShellDocs. Highlights (details in the CHANGELOG):

- `feat/build-static-prerender` (0.1.5) — `shelldocs build` prerenders every URL into a static site.
Expand All @@ -224,6 +224,7 @@ Driven by building the ShellUI docs on ShellDocs. Highlights (details in the CHA
- `feat/static-search` (0.1.15) — search runs in `shelldocs.js` against `/_shelldocs/search.json`, which `build` copies into the export, so static sites have search.
- `fix/iframe-preview-navigation` (0.1.16) — an `<IframePreview>` reused for the next page after in-site navigation is unloaded and set up again.
- `fix/docs-site-findings` (0.1.17) — llms.txt for AI agents (`EnableLlmsTxt`: `/llms.txt`, `/llms-full.txt`, per-page `.md`, agent instruction files, page actions menu, static export); HTML-only `razor:preview` fences render live, `404.html` shows the visitor's path, `LogoSvg` sizing, search on `HomeLayout`, spacing in the missing-tab note.
- `fix/base-href-links`, `fix/nuget-readme-and-issues` (0.1.18) — `shelldocs preview` serves an export locally; Markdown READMEs per package for nuget.org; `--base-href` prefixes root-relative links in the export; folder sections use their `meta.json` `title`; entities in component attribute values are decoded; colour presets (`o.Theme`: Graphite, Harbor, Lagoon, Forest, Savanna, Ember, Jacaranda) in place of the never-built Fuma / Nextra; unused chrome state services removed; CONTRIBUTING.md.
- `fix/preview-fidelity`, `feat/generics-redirects-page-title` (0.1.10) — `not-prose` previews, Razor child content, stretch layout, generic components in markdown, redirects (middleware + static pages), `RenderPageTitle`, theme sync and a static-host `ThemeToggle`.

### `feat/animation-polish`
Expand Down Expand Up @@ -298,6 +299,8 @@ Ships to new package `ShellDocs.Xml`.

## Phase 5 — Ecosystem push (ongoing)

*Replaced in 0.1.18 by colour presets in `ShellDocs.Tokens` (`o.Theme`: Graphite, Harbor, Lagoon, Forest, Savanna, Ember, Jacaranda). Presets that also change layout or typography would still be new work.*

### `feat/theme-fuma`
Ships to new package `ShellDocs.Themes.Fuma`.

Expand Down
Loading
Loading