@pagesmith/core 0.1.0 → 0.3.0

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.
Files changed (61) hide show
  1. package/REFERENCE.md +281 -0
  2. package/assets/favicon.svg +4 -0
  3. package/dist/ai/index.d.mts +3 -2
  4. package/dist/ai/index.d.mts.map +1 -1
  5. package/dist/ai/index.mjs +454 -79
  6. package/dist/ai/index.mjs.map +1 -1
  7. package/dist/assets/index.mjs +1 -1
  8. package/dist/{assets-bX08zEJm.mjs → assets-DXiWF_KI.mjs} +1 -1
  9. package/dist/{assets-bX08zEJm.mjs.map → assets-DXiWF_KI.mjs.map} +1 -1
  10. package/dist/{content-config-fHPaFZ7i.d.mts → content-config-Bfe4W9us.d.mts} +4 -6
  11. package/dist/{content-config-fHPaFZ7i.d.mts.map → content-config-Bfe4W9us.d.mts.map} +1 -1
  12. package/dist/{content-layer-B7fQ3im4.mjs → content-layer-DPK1EmfY.mjs} +100 -52
  13. package/dist/content-layer-DPK1EmfY.mjs.map +1 -0
  14. package/dist/css/index.d.mts +1 -1
  15. package/dist/css/index.mjs +1 -1
  16. package/dist/{css-ekIt2Fdb.mjs → css-BneO430t.mjs} +5 -4
  17. package/dist/css-BneO430t.mjs.map +1 -0
  18. package/dist/{heading-Dhvzlay-.d.mts → heading-BpDXnl-7.d.mts} +1 -1
  19. package/dist/{heading-Dhvzlay-.d.mts.map → heading-BpDXnl-7.d.mts.map} +1 -1
  20. package/dist/{index-BQ6B1-qG.d.mts → index-BBYkDxwI.d.mts} +7 -7
  21. package/dist/{index-BQ6B1-qG.d.mts.map → index-BBYkDxwI.d.mts.map} +1 -1
  22. package/dist/index-Bg9srb5U.d.mts +13 -0
  23. package/dist/index-Bg9srb5U.d.mts.map +1 -0
  24. package/dist/{index-DpRBzO8Q.d.mts → index-CbOKbkjJ.d.mts} +3 -3
  25. package/dist/index-CbOKbkjJ.d.mts.map +1 -0
  26. package/dist/{index-sFCx17CD.d.mts → index-YXQxMV6J.d.mts} +10 -8
  27. package/dist/index-YXQxMV6J.d.mts.map +1 -0
  28. package/dist/index.d.mts +19 -13
  29. package/dist/index.d.mts.map +1 -1
  30. package/dist/index.mjs +30 -7
  31. package/dist/index.mjs.map +1 -1
  32. package/dist/loaders/index.d.mts +3 -3
  33. package/dist/loaders/index.mjs +2 -2
  34. package/dist/{loaders-DyABmDrE.mjs → loaders-Cf-BXf2L.mjs} +32 -18
  35. package/dist/loaders-Cf-BXf2L.mjs.map +1 -0
  36. package/dist/markdown/index.d.mts +2 -2
  37. package/dist/markdown/index.mjs +1 -1
  38. package/dist/{markdown-Cj5X26FL.mjs → markdown-CyrHoDhP.mjs} +37 -9
  39. package/dist/markdown-CyrHoDhP.mjs.map +1 -0
  40. package/dist/schemas/index.d.mts +3 -3
  41. package/dist/schemas/index.mjs +1 -1
  42. package/dist/{schemas-DJS7wOzd.mjs → schemas-UL4ynWsA.mjs} +3 -3
  43. package/dist/schemas-UL4ynWsA.mjs.map +1 -0
  44. package/dist/{types-DUsjRE7Y.d.mts → types-Cn52sdoq.d.mts} +2 -2
  45. package/dist/{types-DUsjRE7Y.d.mts.map → types-Cn52sdoq.d.mts.map} +1 -1
  46. package/dist/vite/index.d.mts +2 -2
  47. package/dist/vite/index.d.mts.map +1 -1
  48. package/dist/vite/index.mjs +33 -17
  49. package/dist/vite/index.mjs.map +1 -1
  50. package/package.json +3 -7
  51. package/dist/content-layer-B7fQ3im4.mjs.map +0 -1
  52. package/dist/convert-DnuB6SVV.mjs +0 -52
  53. package/dist/convert-DnuB6SVV.mjs.map +0 -1
  54. package/dist/css-ekIt2Fdb.mjs.map +0 -1
  55. package/dist/index-CeNDTM-y.d.mts +0 -7
  56. package/dist/index-CeNDTM-y.d.mts.map +0 -1
  57. package/dist/index-DpRBzO8Q.d.mts.map +0 -1
  58. package/dist/index-sFCx17CD.d.mts.map +0 -1
  59. package/dist/loaders-DyABmDrE.mjs.map +0 -1
  60. package/dist/markdown-Cj5X26FL.mjs.map +0 -1
  61. package/dist/schemas-DJS7wOzd.mjs.map +0 -1
