dogsbay 0.2.0-beta.2 → 0.2.0-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/agent.js +305 -0
- package/dist/commands/site-build.js +66 -15
- package/dist/commands/site-dev.js +181 -23
- package/dist/commands/site-init.js +193 -32
- package/dist/config/defaults.js +8 -1
- package/dist/config/load.js +6 -32
- package/dist/config/to-astro-options.js +1 -0
- package/dist/import-content.js +13 -12
- package/dist/index.js +19 -4
- package/dist/passthrough-astro.js +152 -0
- package/dist/registry.js +8 -0
- package/package.json +11 -9
- package/skills/platform/agent-readiness/SKILL.md +262 -0
- package/skills/platform/cli-commands/SKILL.md +205 -0
- package/skills/platform/config-yml/SKILL.md +219 -0
- package/skills/platform/frontmatter-fields/SKILL.md +310 -0
- package/skills/platform/markdown-directives/SKILL.md +329 -0
- package/skills/platform/multi-source/SKILL.md +294 -0
- package/skills/platform/nav-file/SKILL.md +107 -0
- package/skills/platform/openapi-source/SKILL.md +237 -0
- package/skills/platform/plugin-api/SKILL.md +280 -0
- package/skills/platform/project-anatomy/SKILL.md +156 -0
- package/skills/platform/taxonomy-config/SKILL.md +392 -0
- package/skills/platform/theme-tokens/SKILL.md +276 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dogsbay:frontmatter-fields
|
|
3
|
+
description: Reference for the frontmatter fields Dogsbay recognises and how the importers + audit rules use them. Use when adding YAML frontmatter to a content/*.md page or debugging why a field isn't taking effect.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Frontmatter fields
|
|
7
|
+
|
|
8
|
+
Every Dogsbay markdown page can declare YAML frontmatter at
|
|
9
|
+
the top, delimited by `---` lines. The importer parses it via
|
|
10
|
+
`gray-matter`; the recognised keys flow into `ExportPage` and
|
|
11
|
+
the rendered `.astro` page.
|
|
12
|
+
|
|
13
|
+
```markdown
|
|
14
|
+
---
|
|
15
|
+
title: Configuration
|
|
16
|
+
description: How to configure your Dogsbay site.
|
|
17
|
+
draft: false
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# Configuration
|
|
21
|
+
|
|
22
|
+
…
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Three categories of frontmatter
|
|
26
|
+
|
|
27
|
+
Dogsbay sees three distinct kinds of frontmatter, and they're
|
|
28
|
+
easy to confuse:
|
|
29
|
+
|
|
30
|
+
1. **Built-in fields** with semantic meaning — Dogsbay's
|
|
31
|
+
importer (`parseMeta`) lifts these into `ExportPage` and the
|
|
32
|
+
layout reads them. Setting them produces visible effects
|
|
33
|
+
(chips, badges, build-time gates, SEO meta).
|
|
34
|
+
2. **User-declared taxonomies** — keys you name in
|
|
35
|
+
`taxonomies:` config get lifted into `meta.taxonomies[name]`
|
|
36
|
+
and produce browse pages, faceted search, and (for the five
|
|
37
|
+
built-ins below) chips. See `dogsbay:taxonomy-config`.
|
|
38
|
+
3. **Arbitrary frontmatter** — anything else is preserved
|
|
39
|
+
on `ExportPage.frontmatter` but not consumed. Suitable for
|
|
40
|
+
build-tool inputs, internal annotations, or fields that
|
|
41
|
+
future plugins might read.
|
|
42
|
+
|
|
43
|
+
The three tiers are mutually exclusive: `tags` is a built-in
|
|
44
|
+
(tier 1), not "user-defined" (tier 2). Custom `difficulty`
|
|
45
|
+
declared in your `taxonomies:` config is tier 2, not tier 3.
|
|
46
|
+
|
|
47
|
+
# Tier 1: Built-in fields
|
|
48
|
+
|
|
49
|
+
Each subsection groups built-ins by purpose. Setting any of
|
|
50
|
+
these produces a real effect — they aren't opaque slots.
|
|
51
|
+
|
|
52
|
+
## Identification
|
|
53
|
+
|
|
54
|
+
| Field | Type | Purpose |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| `title` | string | Page title. Used in `<title>` tag, sidebar fallback, OG meta. Default: H1 of body, or filename. |
|
|
57
|
+
| `description` | string | Page description. Used in `<meta name="description">`, OG description, search snippets. Treated as load-bearing for SEO and AEO. |
|
|
58
|
+
|
|
59
|
+
## Routing
|
|
60
|
+
|
|
61
|
+
| Field | Type | Purpose |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| `redirect` | string | Page is a redirect-only route. Renders no body; emits a 0-byte `<meta http-equiv="refresh">` page that points at the value. Use when you need a stable old URL to point at a new page. |
|
|
64
|
+
| `slug` | string | Override the URL slug (default: filename without `.md`). Use sparingly — file paths are usually the better source of truth. |
|
|
65
|
+
|
|
66
|
+
## Visibility
|
|
67
|
+
|
|
68
|
+
| Field | Type | Default | Purpose |
|
|
69
|
+
|---|---|---|---|
|
|
70
|
+
| `draft` | boolean | `false` | When `true`, the page is excluded from production builds (`dogsbay site build`). It IS included in `dogsbay site dev` so the writer can preview. |
|
|
71
|
+
| `noindex` | boolean | `false` | Adds `<meta name="robots" content="noindex">`. Page is still public; just hidden from external search engines. |
|
|
72
|
+
| `excludeFromSearch` | boolean | `false` | Skip Pagefind indexing for this page. Use for legal pages, redirect stubs, etc. Independent of `noindex` — a page can be in-site-searchable but external-noindex, or vice versa. |
|
|
73
|
+
|
|
74
|
+
The escape hatch for production builds is `--include-drafts`
|
|
75
|
+
on `dogsbay site build` (matches the always-on behaviour of
|
|
76
|
+
`dogsbay site dev`). The build line prints "(N drafts excluded)"
|
|
77
|
+
so the writer notices.
|
|
78
|
+
|
|
79
|
+
`status: draft` is **also** a build-time visibility gate (see
|
|
80
|
+
the "`status` is dual-purpose" subsection below).
|
|
81
|
+
|
|
82
|
+
**Don't stamp `draft: true` or `status: draft` on new pages
|
|
83
|
+
proactively.** In a git-backed site, draftness is the branch
|
|
84
|
+
state — the page is a draft because the PR isn't merged, not
|
|
85
|
+
because of frontmatter. Layering frontmatter draft flags on top
|
|
86
|
+
creates an invisible second gate that survives the merge: the
|
|
87
|
+
PR ships, but the page silently doesn't appear in production
|
|
88
|
+
because nobody removed the flag. Default to no draft flag and
|
|
89
|
+
let branches do the gating. Only stamp draft when the writer
|
|
90
|
+
explicitly asks (or there's no git workflow at all).
|
|
91
|
+
|
|
92
|
+
## Content classification (also taxonomies)
|
|
93
|
+
|
|
94
|
+
These five fields are first-class Dogsbay metadata AND drive
|
|
95
|
+
the taxonomy system when declared in `taxonomies:` config. They
|
|
96
|
+
have semantic effects regardless of whether you declare a
|
|
97
|
+
taxonomy:
|
|
98
|
+
|
|
99
|
+
| Field | Type | Purpose |
|
|
100
|
+
|---|---|---|
|
|
101
|
+
| `type` | string | Open string — `tutorial`, `how-to`, `reference`, `explanation`, or any custom value. Renders a `<TypeBadge>`; drives Schema.org JSON-LD selection (`HowTo` for how-tos, `TechArticle` for references). |
|
|
102
|
+
| `status` | enum | Closed enum — `draft \| preview \| stable \| deprecated`. Renders a `<StatusBadge>`. **`draft` is special-cased** (see below). |
|
|
103
|
+
| `audience` | string[] | Who the page is for. Single string is coerced to a one-element array. Surfaced as `<div data-pagefind-filter="audience:<value>">` for search facets. |
|
|
104
|
+
| `category` | string[] | Category segments. Auto-derived from path when absent (e.g. `/guides/auth/foo` → `["guides", "auth"]`). Hidden Pagefind facet. |
|
|
105
|
+
| `tags` | string[] | Free-form chip strip on the article header. Slash-nested values link to taxonomy term pages (`api/rest` → `/tags/api/rest/`). |
|
|
106
|
+
|
|
107
|
+
When **declared in `taxonomies:` config** (recommended), these
|
|
108
|
+
also light up:
|
|
109
|
+
|
|
110
|
+
- A browse index (`/tags/`, `/by-type/`, `/by-status/`, etc.)
|
|
111
|
+
- Per-term pages (`/tags/concept/auth`, `/by-type/tutorial`)
|
|
112
|
+
- A faceted-search checkbox group in `Cmd+K` search (one column
|
|
113
|
+
per declared taxonomy, sorted by frequency)
|
|
114
|
+
- Display-config consumption for human labels and prefix
|
|
115
|
+
colors
|
|
116
|
+
|
|
117
|
+
See `dogsbay:taxonomy-config` for the full taxonomy surface.
|
|
118
|
+
|
|
119
|
+
### `status` is dual-purpose
|
|
120
|
+
|
|
121
|
+
`status: draft` is **both** a taxonomy value AND aliased to
|
|
122
|
+
`draft: true` as a build-time visibility gate. A page with
|
|
123
|
+
`status: draft` is excluded from production builds the same
|
|
124
|
+
way `draft: true` is. The other three values (`preview`,
|
|
125
|
+
`stable`, `deprecated`) are pure taxonomy — they render a
|
|
126
|
+
`<StatusBadge>` chip and populate the `/by-status/` browse
|
|
127
|
+
page, but don't gate visibility.
|
|
128
|
+
|
|
129
|
+
This is the only built-in taxonomy with overloaded semantics.
|
|
130
|
+
Implications:
|
|
131
|
+
|
|
132
|
+
- `status: draft` + `dogsbay site build` → page omitted from
|
|
133
|
+
output (the same N-drafts-excluded message fires).
|
|
134
|
+
- `status: preview` / `stable` / `deprecated` → page ships
|
|
135
|
+
normally; just renders the badge and gets bucketed into
|
|
136
|
+
`/by-status/<value>/`.
|
|
137
|
+
- A writer who wants `draft` to be a pure taxonomy value
|
|
138
|
+
(no exclusion) should rename to a different value (e.g.
|
|
139
|
+
`status: in-progress`) and customize the badge label via
|
|
140
|
+
`taxonomies.status.labels`.
|
|
141
|
+
|
|
142
|
+
The escape hatch on `dogsbay site build` is `--include-drafts`
|
|
143
|
+
(see the visibility section above).
|
|
144
|
+
|
|
145
|
+
## SEO / social
|
|
146
|
+
|
|
147
|
+
| Field | Type | Purpose |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| `ogImage` | string | Per-page Open Graph image URL. Falls back to `siteConfig.ogImage` then no OG image. |
|
|
150
|
+
| `ogType` | string | Override `<meta property="og:type">` (default `article`). |
|
|
151
|
+
| `canonicalUrl` | string | Explicit `<link rel="canonical">` href. Default: build-time-computed from `siteUrl` + URL. |
|
|
152
|
+
|
|
153
|
+
## Agent surface
|
|
154
|
+
|
|
155
|
+
| Field | Type | Purpose |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| `llmActions` | boolean / object | When `false`, suppress the per-page LLM-action UI cluster (Copy as markdown, Open in Claude, etc.). When an object, override placement / providers. See `dogsbay:agent-readiness`. |
|
|
158
|
+
|
|
159
|
+
## Dates and ordering
|
|
160
|
+
|
|
161
|
+
| Field | Type | Purpose |
|
|
162
|
+
|---|---|---|
|
|
163
|
+
| `updated` | date | ISO date string for "last updated" displays. Date objects are coerced via `.toISOString()`. |
|
|
164
|
+
| `created` | date | ISO date string for "first published" displays. Same coercion. |
|
|
165
|
+
| `weight` | number | Sort hint for term/index pages (lower first). Non-numeric values are dropped. |
|
|
166
|
+
|
|
167
|
+
## Auto-rendering hints
|
|
168
|
+
|
|
169
|
+
| Field | Type | Default | Purpose |
|
|
170
|
+
|---|---|---|---|
|
|
171
|
+
| `autoH1` | boolean | depends | When `true`, the layout renders `<h1>{title}</h1>` at the top of `<main>` if the body doesn't start with an H1. Computed per-page by the lede-detection step. |
|
|
172
|
+
| `autoLede` | boolean | `false` | When `true`, render `<p>{description}</p>` below the auto-H1 (or above the meta strip when there's no H1). |
|
|
173
|
+
|
|
174
|
+
## Multi-source axis metadata (read-only, set by aggregator)
|
|
175
|
+
|
|
176
|
+
These get stamped by the multi-source aggregator when more than
|
|
177
|
+
one source / version / locale is in play. Setting them manually
|
|
178
|
+
is a mistake — the aggregator overwrites on every build.
|
|
179
|
+
|
|
180
|
+
| Field | Type | Purpose |
|
|
181
|
+
|---|---|---|
|
|
182
|
+
| `multiSource.namespace` | string | Set when ≥2 sources have distinct names. |
|
|
183
|
+
| `multiSource.version` | string | Set when version axis is active. |
|
|
184
|
+
| `multiSource.locale` | string | Set when locale axis is active. |
|
|
185
|
+
| `multiSource.originalSlug` | string | Slug as the importer produced it before any axis prefixing. Used by the version-switcher to compute cross-version equivalents. |
|
|
186
|
+
|
|
187
|
+
## Custom props bag
|
|
188
|
+
|
|
189
|
+
| Field | Type | Purpose |
|
|
190
|
+
|---|---|---|
|
|
191
|
+
| `props` | object | Arbitrary key/value bag passed to the layout's per-page props slot. Useful for plugin or pattern integrations that need page-specific config without inventing a new top-level field. |
|
|
192
|
+
|
|
193
|
+
# Tier 2: User-declared taxonomies
|
|
194
|
+
|
|
195
|
+
Any frontmatter key you name in `taxonomies:` config gets
|
|
196
|
+
lifted into `meta.taxonomies[name]` as a string array. Example:
|
|
197
|
+
declaring `taxonomies.difficulty` in `dogsbay.config.yml` makes
|
|
198
|
+
`difficulty: intermediate` available as a Pagefind facet, a
|
|
199
|
+
browse page at `/by-difficulty/intermediate/`, and (with
|
|
200
|
+
`prefixes:` config) a chip color.
|
|
201
|
+
|
|
202
|
+
The five Tier 1 classification fields (`status`, `type`,
|
|
203
|
+
`audience`, `category`, `tags`) are **also** valid in
|
|
204
|
+
`taxonomies:` config — declaring them there extends their
|
|
205
|
+
existing built-in behavior (chip strips, badges) with the
|
|
206
|
+
taxonomy surface (browse pages, facets).
|
|
207
|
+
|
|
208
|
+
Keys NOT in `taxonomies:` config are tier 3 (arbitrary).
|
|
209
|
+
|
|
210
|
+
See `dogsbay:taxonomy-config` for the full taxonomy surface,
|
|
211
|
+
including `prefixes` (chip colors), `labels` (display
|
|
212
|
+
overrides), `values` (closed enum + audit), and `hierarchical`
|
|
213
|
+
(slash-nested browsing).
|
|
214
|
+
|
|
215
|
+
# Tier 3: Arbitrary frontmatter
|
|
216
|
+
|
|
217
|
+
Anything not in tiers 1–2 is preserved on
|
|
218
|
+
`ExportPage.frontmatter` and forwarded to the rendered page,
|
|
219
|
+
but Dogsbay's importer + layout don't consume it. No semantic
|
|
220
|
+
effect — no chips, no facets, no audit rules, no SEO meta.
|
|
221
|
+
|
|
222
|
+
Use cases:
|
|
223
|
+
|
|
224
|
+
- Internal annotations the writing team uses (e.g. a `reviewers:`
|
|
225
|
+
list rendered nowhere but tracked for editorial workflow).
|
|
226
|
+
- Custom plugin inputs (a plugin can add an `auditRule` that
|
|
227
|
+
reads any frontmatter key — see `dogsbay:plugin-api`).
|
|
228
|
+
- Importer-specific carry-through: Starlight's
|
|
229
|
+
`pcx_content_type`, MkDocs' `template`, etc. are preserved
|
|
230
|
+
but not lifted into Dogsbay's typed slots.
|
|
231
|
+
|
|
232
|
+
Plugins promote arbitrary frontmatter to semantic via the
|
|
233
|
+
`auditRules` and `componentWrappers` hooks. If you find
|
|
234
|
+
yourself wanting an arbitrary field to "do something", that's
|
|
235
|
+
the path.
|
|
236
|
+
|
|
237
|
+
## Diátaxis (only if `@dogsbay/pattern-diataxis` is installed)
|
|
238
|
+
|
|
239
|
+
The Diátaxis pattern adds audit rules that match on `meta.type`
|
|
240
|
+
values:
|
|
241
|
+
|
|
242
|
+
| Value | Triggers |
|
|
243
|
+
|---|---|
|
|
244
|
+
| `tutorial` | `diataxis/tutorial-*` audit rules (verb-led headings, step structure, etc.) |
|
|
245
|
+
| `how-to` | `diataxis/how-to-*` rules |
|
|
246
|
+
| `reference` | `diataxis/reference-*` rules |
|
|
247
|
+
| `explanation` | `diataxis/explanation-*` rules |
|
|
248
|
+
|
|
249
|
+
Without the pattern installed, `meta.type` still works — it
|
|
250
|
+
renders a `<TypeBadge>` and powers `/by-type/` if you declare
|
|
251
|
+
the taxonomy. The pattern just adds opinionated audit rules.
|
|
252
|
+
|
|
253
|
+
# How importers + audit rules read frontmatter
|
|
254
|
+
|
|
255
|
+
- **format-dogsbay-md** parses via gray-matter; the typed
|
|
256
|
+
subset becomes `ExportPage.title`, `description`, `redirect`.
|
|
257
|
+
The full raw YAML lands in `ExportPage.frontmatter`.
|
|
258
|
+
- **format-mkdocs / format-obsidian / format-starlight** do
|
|
259
|
+
the same; importer-specific keys are preserved in
|
|
260
|
+
`frontmatter` but not lifted to typed fields.
|
|
261
|
+
- **format-astro** writes the typed fields into the generated
|
|
262
|
+
`.astro` page's frontmatter; the layout reads them as props.
|
|
263
|
+
- **dogsbay site check** rules can match on any frontmatter
|
|
264
|
+
key. `seo/description-missing` and `seo/description-length`
|
|
265
|
+
look at the `description` field directly.
|
|
266
|
+
|
|
267
|
+
# Cross-format `description` quirk
|
|
268
|
+
|
|
269
|
+
Three importers generate descriptions slightly differently:
|
|
270
|
+
|
|
271
|
+
- **dogsbay-md** uses whatever's in frontmatter. Empty if
|
|
272
|
+
missing.
|
|
273
|
+
- **MkDocs** falls back to the first paragraph if frontmatter
|
|
274
|
+
is empty (matching MkDocs Material convention).
|
|
275
|
+
- **Starlight** treats the typed subset as authoritative.
|
|
276
|
+
|
|
277
|
+
If the `seo/description-missing` audit fires unexpectedly,
|
|
278
|
+
check whether the importer is providing a default vs requiring
|
|
279
|
+
explicit declaration.
|
|
280
|
+
|
|
281
|
+
# Common mistakes
|
|
282
|
+
|
|
283
|
+
- ❌ Embedding YAML in the body (only the leading
|
|
284
|
+
`---`-delimited block is parsed; later `---` is rendered as
|
|
285
|
+
`<hr>`).
|
|
286
|
+
- ❌ Single-quoted multi-line strings without `>` or `|` block
|
|
287
|
+
scalars — multi-line strings need YAML's block syntax.
|
|
288
|
+
- ❌ Setting `multiSource.namespace` (or any `multiSource.*`)
|
|
289
|
+
manually — overwritten by the aggregator on every build.
|
|
290
|
+
- ❌ Using `draft: 'true'` (string) instead of `draft: true`
|
|
291
|
+
(boolean) — strings are truthy but the audit rules check for
|
|
292
|
+
the boolean.
|
|
293
|
+
- ❌ Adding `status: draft` (or `draft: true`) to a new page
|
|
294
|
+
by default. Branches handle draft state in a git workflow;
|
|
295
|
+
the frontmatter gate persists past merge and silently hides
|
|
296
|
+
the page in production. Only stamp draft when explicitly
|
|
297
|
+
asked.
|
|
298
|
+
- ❌ Treating `status`, `type`, `audience`, `category`, `tags`
|
|
299
|
+
as user-defined fields. They're built-in classification with
|
|
300
|
+
semantic effects, AND they're also the canonical taxonomies
|
|
301
|
+
to declare in `taxonomies:` config. Use the built-in name
|
|
302
|
+
rather than inventing a parallel field.
|
|
303
|
+
- ❌ Setting `status: beta` (or any value not in the closed
|
|
304
|
+
enum). The four values are `draft | preview | stable |
|
|
305
|
+
deprecated` — `parseMeta` silently drops anything else, so
|
|
306
|
+
the badge won't render and you'll waste time debugging.
|
|
307
|
+
- ❌ Custom `slug` that doesn't match the file path's parent
|
|
308
|
+
segments — the URL becomes inconsistent with the file
|
|
309
|
+
hierarchy. Stick with file-path-derived slugs unless there's
|
|
310
|
+
a specific reason.
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dogsbay:markdown-directives
|
|
3
|
+
description: Write Dogsbay markdown using the directive syntax for cards, steps, tabs, callouts, grids, details, and other components. Use when authoring or editing content/*.md pages.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Dogsbay markdown directives
|
|
7
|
+
|
|
8
|
+
Dogsbay markdown is a small superset of CommonMark with `:::name`
|
|
9
|
+
block directives for the components docs sites need most. The
|
|
10
|
+
directive syntax is parser-enforced — getting it wrong fails the
|
|
11
|
+
build or renders as literal text.
|
|
12
|
+
|
|
13
|
+
## Block directive shape
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
:::name{attr1="value" attr2="value"}
|
|
17
|
+
content
|
|
18
|
+
:::
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Use `::::` (four colons) when the content itself contains `:::`
|
|
22
|
+
(e.g., a directive nested inside another).
|
|
23
|
+
|
|
24
|
+
## Callouts
|
|
25
|
+
|
|
26
|
+
Two equivalent forms — pick whichever reads cleaner.
|
|
27
|
+
|
|
28
|
+
### GitHub-alert form (preferred for note/warning/tip/danger)
|
|
29
|
+
|
|
30
|
+
```markdown
|
|
31
|
+
> [!NOTE]
|
|
32
|
+
> Helpful supplemental information.
|
|
33
|
+
|
|
34
|
+
> [!WARNING]
|
|
35
|
+
> Don't do the thing.
|
|
36
|
+
|
|
37
|
+
> [!TIP]
|
|
38
|
+
> Confirmation that you're on the right track.
|
|
39
|
+
|
|
40
|
+
> [!DANGER]
|
|
41
|
+
> Destructive or irreversible.
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The token after `[!` is the type — `NOTE`, `TIP`, `WARNING`,
|
|
45
|
+
`DANGER`, `IMPORTANT`, `CAUTION`.
|
|
46
|
+
|
|
47
|
+
### Directive form (for custom titles or types outside the GitHub set)
|
|
48
|
+
|
|
49
|
+
```markdown
|
|
50
|
+
:::callout{type="success" title="Build complete"}
|
|
51
|
+
The site published in 4.2 seconds.
|
|
52
|
+
:::
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Without `title`, the directive form behaves identically to the
|
|
56
|
+
GitHub form for the type.
|
|
57
|
+
|
|
58
|
+
## Steps
|
|
59
|
+
|
|
60
|
+
Numbered steps for sequential procedures. Renders as `<Steps>` +
|
|
61
|
+
`<Step>` components with circle indicators.
|
|
62
|
+
|
|
63
|
+
```markdown
|
|
64
|
+
:::steps
|
|
65
|
+
1. **Install the CLI**
|
|
66
|
+
Run `npm install -g dogsbay`.
|
|
67
|
+
|
|
68
|
+
2. **Initialise**
|
|
69
|
+
Run `dogsbay site init my-docs`.
|
|
70
|
+
|
|
71
|
+
3. **Preview**
|
|
72
|
+
Run `dogsbay site dev` and open localhost:4321.
|
|
73
|
+
:::
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The numbered-list inside is plain markdown. Bold the step's
|
|
77
|
+
short verb, then a paragraph or code block of detail.
|
|
78
|
+
|
|
79
|
+
## Tabs
|
|
80
|
+
|
|
81
|
+
Side-by-side content using a definition-list inside `:::tabs`.
|
|
82
|
+
|
|
83
|
+
```markdown
|
|
84
|
+
:::tabs
|
|
85
|
+
TypeScript
|
|
86
|
+
: ```ts
|
|
87
|
+
const x = 1;
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Python
|
|
91
|
+
: ```py
|
|
92
|
+
x = 1
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Curl
|
|
96
|
+
: ```bash
|
|
97
|
+
curl https://example.com/api
|
|
98
|
+
```
|
|
99
|
+
:::
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The tab label is the term; the tab content is the definition
|
|
103
|
+
(`: …` with three spaces or a tab). Multi-line content is
|
|
104
|
+
allowed; indent further lines to align with the first.
|
|
105
|
+
|
|
106
|
+
## Cards
|
|
107
|
+
|
|
108
|
+
Bulleted list of bold-link entries inside `:::cards`. Renders as
|
|
109
|
+
a responsive grid.
|
|
110
|
+
|
|
111
|
+
```markdown
|
|
112
|
+
:::cards
|
|
113
|
+
- **[Getting started](./getting-started)** {icon="rocket"}
|
|
114
|
+
Three-minute orientation to authoring.
|
|
115
|
+
|
|
116
|
+
- **[API reference](./api/)** {icon="book-open"}
|
|
117
|
+
Endpoint browser, schemas, code samples.
|
|
118
|
+
|
|
119
|
+
- **[GitHub](https://github.com/your-org/repo)** {icon="github"}
|
|
120
|
+
Star, browse, file an issue.
|
|
121
|
+
:::
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Each item: `- **[Title](href)**` optionally followed by an
|
|
125
|
+
attribute block (`{icon="..."}`), then the description on the
|
|
126
|
+
next line, indented two spaces. Optional blank line between
|
|
127
|
+
items improves readability.
|
|
128
|
+
|
|
129
|
+
### Icons on cards
|
|
130
|
+
|
|
131
|
+
`icon` accepts any name from the platform Icon component
|
|
132
|
+
(see `dogsbay:theme-tokens` for the Icon component reference):
|
|
133
|
+
|
|
134
|
+
- **Bare names** default to Lucide:
|
|
135
|
+
`{icon="rocket"}`, `{icon="book-open"}`, `{icon="github"}`.
|
|
136
|
+
Browse the catalog at <https://lucide.dev/icons/>.
|
|
137
|
+
- **`pack:name`** routes to other Iconify packs:
|
|
138
|
+
`{icon="mdi:home"}` (Material Design Icons),
|
|
139
|
+
`{icon="simple-icons:github"}` (brand glyphs),
|
|
140
|
+
`{icon="lucide:book-open"}` (explicit Lucide).
|
|
141
|
+
- **Emoji shortcodes** map to Unicode characters when no
|
|
142
|
+
Iconify pack is given: `{icon="rocket"}` → 🚀,
|
|
143
|
+
`{icon="tada"}` → 🎉. The emoji map wins for bare names that
|
|
144
|
+
match it.
|
|
145
|
+
|
|
146
|
+
When the name doesn't resolve in any pack, the icon slot
|
|
147
|
+
renders nothing (silent fallback) — better than a broken-image
|
|
148
|
+
placeholder, since the title and description still convey the
|
|
149
|
+
card's intent.
|
|
150
|
+
|
|
151
|
+
## Single card (with attrs or YAML body)
|
|
152
|
+
|
|
153
|
+
For a standalone card with rich props, use the singular `:::card`
|
|
154
|
+
directive:
|
|
155
|
+
|
|
156
|
+
```markdown
|
|
157
|
+
:::card{title="Pro plan" href="/pricing/pro"}
|
|
158
|
+
For growing teams.
|
|
159
|
+
:::
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
When prop count exceeds 3 OR any value contains a newline, the
|
|
163
|
+
serializer switches to YAML body form:
|
|
164
|
+
|
|
165
|
+
```markdown
|
|
166
|
+
:::card
|
|
167
|
+
---
|
|
168
|
+
title: Pro plan
|
|
169
|
+
description: |
|
|
170
|
+
For growing teams.
|
|
171
|
+
Includes priority support.
|
|
172
|
+
href: /pricing/pro
|
|
173
|
+
icon: rocket
|
|
174
|
+
---
|
|
175
|
+
:::
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Both forms are accepted by the parser.
|
|
179
|
+
|
|
180
|
+
## Link card (`:::link-card`)
|
|
181
|
+
|
|
182
|
+
A focused variant of `:::card` for "go here next" navigation
|
|
183
|
+
affordances. Renders a chevron arrow on the right and a
|
|
184
|
+
distinctive hover state — visually clearer that it's a link
|
|
185
|
+
rather than a content tile.
|
|
186
|
+
|
|
187
|
+
```markdown
|
|
188
|
+
:::link-card{title="Configuration guide" href="/config/"}
|
|
189
|
+
Site name, theme, base path, and per-source settings live in
|
|
190
|
+
dogsbay.config.yml.
|
|
191
|
+
:::
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
YAML body form when prop count or content grows:
|
|
195
|
+
|
|
196
|
+
```markdown
|
|
197
|
+
:::link-card
|
|
198
|
+
---
|
|
199
|
+
title: Configuration guide
|
|
200
|
+
description: |
|
|
201
|
+
Site name, theme, base path, and per-source settings live in
|
|
202
|
+
dogsbay.config.yml.
|
|
203
|
+
href: /config/
|
|
204
|
+
---
|
|
205
|
+
:::
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Props: `title` (required), `href` (required), `description`
|
|
209
|
+
(optional — also accepted as the body paragraph for ergonomic
|
|
210
|
+
authoring). No `icon` slot — link-cards intentionally lean on
|
|
211
|
+
the chevron alone for the link affordance. When you need an
|
|
212
|
+
icon, use `:::card`.
|
|
213
|
+
|
|
214
|
+
### When to pick which card directive
|
|
215
|
+
|
|
216
|
+
- **`:::cards`** (plural) — list of related links, displayed as
|
|
217
|
+
a responsive grid. Best for "browse next" clusters at the
|
|
218
|
+
end of a page or on a landing page. Items are bulleted-link
|
|
219
|
+
shorthand.
|
|
220
|
+
- **`:::card`** (singular) — one rich card with full prop
|
|
221
|
+
surface (`icon`, `variant`, custom classes, arbitrary body).
|
|
222
|
+
Use when you want a tile with deliberate visual weight.
|
|
223
|
+
- **`:::link-card`** — one card scoped to a single navigation
|
|
224
|
+
link, with chevron arrow. Use for callouts that lead the
|
|
225
|
+
reader somewhere specific ("Continue with Configuration
|
|
226
|
+
guide →").
|
|
227
|
+
|
|
228
|
+
## Grid
|
|
229
|
+
|
|
230
|
+
Generic responsive grid container with `cols` and `gap` attrs:
|
|
231
|
+
|
|
232
|
+
```markdown
|
|
233
|
+
:::grid{cols="3" gap="4"}
|
|
234
|
+
|
|
235
|
+
Cell A
|
|
236
|
+
|
|
237
|
+
Cell B
|
|
238
|
+
|
|
239
|
+
Cell C
|
|
240
|
+
|
|
241
|
+
:::
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Each cell is plain markdown content (a paragraph, a callout, a
|
|
245
|
+
code block, etc.). Empty lines between cells separate them.
|
|
246
|
+
|
|
247
|
+
## Details (collapsible)
|
|
248
|
+
|
|
249
|
+
```markdown
|
|
250
|
+
:::details{title="Show advanced configuration"}
|
|
251
|
+
The expanded content goes here.
|
|
252
|
+
|
|
253
|
+
Multi-paragraph + code blocks + nested directives all work.
|
|
254
|
+
:::
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Renders as `<details><summary>Title</summary>...</details>`.
|
|
258
|
+
Closed by default; pass `open="true"` to start expanded.
|
|
259
|
+
|
|
260
|
+
## Code blocks
|
|
261
|
+
|
|
262
|
+
Triple-backtick fenced blocks with language identifiers. Always
|
|
263
|
+
specify the language for syntax highlighting:
|
|
264
|
+
|
|
265
|
+
````markdown
|
|
266
|
+
```bash
|
|
267
|
+
curl -X POST https://api.example.com/v1/pets
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
```yaml title="dogsbay.config.yml"
|
|
271
|
+
site:
|
|
272
|
+
name: Example
|
|
273
|
+
```
|
|
274
|
+
````
|
|
275
|
+
|
|
276
|
+
Supported attributes on the fence:
|
|
277
|
+
|
|
278
|
+
- `title="..."` — header bar above the code block
|
|
279
|
+
- `lineNumbers` — render line numbers
|
|
280
|
+
- `frame="terminal"` — terminal styling
|
|
281
|
+
|
|
282
|
+
## Inline directives
|
|
283
|
+
|
|
284
|
+
For inline-level marks, use `:name[text]{attrs}`:
|
|
285
|
+
|
|
286
|
+
```markdown
|
|
287
|
+
Press :kbd[Ctrl+C] to copy.
|
|
288
|
+
This is :badge[New]{tone="success"} content.
|
|
289
|
+
Click :icon[rocket] to launch, or :icon[mdi:home] to go home.
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
`:icon[name]` accepts the same shorthand as the `{icon=...}`
|
|
293
|
+
attribute on cards — bare names default to Lucide,
|
|
294
|
+
`pack:name` routes to other Iconify packs, emoji shortcodes
|
|
295
|
+
render as Unicode. See "Icons on cards" above.
|
|
296
|
+
|
|
297
|
+
## Frontmatter
|
|
298
|
+
|
|
299
|
+
Every page should start with YAML frontmatter delimited by `---`:
|
|
300
|
+
|
|
301
|
+
```markdown
|
|
302
|
+
---
|
|
303
|
+
title: Configuration
|
|
304
|
+
description: How to configure the site via dogsbay.config.yml.
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
# Configuration
|
|
308
|
+
|
|
309
|
+
…
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
See `dogsbay:frontmatter-fields` for the platform-recognised
|
|
313
|
+
fields.
|
|
314
|
+
|
|
315
|
+
## Common mistakes
|
|
316
|
+
|
|
317
|
+
- ❌ Using `<Cards>` JSX — Dogsbay markdown is NOT MDX. Use
|
|
318
|
+
`:::cards` directives instead.
|
|
319
|
+
- ❌ Forgetting the language identifier on code fences — most
|
|
320
|
+
themes won't highlight without it.
|
|
321
|
+
- ❌ Mixing tab definition-list `:` with regular list `-` markers
|
|
322
|
+
— they're different syntactic structures.
|
|
323
|
+
- ❌ Writing card descriptions on the same line as the title —
|
|
324
|
+
must be on the next line, indented two spaces.
|
|
325
|
+
- ❌ Using a non-existent icon name. The icon slot fails
|
|
326
|
+
silently when the name doesn't resolve, so a typo leaves the
|
|
327
|
+
card looking wrong without any error. Verify Lucide names
|
|
328
|
+
against <https://lucide.dev/icons/> or use the `pack:name`
|
|
329
|
+
form to be explicit.
|