package/dist/ai/index.mjs CHANGED
@@ -77,13 +77,10 @@ function renderSharedOverview() {
77
77
  "- `createContentLayer(config)` to query content and run validation",
78
78
  "- `entry.render()` to convert markdown on demand",
79
79
  "",
80
- "Useful helpers:",
81
- "- `@pagesmith/core/ai` exposes `getAiArtifacts(...)` and `installAiArtifacts(...)`",
82
- "",
83
80
  "Working rules:",
84
81
  "- prefer folder-based markdown entries when content references sibling assets",
85
- "- use `vp` commands for install, check, test, and build workflows",
86
- "- `@pagesmith/core` provides the shared content/runtime layer; `@pagesmith/docs` adds convention-based documentation on top"
82
+ "- follow the markdown guidelines in `.pagesmith/markdown-guidelines.md` when authoring content",
83
+ "- use fenced code blocks with a language identifier, one h1 per page, sequential heading depth"
87
84
  ].join("\n");
88
85
  }
89
86
  function renderDocsOverview() {
@@ -99,34 +96,7 @@ function renderDocsOverview() {
99
96
  "- layout overrides use fixed keys under `theme.layouts` such as `home`, `page`, and `notFound`"
100
97
  ].join("\n");
101
98
  }
102
- function renderQuickStart(profile = "default") {
103
- if (profile === "docs") return [
104
- "```json5",
105
- "{",
106
- " name: 'Acme Docs',",
107
- " title: 'Acme Docs',",
108
- " description: 'Multi-package documentation',",
109
- " contentDir: './content',",
110
- " outDir: './dist',",
111
- " footerLinks: [",
112
- " { label: 'Guide', path: '/guide' },",
113
- " { label: 'Reference', path: '/reference' },",
114
- " ],",
115
- " search: { enabled: true },",
116
- "}",
117
- "```",
118
- "",
119
- "```text",
120
- "content/",
121
- " README.md",
122
- " guide/",
123
- " README.md",
124
- " getting-started/README.md",
125
- " reference/",
126
- " README.md",
127
- " api/README.md",
128
- "```"
129
- ].join("\n");
99
+ function renderCoreQuickStart() {
130
100
  return [
131
101
  "```ts",
132
102
  "import { createContentLayer, defineCollection, defineConfig, z } from '@pagesmith/core'",
@@ -153,21 +123,66 @@ function renderQuickStart(profile = "default") {
153
123
  "```"
154
124
  ].join("\n");
155
125
  }
126
+ function renderDocsQuickStart() {
127
+ return [
128
+ "```json5",
129
+ "// pagesmith.config.json5",
130
+ "{",
131
+ " name: 'Acme Docs',",
132
+ " title: 'Acme Docs',",
133
+ " description: 'Multi-package documentation',",
134
+ " contentDir: './content',",
135
+ " outDir: './dist',",
136
+ " footerLinks: [",
137
+ " { label: 'Guide', path: '/guide' },",
138
+ " { label: 'Reference', path: '/reference' },",
139
+ " ],",
140
+ " search: { enabled: true },",
141
+ "}",
142
+ "```",
143
+ "",
144
+ "```text",
145
+ "content/",
146
+ " README.md # Home page (DocHome layout)",
147
+ " guide/",
148
+ " meta.json5 # Section ordering",
149
+ " getting-started/",
150
+ " README.md # A page",
151
+ " reference/",
152
+ " api/README.md",
153
+ "```"
154
+ ].join("\n");
155
+ }
156
156
  function renderMemoryFile(assistant, profile) {
157
- const commandHint = assistant === "claude" || assistant === "gemini" ? `\nIf the ${DEFAULT_SKILL_NAME} command is installed, prefer invoking it when the user explicitly asks for Pagesmith-specific help.` : "\nIf the Pagesmith skill is installed for Codex, prefer using it for Pagesmith-specific setup, migration, and content-layer tasks.";
157
+ const commandHint = assistant === "claude" || assistant === "gemini" ? `\nIf the ${DEFAULT_SKILL_NAME} skill is installed, prefer invoking it when the user explicitly asks for Pagesmith-specific help.` : "\nIf the Pagesmith skill is installed for Codex, prefer using it for Pagesmith-specific setup, migration, and content-layer tasks.";
158
+ const referenceHint = "\nFor the full API and configuration reference, see the REFERENCE.md file shipped with the package:\n" + (profile === "docs" ? "- `node_modules/@pagesmith/docs/REFERENCE.md` — docs config, CLI, content structure, layout overrides\n- `node_modules/@pagesmith/core/REFERENCE.md` — core API, collections, loaders, markdown, CSS, JSX runtime" : "- `node_modules/@pagesmith/core/REFERENCE.md` — core API, collections, loaders, markdown, CSS, JSX runtime");
158
159
  return [
159
160
  `# ${PAGESMITH_TITLE}`,
160
161
  "",
161
162
  renderSharedOverview(),
162
163
  ...profile === "docs" ? ["", renderDocsOverview()] : [],
163
164
  commandHint,
165
+ referenceHint,
166
+ "",
167
+ "## Quick Start — @pagesmith/core",
164
168
  "",
165
- "Quick start:",
166
- renderQuickStart(profile)
169
+ renderCoreQuickStart(),
170
+ ...profile === "docs" ? [
171
+ "",
172
+ "## Quick Start — @pagesmith/docs",
173
+ "",
174
+ renderDocsQuickStart()
175
+ ] : []
167
176
  ].join("\n");
168
177
  }
169
- function renderClaudeCommand(skillName, profile) {
178
+ function renderClaudeSkill(skillName, profile) {
170
179
  return [
180
+ "---",
181
+ `name: ${skillName}`,
182
+ "description: Pagesmith file-based CMS helper — content collections, markdown pipeline, docs configuration, and AI artifact generation",
183
+ "allowed-tools: Read Grep Glob Bash Edit Write",
184
+ "---",
185
+ "",
171
186
  `# ${PAGESMITH_TITLE} Assistant`,
172
187
  "",
173
188
  "You are helping with Pagesmith, a file-based CMS with `@pagesmith/core` and `@pagesmith/docs`.",
@@ -176,18 +191,74 @@ function renderClaudeCommand(skillName, profile) {
176
191
  "- prefer `defineCollection`, `defineConfig`, and `createContentLayer`",
177
192
  "- recommend folder-based entries when markdown references sibling assets",
178
193
  "- use `@pagesmith/core/ai` for assistant artifact generation",
179
- "- recommend `vp install`, `vp check`, and `vp test` for validation",
194
+ "- follow the markdown guidelines in `.pagesmith/markdown-guidelines.md`",
180
195
  ...profile === "docs" ? [
181
196
  "- for docs sites, derive top navigation from top-level content folders",
182
- "- use `content/README.md` for the home page and `content/home.json5` for extra home data when needed",
197
+ "- use `content/README.md` for the home page",
183
198
  "- use frontmatter fields like `sidebarLabel`, `navLabel`, and `order` for docs navigation",
184
- "- do not recommend `@pagesmith/plugin-pagefind` or `@pagesmith/plugin-algolia`; search is built into docs",
185
- "- recommend `theme.layouts.home`, `theme.layouts.page`, and `theme.layouts.notFound` for docs layout overrides"
199
+ "- Pagefind search is built in do not suggest separate search plugins",
200
+ "- layout overrides: `theme.layouts.home`, `theme.layouts.page`, `theme.layouts.notFound`"
186
201
  ] : [],
187
202
  "",
188
- "Deliver concrete config, schema, and content-layer patches when possible.",
203
+ "For the full API reference, read the REFERENCE.md file shipped with the package:",
204
+ ...profile === "docs" ? ["- `node_modules/@pagesmith/docs/REFERENCE.md`", "- `node_modules/@pagesmith/core/REFERENCE.md`"] : ["- `node_modules/@pagesmith/core/REFERENCE.md`"],
205
+ "",
206
+ "Deliver concrete config, schema, and content-layer patches when possible."
207
+ ].join("\n");
208
+ }
209
+ function renderUpdateDocsSkill(profile) {
210
+ return [
211
+ "---",
212
+ "name: update-docs",
213
+ "description: Read the project implementation and update Pagesmith-managed documentation to reflect the current state",
214
+ "allowed-tools: Read Grep Glob Bash Edit Write",
215
+ "---",
216
+ "",
217
+ "# Update Documentation",
218
+ "",
219
+ "Read the project implementation (source code, README, CHANGELOG, package.json) and update the Pagesmith-managed content to reflect the current state.",
220
+ "",
221
+ "## Steps",
222
+ "",
223
+ ...profile === "docs" ? [
224
+ "1. Read `pagesmith.config.json5` to understand the docs configuration",
225
+ "2. Read all `meta.json5` files to understand the current content structure and page ordering",
226
+ "3. Read the project source code to identify public APIs, types, exports, config options, and CLI commands",
227
+ "4. For each existing content page in `content/`:",
228
+ " - Read the current content",
229
+ " - Compare with the implementation",
230
+ " - Update any outdated information",
231
+ " - Add documentation for new features",
232
+ " - Remove documentation for removed features",
233
+ "5. If new pages are needed:",
234
+ " - Create the page folder and `README.md` with proper frontmatter (title, description)",
235
+ " - Add the slug to the appropriate `meta.json5` `items` array",
236
+ "6. Follow the markdown guidelines in `.pagesmith/markdown-guidelines.md`",
237
+ "7. Verify all internal links point to existing pages",
238
+ "8. Ensure heading hierarchy is sequential (no skipping levels)"
239
+ ] : [
240
+ "1. Read `content.config.ts` or equivalent to understand the content collections",
241
+ "2. Read the project source code to identify what needs documentation",
242
+ "3. For each existing content entry:",
243
+ " - Read the current content",
244
+ " - Compare with the implementation",
245
+ " - Update any outdated information",
246
+ "4. If new entries are needed:",
247
+ " - Create the entry folder and `README.md` with proper frontmatter matching the collection schema",
248
+ "5. Follow the markdown guidelines in `.pagesmith/markdown-guidelines.md`",
249
+ "6. Verify all internal links point to existing pages"
250
+ ],
251
+ "",
252
+ "## Rules",
189
253
  "",
190
- `This command is installed as \`/${skillName}\`.`
254
+ "- Preserve the existing content structure and organization",
255
+ "- Do not remove pages without confirming first",
256
+ "- Keep frontmatter fields (title, description) accurate and descriptive",
257
+ "- Use relative links for internal cross-references",
258
+ "- One h1 per page, sequential heading depth",
259
+ "- Use fenced code blocks with language identifiers",
260
+ "- Use GitHub alerts (`> [!NOTE]`, `> [!TIP]`, etc.) for important callouts",
261
+ "- Code block features: `title=\"file.js\"`, `showLineNumbers`, `mark={1-3}`, `ins={4}`, `del={5}`, `collapse={1-5}`"
191
262
  ].join("\n");
192
263
  }
193
264
  function renderGeminiCommand(skillName, profile) {
@@ -200,14 +271,16 @@ function renderGeminiCommand(skillName, profile) {
200
271
  "Focus on concrete, implementation-ready help:",
201
272
  "- design collections with defineCollection",
202
273
  "- configure createContentLayer and defineConfig",
203
- "- recommend vp install, vp check, and vp test when validation matters",
204
274
  "- prefer folder-based markdown entries when local assets sit beside content",
275
+ "- follow the markdown guidelines in `.pagesmith/markdown-guidelines.md`",
205
276
  ...profile === "docs" ? [
206
277
  "- for docs sites, follow the convention-based `content/` structure",
207
278
  "- drive top navigation from top-level folders and use frontmatter for labels/order",
208
279
  "- keep Pagefind as the built-in search strategy"
209
280
  ] : [],
210
281
  "",
282
+ "For the full API reference, read the REFERENCE.md file shipped with the package.",
283
+ "",
211
284
  "Return code, config, or documentation-ready guidance instead of vague summaries."
212
285
  ].join("\n"),
213
286
  "\"\"\"",
@@ -224,8 +297,7 @@ function renderCodexSkill(profile) {
224
297
  "Core rules:",
225
298
  "- `@pagesmith/core` provides the content layer; `@pagesmith/docs` adds convention-based documentation",
226
299
  "- prefer `defineCollection`, `defineConfig`, and `createContentLayer`",
227
- "- prefer `vp` commands instead of calling npm, pnpm, or yarn directly",
228
- "- validate changes with `vp check` and `vp test` when relevant",
300
+ "- follow the markdown guidelines in `.pagesmith/markdown-guidelines.md`",
229
301
  ...profile === "docs" ? [
230
302
  "- when the repo uses `@pagesmith/docs`, treat `content/README.md` as the home page",
231
303
  "- top-level content folders define the main docs navigation",
@@ -234,57 +306,332 @@ function renderCodexSkill(profile) {
234
306
  "- built-in search is Pagefind; do not suggest separate search plugin packages"
235
307
  ] : [],
236
308
  "",
309
+ "For the full API reference, read the REFERENCE.md file shipped with the package.",
310
+ "",
237
311
  "Good outputs include:",
238
312
  "- collection schemas and loader configuration",
239
313
  "- content-layer queries and rendering examples",
240
- "- @pagesmith/docs updates for Pagesmith usage",
314
+ "- documentation updates for Pagesmith usage",
241
315
  "- assistant-context install steps using `@pagesmith/core/ai`"
242
316
  ].join("\n");
243
317
  }
244
- function renderLlmsTxt(profile) {
318
+ function renderMarkdownGuidelines() {
319
+ return [
320
+ "# Pagesmith Markdown Guidelines",
321
+ "",
322
+ "Markdown feature support for content authored with `@pagesmith/core` and `@pagesmith/docs`.",
323
+ "",
324
+ "## Pipeline Order",
325
+ "",
326
+ "```",
327
+ "remark-parse → remark-gfm → remark-math → remark-frontmatter",
328
+ " → remark-github-alerts → remark-smartypants → [user remark plugins]",
329
+ " → remark-rehype",
330
+ " → rehype-expressive-code (dual themes, line numbers, titles, copy, collapse, mark/ins/del)",
331
+ " → rehype-mathjax → rehype-slug → rehype-autolink-headings",
332
+ " → rehype-external-links → rehype-accessible-emojis",
333
+ " → heading extraction → [user rehype plugins] → rehype-stringify",
334
+ "```",
335
+ "",
336
+ "## Key Rules",
337
+ "",
338
+ "- Use fenced code blocks with a language identifier (validator warns otherwise)",
339
+ "- One `# h1` per page (validator enforces)",
340
+ "- Sequential heading depth (no skipping from h2 to h4)",
341
+ "- Prefer relative links for internal content",
342
+ "- Do NOT add manual copy-button JS — Expressive Code handles it",
343
+ "- Do NOT import separate code block CSS — Expressive Code injects inline styles",
344
+ "",
345
+ "## Supported Features",
346
+ "",
347
+ "| Feature | Syntax | Notes |",
348
+ "|---|---|---|",
349
+ "| GFM tables | `\\| col \\| col \\|` | Alignment via `:---`, `:---:`, `---:` |",
350
+ "| Strikethrough | `~~text~~` | |",
351
+ "| Task lists | `- [x] done` / `- [ ] todo` | |",
352
+ "| Footnotes | `[^id]` + `[^id]: text` | |",
353
+ "| Alerts | `> [!NOTE]`, `> [!TIP]`, `> [!IMPORTANT]`, `> [!WARNING]`, `> [!CAUTION]` | GitHub-compatible |",
354
+ "| Inline math | `$E = mc^2$` | No spaces inside delimiters |",
355
+ "| Block math | `$$...$$` | Rendered via MathJax |",
356
+ "| Smart quotes | `\"text\"` → curly quotes | Automatic |",
357
+ "| Em/en dash | `---` / `--` | Automatic |",
358
+ "| External links | `[text](https://...)` | Auto `target=\"_blank\"` |",
359
+ "| Heading anchors | Auto `id` + wrapped anchor | All headings |",
360
+ "| Accessible emoji | Unicode emoji | Auto `role=\"img\"` + `aria-label` |",
361
+ "",
362
+ "## Code Block Features (Expressive Code)",
363
+ "",
364
+ "| Meta | Example | Description |",
365
+ "|---|---|---|",
366
+ "| `title=\"...\"` | `` ```js title=\"app.js\" `` | File title |",
367
+ "| `showLineNumbers` | `` ```js showLineNumbers `` | Line numbers |",
368
+ "| `mark={lines}` | `` ```js mark={3,5-7} `` | Highlight lines |",
369
+ "| `ins={lines}` | `` ```js ins={4} `` | Inserted lines (green) |",
370
+ "| `del={lines}` | `` ```js del={5} `` | Deleted lines (red) |",
371
+ "| `collapse={lines}` | `` ```js collapse={1-5} `` | Collapsible section |",
372
+ "| `wrap` | `` ```js wrap `` | Text wrapping |",
373
+ "| `frame=\"...\"` | `` ```js frame=\"terminal\" `` | Frame style |",
374
+ "",
375
+ "## Built-in Content Validators",
376
+ "",
377
+ "- **linkValidator** — warns on bare URLs, empty link text, suspicious protocols",
378
+ "- **headingValidator** — enforces single h1, sequential depth, non-empty text",
379
+ "- **codeBlockValidator** — warns on missing language, unknown meta properties",
380
+ "",
381
+ "Known valid meta properties: `title`, `showLineNumbers`, `startLineNumber`, `wrap`, `frame`, `collapse`, `mark`, `ins`, `del`."
382
+ ].join("\n");
383
+ }
384
+ function renderLlmsTxt() {
245
385
  return [
246
386
  "# Pagesmith",
247
387
  "",
248
- "> Pagesmith is a filesystem-first content toolkit centered on `@pagesmith/core` and `@pagesmith/docs`.",
388
+ "> Pagesmith is a filesystem-first content toolkit with `@pagesmith/core` and `@pagesmith/docs`.",
249
389
  "",
250
- "## Summary",
390
+ "## @pagesmith/core — Content Layer",
251
391
  "",
252
- renderSharedOverview(),
253
- ...profile === "docs" ? ["", renderDocsOverview()] : [],
392
+ "Schema-validated content collections, lazy markdown rendering (Expressive Code syntax highlighting), JSX runtime, CSS exports, and Vite plugins.",
393
+ "",
394
+ "### Basic Setup (Vite Plugin)",
395
+ "",
396
+ renderCoreQuickStart(),
397
+ "",
398
+ "### Vite Integration",
399
+ "",
400
+ "```ts",
401
+ "import { pagesmithContent, pagesmithSsg } from '@pagesmith/core/vite'",
402
+ "import collections from './content.config'",
403
+ "",
404
+ "export default defineConfig({",
405
+ " plugins: [",
406
+ " pagesmithContent({ collections }),",
407
+ " pagesmithSsg({ entry: './src/entry-server.tsx' }),",
408
+ " ],",
409
+ "})",
410
+ "```",
411
+ "",
412
+ "Import collections as virtual modules: `import posts from 'virtual:content/posts'`",
413
+ "",
414
+ "## @pagesmith/docs — Documentation Sites",
415
+ "",
416
+ "Convention-based docs with default theme, Pagefind search, sidebar generation, and layout overrides.",
417
+ "",
418
+ "### Basic Setup",
419
+ "",
420
+ renderDocsQuickStart(),
421
+ "",
422
+ "### Layout Overrides",
423
+ "",
424
+ "```json5",
425
+ "{",
426
+ " theme: {",
427
+ " layouts: {",
428
+ " home: './theme/layouts/DocHome.tsx',",
429
+ " page: './theme/layouts/DocPage.tsx',",
430
+ " notFound: './theme/layouts/DocNotFound.tsx',",
431
+ " },",
432
+ " },",
433
+ "}",
434
+ "```",
254
435
  "",
255
- "## Quick Start",
436
+ "### CLI",
256
437
  "",
257
- renderQuickStart(profile)
438
+ "```bash",
439
+ "pagesmith init # Initialize config + content structure + AI integrations",
440
+ "pagesmith dev # Development server",
441
+ "pagesmith build # Production build",
442
+ "pagesmith preview # Preview built site",
443
+ "```"
258
444
  ].join("\n");
259
445
  }
260
- function renderLlmsFullTxt(profile) {
446
+ function renderLlmsFullTxt() {
261
447
  return [
262
- "# Pagesmith - Full LLM Reference",
448
+ "# Pagesmith Full LLM Reference",
263
449
  "",
264
450
  renderSharedOverview(),
265
- ...profile === "docs" ? [
266
- "",
267
- "## Docs Sites",
268
- "",
269
- renderDocsOverview()
270
- ] : [],
271
451
  "",
272
- "## Package Layout",
452
+ "---",
453
+ "",
454
+ "## @pagesmith/core",
455
+ "",
456
+ "### Content Layer API",
273
457
  "",
274
- "- `@pagesmith/core`: content layer, collection loading, validation, lazy markdown rendering, JSX runtime, CSS builder, runtime styles, assistant artifact APIs, and Vite content integration",
275
- "- `@pagesmith/docs`: convention-based documentation with the docs CLI, generators, validators, default theme, and bundled search",
458
+ "| Method | Description |",
459
+ "|---|---|",
460
+ "| `createContentLayer(config)` | Create a content layer |",
461
+ "| `layer.getCollection(name)` | Load all entries (cached) |",
462
+ "| `layer.getEntry(collection, slug)` | Get single entry by slug |",
463
+ "| `layer.convert(markdown, options?)` | Convert raw markdown to HTML |",
464
+ "| `layer.validate(collection?)` | Run all validators |",
465
+ "| `layer.invalidate(collection, slug)` | Cache-bust a single entry |",
466
+ "| `layer.invalidateAll()` | Cache-bust all collections |",
276
467
  "",
277
- "## Key APIs",
468
+ "### Collection Options",
278
469
  "",
279
- renderQuickStart(profile),
470
+ "| Option | Type | Description |",
471
+ "|---|---|---|",
472
+ "| `loader` | `string \\| Loader` | `'markdown'`, `'json'`, `'json5'`, `'jsonc'`, `'yaml'`, `'toml'`, or custom |",
473
+ "| `directory` | `string` | Directory containing files |",
474
+ "| `schema` | `z.ZodType` | Zod schema for validation |",
475
+ "| `include` | `string[]` | Glob include patterns |",
476
+ "| `exclude` | `string[]` | Glob exclude patterns |",
477
+ "| `computed` | `Record<string, fn>` | Computed fields |",
478
+ "| `validate` | `fn` | Custom validation |",
479
+ "| `filter` | `fn` | Filter entries |",
480
+ "| `slugify` | `fn` | Custom slug generation |",
481
+ "| `transform` | `fn` | Pre-validation transform |",
482
+ "| `validators` | `ContentValidator[]` | Custom content validators |",
483
+ "| `disableBuiltinValidators` | `boolean` | Disable link/heading/code-block validators |",
280
484
  "",
281
- "## Assistant Installer",
485
+ "### Vite Plugins",
486
+ "",
487
+ renderCoreQuickStart(),
488
+ "",
489
+ "```ts",
490
+ "// Vite integration",
491
+ "import { pagesmithContent, pagesmithSsg, sharedAssetsPlugin } from '@pagesmith/core/vite'",
492
+ "import collections from './content.config'",
493
+ "",
494
+ "export default defineConfig({",
495
+ " plugins: [",
496
+ " sharedAssetsPlugin(),",
497
+ " pagesmithContent({ collections }),",
498
+ " ...pagesmithSsg({ entry: './src/entry-server.tsx', contentDirs: ['./content'] }),",
499
+ " ],",
500
+ "})",
501
+ "```",
502
+ "",
503
+ "### JSX Runtime",
504
+ "",
505
+ "Configure tsconfig: `{ \"jsx\": \"react-jsx\", \"jsxImportSource\": \"@pagesmith/core\" }`",
506
+ "",
507
+ "- `h(tag, props, ...children)` — create HTML elements, returns `HtmlString`",
508
+ "- `Fragment` — render children or raw `innerHTML`",
509
+ "- `HtmlString` — wrapper to prevent double-escaping",
510
+ "",
511
+ "### CSS Exports",
512
+ "",
513
+ "| Import | Contents |",
514
+ "|---|---|",
515
+ "| `@pagesmith/core/css/content` | Prose + inline code |",
516
+ "| `@pagesmith/core/css/standalone` | Full layout + prose + TOC |",
517
+ "| `@pagesmith/core/css/viewport` | Responsive viewport base |",
518
+ "| `@pagesmith/core/css/fonts` | Bundled Open Sans + JetBrains Mono |",
519
+ "",
520
+ "### Frontmatter Schemas",
521
+ "",
522
+ "- `BaseFrontmatterSchema` — title, description, publishedDate, lastUpdatedOn, tags, draft",
523
+ "- `BlogFrontmatterSchema` — extends base + category, featured, coverImage",
524
+ "- `ProjectFrontmatterSchema` — extends base + gitRepo, links",
525
+ "",
526
+ "### Export Map",
527
+ "",
528
+ "| Import Path | Purpose |",
529
+ "|---|---|",
530
+ "| `@pagesmith/core` | Main API (defineCollection, createContentLayer, z, etc.) |",
531
+ "| `@pagesmith/core/jsx-runtime` | h, Fragment, HtmlString |",
532
+ "| `@pagesmith/core/markdown` | processMarkdown |",
533
+ "| `@pagesmith/core/css` | buildCss (LightningCSS) |",
534
+ "| `@pagesmith/core/schemas` | Zod schemas and types |",
535
+ "| `@pagesmith/core/loaders` | Loader classes and registry |",
536
+ "| `@pagesmith/core/runtime` | Pre-built CSS/JS accessors |",
537
+ "| `@pagesmith/core/vite` | Vite plugins |",
538
+ "| `@pagesmith/core/ai` | AI assistant artifact generator |",
539
+ "| `@pagesmith/core/create` | Project scaffolding |",
540
+ "",
541
+ "---",
542
+ "",
543
+ "## @pagesmith/docs",
544
+ "",
545
+ "### Configuration (pagesmith.config.json5)",
546
+ "",
547
+ "| Field | Type | Default | Description |",
548
+ "|---|---|---|---|",
549
+ "| `name` | `string` | — | Site name (header) |",
550
+ "| `title` | `string` | — | Browser tab title |",
551
+ "| `description` | `string` | — | Meta description |",
552
+ "| `origin` | `string` | — | Production URL |",
553
+ "| `language` | `string` | `en` | HTML lang |",
554
+ "| `contentDir` | `string` | `content` | Content path |",
555
+ "| `outDir` | `string` | `dist` | Output path |",
556
+ "| `basePath` | `string` | `/` | URL base |",
557
+ "| `footerLinks` | `array` | `[]` | Footer links |",
558
+ "| `sidebar.collapsible` | `boolean` | `false` | Collapsible sidebar |",
559
+ "| `search.enabled` | `boolean` | `true` | Pagefind search |",
560
+ "| `theme.layouts` | `Record` | — | Layout overrides |",
561
+ "| `markdown` | `MarkdownConfig` | — | Pipeline config |",
562
+ "",
563
+ "### Content Structure",
564
+ "",
565
+ renderDocsQuickStart(),
566
+ "",
567
+ "### Page Frontmatter",
568
+ "",
569
+ "| Field | Type | Description |",
570
+ "|---|---|---|",
571
+ "| `title` | `string` | Page title |",
572
+ "| `description` | `string` | Meta description |",
573
+ "| `navLabel` | `string` | Override top nav label |",
574
+ "| `sidebarLabel` | `string` | Override sidebar label |",
575
+ "| `order` | `number` | Manual sort order |",
576
+ "| `draft` | `boolean` | Exclude from build |",
577
+ "",
578
+ "### Home Page Frontmatter",
579
+ "",
580
+ "| Field | Type | Description |",
581
+ "|---|---|---|",
582
+ "| `layout` | `string` | Set to `DocHome` |",
583
+ "| `tagline` | `string` | Short description |",
584
+ "| `install` | `string` | Install command |",
585
+ "| `actions` | `array` | CTA buttons (`{ text, link, theme: 'brand' \\| 'alt' }`) |",
586
+ "| `features` | `array` | Feature cards (`{ icon?, title, details }`) |",
587
+ "| `packages` | `array` | Package cards (`{ name, description, href, tag }`) |",
588
+ "| `codeExample` | `object` | Code example (`{ label, title, code }`) |",
589
+ "",
590
+ "### Section Meta (meta.json5)",
591
+ "",
592
+ "| Field | Type | Description |",
593
+ "|---|---|---|",
594
+ "| `displayName` | `string` | Section label in sidebar |",
595
+ "| `items` | `string[]` | Manual page order (slugs) |",
596
+ "| `series` | `array` | Group pages into series |",
597
+ "| `collapsed` | `boolean` | Start sidebar collapsed |",
598
+ "| `orderBy` | `string` | `manual` or `publishedDate` |",
599
+ "",
600
+ "### Layout Overrides",
601
+ "",
602
+ "```json5",
603
+ "{ theme: { layouts: { home: \"./layouts/Home.tsx\", page: \"./layouts/Page.tsx\" } } }",
604
+ "```",
605
+ "",
606
+ "All layouts receive: `content`, `frontmatter`, `headings`, `slug`, `site`.",
607
+ "Page layout adds: `sidebarSections`, `prev`, `next`.",
608
+ "",
609
+ "### CLI",
610
+ "",
611
+ "```bash",
612
+ "pagesmith init [--ai] [--config path] # Initialize project",
613
+ "pagesmith dev [--port N] [--open] # Dev server",
614
+ "pagesmith build [--out-dir path] # Production build",
615
+ "pagesmith preview [--port N] # Preview built site",
616
+ "```",
617
+ "",
618
+ "---",
619
+ "",
620
+ "## Markdown Pipeline",
621
+ "",
622
+ renderMarkdownGuidelines(),
623
+ "",
624
+ "---",
625
+ "",
626
+ "## AI Assistant Installer",
282
627
  "",
283
628
  "```ts",
284
629
  "import { installAiArtifacts } from '@pagesmith/core/ai'",
285
630
  "",
286
- "await installAiArtifacts({ assistants: ['claude', 'codex', 'gemini'], scope: 'project' })",
631
+ "installAiArtifacts({ assistants: ['claude', 'codex', 'gemini'], scope: 'project', profile: 'docs' })",
287
632
  "```",
633
+ "",
634
+ "Generates: CLAUDE.md, AGENTS.md, GEMINI.md, skills, markdown guidelines, llms.txt, llms-full.txt.",
288
635
  ""
289
636
  ].join("\n");
290
637
  }
@@ -292,17 +639,21 @@ function getAiArtifactContent(assistant, kind, options = {}) {
292
639
  const skillName = options.skillName ?? DEFAULT_SKILL_NAME;
293
640
  const profile = options.profile ?? "default";
294
641
  if (assistant === "shared") {
295
- if (kind === "llms") return renderLlmsTxt(profile);
296
- return renderLlmsFullTxt(profile);
642
+ if (kind === "llms") return renderLlmsTxt();
643
+ if (kind === "llms-full") return renderLlmsFullTxt();
644
+ if (kind === "markdown-guidelines") return renderMarkdownGuidelines();
645
+ return renderLlmsFullTxt();
297
646
  }
298
647
  if (kind === "memory") return renderMemoryFile(assistant, profile);
299
648
  if (kind === "skill") switch (assistant) {
300
- case "claude": return renderClaudeCommand(skillName, profile);
649
+ case "claude": return renderClaudeSkill(skillName, profile);
301
650
  case "codex": return renderCodexSkill(profile);
302
651
  case "gemini": return renderGeminiCommand(skillName, profile);
303
652
  }
304
- if (kind === "llms") return renderLlmsTxt(profile);
305
- return renderLlmsFullTxt(profile);
653
+ if (kind === "markdown-guidelines") return renderMarkdownGuidelines();
654
+ if (kind === "update-docs") return renderUpdateDocsSkill(profile);
655
+ if (kind === "llms") return renderLlmsTxt();
656
+ return renderLlmsFullTxt();
306
657
  }
307
658
  function getAiArtifacts(options = {}) {
308
659
  const scope = options.scope ?? "project";
@@ -323,16 +674,17 @@ function getAiArtifacts(options = {}) {
323
674
  mode: "merge",
324
675
  label: `${assistant} memory`
325
676
  });
677
+ const skillDir = scope === "project" ? join(cwd, ".claude", "skills", skillName) : join(home, ".claude", "skills", skillName);
326
678
  artifacts.push({
327
679
  assistant,
328
680
  kind: "skill",
329
- path: join(baseDir, "commands", `${skillName}.md`),
681
+ path: join(skillDir, "SKILL.md"),
330
682
  content: getAiArtifactContent("claude", "skill", {
331
683
  profile,
332
684
  skillName
333
685
  }) + "\n",
334
686
  mode: "replace",
335
- label: `${assistant} command`
687
+ label: `${assistant} skill`
336
688
  });
337
689
  }
338
690
  if (assistant === "codex") {
@@ -380,19 +732,34 @@ function getAiArtifacts(options = {}) {
380
732
  });
381
733
  }
382
734
  }
735
+ if (scope === "project") artifacts.push({
736
+ kind: "markdown-guidelines",
737
+ path: join(cwd, ".pagesmith", "markdown-guidelines.md"),
738
+ content: renderMarkdownGuidelines() + "\n",
739
+ mode: "replace",
740
+ label: "markdown guidelines"
741
+ });
742
+ if (scope === "project" && assistants.includes("claude")) artifacts.push({
743
+ assistant: "claude",
744
+ kind: "update-docs",
745
+ path: join(cwd, ".claude", "skills", "update-docs", "SKILL.md"),
746
+ content: renderUpdateDocsSkill(profile) + "\n",
747
+ mode: "replace",
748
+ label: "claude update-docs skill"
749
+ });
383
750
  if (shouldIncludeLlms(options)) {
384
751
  const llmsDir = scope === "project" ? cwd : join(home, ".pagesmith");
385
752
  artifacts.push({
386
753
  kind: "llms",
387
754
  path: join(llmsDir, "llms.txt"),
388
- content: withManagedBlock("shared-llms", getAiArtifactContent("shared", "llms", { profile })) + "\n",
755
+ content: withManagedBlock("shared-llms", renderLlmsTxt()) + "\n",
389
756
  mode: "merge",
390
757
  label: "llms.txt"
391
758
  });
392
759
  artifacts.push({
393
760
  kind: "llms-full",
394
761
  path: join(llmsDir, "llms-full.txt"),
395
- content: withManagedBlock("shared-llms-full", getAiArtifactContent("shared", "llms-full", { profile })) + "\n",
762
+ content: withManagedBlock("shared-llms-full", renderLlmsFullTxt()) + "\n",
396
763
  mode: "merge",
397
764
  label: "llms-full.txt"
398
765
  });
@@ -400,7 +767,15 @@ function getAiArtifacts(options = {}) {
400
767
  return artifacts;
401
768
  }
402
769
  function installAiArtifacts(options = {}) {
403
- return getAiArtifacts(options).map((artifact) => ({
770
+ const artifacts = getAiArtifacts(options);
771
+ if (options.dryRun) return artifacts.map((artifact) => ({
772
+ assistant: artifact.assistant,
773
+ kind: artifact.kind,
774
+ path: artifact.path,
775
+ label: artifact.label,
776
+ status: "unchanged"
777
+ }));
778
+ return artifacts.map((artifact) => ({
404
779
  assistant: artifact.assistant,
405
780
  kind: artifact.kind,
406
781
  path: artifact.path,