livemark 0.2.0 → 0.7.1

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 (348) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +5 -1
  3. package/build/actions/changelog/build.d.ts +14 -0
  4. package/build/actions/changelog/build.js +158 -0
  5. package/build/actions/changelog/build.unit.js +66 -0
  6. package/build/actions/config/define.d.ts +6 -0
  7. package/build/actions/config/define.js +8 -0
  8. package/build/actions/config/define.unit.js +29 -0
  9. package/build/actions/config/load.d.ts +5 -0
  10. package/build/actions/config/load.js +25 -0
  11. package/build/actions/config/load.unit.js +23 -0
  12. package/build/commands/build.d.ts +5 -0
  13. package/build/commands/build.js +14 -0
  14. package/build/commands/escape.d.ts +9 -0
  15. package/build/commands/escape.js +56 -0
  16. package/build/commands/preview.d.ts +5 -0
  17. package/build/commands/preview.js +18 -0
  18. package/build/commands/start.d.ts +5 -0
  19. package/build/commands/start.js +19 -0
  20. package/build/docs/markdown/includes/example.d.ts +58 -0
  21. package/build/docs/markdown/includes/example.js +5 -0
  22. package/build/entrypoints/main.d.ts +2 -0
  23. package/build/entrypoints/main.js +12 -0
  24. package/build/helpers/program.d.ts +2 -0
  25. package/build/helpers/program.js +5 -0
  26. package/build/index.d.ts +1 -4
  27. package/build/index.js +2 -5
  28. package/build/livemark.config.d.ts +58 -0
  29. package/build/livemark.config.js +25 -0
  30. package/build/models/config.d.ts +340 -0
  31. package/build/models/config.js +34 -0
  32. package/build/models/link.d.ts +13 -0
  33. package/build/models/link.js +9 -0
  34. package/build/models/patch.d.ts +21 -0
  35. package/build/models/patch.js +7 -0
  36. package/build/models/section.d.ts +75 -0
  37. package/build/models/section.js +26 -0
  38. package/build/models/theme.d.ts +72 -0
  39. package/build/models/theme.js +73 -0
  40. package/build/program.d.ts +2 -0
  41. package/build/program.js +16 -0
  42. package/build/vite.config.d.ts +2 -0
  43. package/build/vite.config.js +48 -0
  44. package/build/website/assets/logo.svg +117 -0
  45. package/build/website/client.tsx +10 -0
  46. package/build/website/components/Abbr.tsx +17 -0
  47. package/build/website/components/AnsiCode.tsx +15 -0
  48. package/build/website/components/Article.tsx +172 -0
  49. package/build/website/components/BackToTop.tsx +32 -0
  50. package/build/website/components/Banner.tsx +32 -0
  51. package/build/website/components/BlogIndex.tsx +121 -0
  52. package/build/website/components/BlogSidebar.tsx +162 -0
  53. package/build/website/components/Breadcrumbs.tsx +22 -0
  54. package/build/website/components/Callout.tsx +72 -0
  55. package/build/website/components/Card.tsx +48 -0
  56. package/build/website/components/Cards.tsx +8 -0
  57. package/build/website/components/ChangelogIndex.tsx +111 -0
  58. package/build/website/components/ChangelogSidebar.tsx +120 -0
  59. package/build/website/components/CodeBlock.tsx +135 -0
  60. package/build/website/components/CodeTabs.tsx +83 -0
  61. package/build/website/components/Column.tsx +4 -0
  62. package/build/website/components/Columns.tsx +12 -0
  63. package/build/website/components/Content.tsx +7 -0
  64. package/build/website/components/ContentTab.tsx +7 -0
  65. package/build/website/components/ContentTabs.tsx +82 -0
  66. package/build/website/components/DefaultCatchBoundary.tsx +54 -0
  67. package/build/website/components/DefinitionList.tsx +21 -0
  68. package/build/website/components/Details.tsx +30 -0
  69. package/build/website/components/FileTree.tsx +52 -0
  70. package/build/website/components/Footer.tsx +16 -0
  71. package/build/website/components/FootnoteRef.tsx +52 -0
  72. package/build/website/components/Heading.tsx +20 -0
  73. package/build/website/components/InlineBadge.tsx +9 -0
  74. package/build/website/components/InlineIcon.tsx +10 -0
  75. package/build/website/components/InlineToc.tsx +31 -0
  76. package/build/website/components/Layout.tsx +190 -0
  77. package/build/website/components/LinkButton.tsx +31 -0
  78. package/build/website/components/Mermaid.tsx +18 -0
  79. package/build/website/components/MermaidRenderer.tsx +37 -0
  80. package/build/website/components/MiniSidebar.tsx +49 -0
  81. package/build/website/components/NotFound.tsx +27 -0
  82. package/build/website/components/PackageTabs.tsx +74 -0
  83. package/build/website/components/PageToolbar.tsx +75 -0
  84. package/build/website/components/PrevNext.tsx +60 -0
  85. package/build/website/components/Search.tsx +28 -0
  86. package/build/website/components/SearchDialog.tsx +245 -0
  87. package/build/website/components/Section.tsx +24 -0
  88. package/build/website/components/SectionHeader.tsx +35 -0
  89. package/build/website/components/Sidebar.tsx +160 -0
  90. package/build/website/components/SidebarLinks.tsx +70 -0
  91. package/build/website/components/SidebarSections.tsx +71 -0
  92. package/build/website/components/SiteTitle.tsx +21 -0
  93. package/build/website/components/SortableTable.tsx +81 -0
  94. package/build/website/components/SoundCloud.tsx +16 -0
  95. package/build/website/components/TagIndex.tsx +120 -0
  96. package/build/website/components/Theme.tsx +39 -0
  97. package/build/website/components/Toc.tsx +226 -0
  98. package/build/website/components/YouTube.tsx +16 -0
  99. package/build/website/components/ZoomImage.tsx +25 -0
  100. package/build/website/content/article.ts +78 -0
  101. package/build/website/content/tag.ts +29 -0
  102. package/build/website/content-collections.ts +208 -0
  103. package/build/website/elements/accordion.tsx +78 -0
  104. package/build/website/elements/alert-dialog.tsx +185 -0
  105. package/build/website/elements/alert.tsx +74 -0
  106. package/build/website/elements/aspect-ratio.tsx +22 -0
  107. package/build/website/elements/avatar.tsx +107 -0
  108. package/build/website/elements/badge.tsx +51 -0
  109. package/build/website/elements/breadcrumb.tsx +120 -0
  110. package/build/website/elements/button-group.tsx +87 -0
  111. package/build/website/elements/button.tsx +57 -0
  112. package/build/website/elements/calendar.tsx +229 -0
  113. package/build/website/elements/card.tsx +102 -0
  114. package/build/website/elements/carousel.tsx +240 -0
  115. package/build/website/elements/chart.tsx +372 -0
  116. package/build/website/elements/checkbox.tsx +26 -0
  117. package/build/website/elements/collapsible.tsx +19 -0
  118. package/build/website/elements/command.tsx +210 -0
  119. package/build/website/elements/context-menu.tsx +270 -0
  120. package/build/website/elements/dialog.tsx +152 -0
  121. package/build/website/elements/direction.tsx +4 -0
  122. package/build/website/elements/drawer.tsx +127 -0
  123. package/build/website/elements/dropdown-menu.tsx +260 -0
  124. package/build/website/elements/empty.tsx +104 -0
  125. package/build/website/elements/field.tsx +235 -0
  126. package/build/website/elements/hover-card.tsx +49 -0
  127. package/build/website/elements/input-group.tsx +171 -0
  128. package/build/website/elements/input-otp.tsx +84 -0
  129. package/build/website/elements/input.tsx +18 -0
  130. package/build/website/elements/item.tsx +199 -0
  131. package/build/website/elements/kbd.tsx +26 -0
  132. package/build/website/elements/label.tsx +17 -0
  133. package/build/website/elements/menubar.tsx +282 -0
  134. package/build/website/elements/native-select.tsx +56 -0
  135. package/build/website/elements/navigation-menu.tsx +171 -0
  136. package/build/website/elements/pagination.tsx +133 -0
  137. package/build/website/elements/popover.tsx +88 -0
  138. package/build/website/elements/progress.tsx +81 -0
  139. package/build/website/elements/radio-group.tsx +36 -0
  140. package/build/website/elements/resizable.tsx +48 -0
  141. package/build/website/elements/scroll-area.tsx +51 -0
  142. package/build/website/elements/select.tsx +200 -0
  143. package/build/website/elements/separator.tsx +22 -0
  144. package/build/website/elements/sheet.tsx +130 -0
  145. package/build/website/elements/sidebar.tsx +717 -0
  146. package/build/website/elements/skeleton.tsx +13 -0
  147. package/build/website/elements/slider.tsx +57 -0
  148. package/build/website/elements/sonner.tsx +40 -0
  149. package/build/website/elements/spinner.tsx +16 -0
  150. package/build/website/elements/switch.tsx +30 -0
  151. package/build/website/elements/table.tsx +112 -0
  152. package/build/website/elements/tabs.tsx +79 -0
  153. package/build/website/elements/textarea.tsx +16 -0
  154. package/build/website/elements/toggle-group.tsx +87 -0
  155. package/build/website/elements/toggle.tsx +43 -0
  156. package/build/website/elements/tooltip.tsx +67 -0
  157. package/build/website/env.d.ts +14 -0
  158. package/build/website/helpers/article-icon.ts +61 -0
  159. package/build/website/helpers/article.ts +90 -0
  160. package/build/website/helpers/changelog-source.ts +16 -0
  161. package/build/website/helpers/changelog-source.unit.ts +38 -0
  162. package/build/website/helpers/dynamic-icon-resolver.tsx +19 -0
  163. package/build/website/helpers/dynamic-icon.tsx +12 -0
  164. package/build/website/helpers/favicon.ts +7 -0
  165. package/build/website/helpers/model.ts +4 -0
  166. package/build/website/helpers/resolve-asset-path.ts +9 -0
  167. package/build/website/helpers/resolve-includes.ts +131 -0
  168. package/build/website/helpers/resolve-includes.unit.ts +126 -0
  169. package/build/website/helpers/search-text.ts +15 -0
  170. package/build/website/helpers/section.ts +50 -0
  171. package/build/website/helpers/section.unit.ts +71 -0
  172. package/build/website/helpers/style.ts +6 -0
  173. package/build/website/helpers/theme.ts +27 -0
  174. package/build/website/helpers/toc-context.ts +10 -0
  175. package/build/website/helpers/toc.ts +46 -0
  176. package/build/website/helpers/toc.unit.ts +74 -0
  177. package/build/website/hooks/in-view.ts +30 -0
  178. package/build/website/hooks/media.ts +19 -0
  179. package/build/website/models/article.ts +55 -0
  180. package/build/website/models/toc.ts +5 -0
  181. package/build/website/plugins/rehype-inline-code.ts +107 -0
  182. package/build/website/plugins/rehype-task-list-a11y.ts +33 -0
  183. package/build/website/plugins/remark-abbr.ts +46 -0
  184. package/build/website/plugins/remark-abbr.unit.ts +99 -0
  185. package/build/website/plugins/remark-ansi.ts +248 -0
  186. package/build/website/plugins/remark-ansi.unit.ts +197 -0
  187. package/build/website/plugins/remark-badge.ts +50 -0
  188. package/build/website/plugins/remark-badge.unit.ts +96 -0
  189. package/build/website/plugins/remark-button.ts +60 -0
  190. package/build/website/plugins/remark-button.unit.ts +147 -0
  191. package/build/website/plugins/remark-callout.ts +57 -0
  192. package/build/website/plugins/remark-card.ts +80 -0
  193. package/build/website/plugins/remark-code-tabs.ts +87 -0
  194. package/build/website/plugins/remark-columns.ts +66 -0
  195. package/build/website/plugins/remark-custom-heading-id.ts +70 -0
  196. package/build/website/plugins/remark-custom-heading-id.unit.ts +131 -0
  197. package/build/website/plugins/remark-deflist.ts +36 -0
  198. package/build/website/plugins/remark-details.ts +49 -0
  199. package/build/website/plugins/remark-filetree.ts +89 -0
  200. package/build/website/plugins/remark-filetree.unit.ts +137 -0
  201. package/build/website/plugins/remark-github-callout.ts +71 -0
  202. package/build/website/plugins/remark-icon.ts +42 -0
  203. package/build/website/plugins/remark-image.ts +34 -0
  204. package/build/website/plugins/remark-media.ts +62 -0
  205. package/build/website/plugins/remark-media.unit.ts +74 -0
  206. package/build/website/plugins/remark-mermaid.ts +23 -0
  207. package/build/website/plugins/remark-npm.ts +52 -0
  208. package/build/website/plugins/remark-steps.ts +36 -0
  209. package/build/website/plugins/remark-steps.unit.ts +97 -0
  210. package/build/website/plugins/remark-tab.ts +100 -0
  211. package/build/website/plugins/remark-tab.unit.ts +181 -0
  212. package/build/website/plugins/remark-toc.ts +39 -0
  213. package/build/website/plugins/remark-toc.unit.ts +82 -0
  214. package/build/website/plugins/shiki-icon.ts +82 -0
  215. package/build/website/plugins/shiki-line-highlight.ts +174 -0
  216. package/build/website/plugins/vite-livemark.ts +91 -0
  217. package/build/website/routeTree.gen.ts +86 -0
  218. package/build/website/router.tsx +34 -0
  219. package/build/website/routes/$.tsx +92 -0
  220. package/build/website/routes/__root.tsx +97 -0
  221. package/build/website/server.ts +7 -0
  222. package/build/website/styles/general.css +163 -0
  223. package/build/website/styles/markdown.css +214 -0
  224. package/build/website/vite.config.ts +71 -0
  225. package/package.json +120 -12
  226. package/skills/authoring/SKILL.md +97 -0
  227. package/skills/configuration/SKILL.md +120 -0
  228. package/skills/customization/SKILL.md +118 -0
  229. package/build/descriptor/index.d.ts +0 -3
  230. package/build/descriptor/index.js +0 -4
  231. package/build/descriptor/load.d.ts +0 -8
  232. package/build/descriptor/load.js +0 -40
  233. package/build/descriptor/node.d.ts +0 -125
  234. package/build/descriptor/node.js +0 -9
  235. package/build/descriptor/save.d.ts +0 -8
  236. package/build/descriptor/save.js +0 -17
  237. package/build/descriptor/save.spec.js +0 -80
  238. package/build/descriptor/validate.d.ts +0 -9
  239. package/build/descriptor/validate.js +0 -14
  240. package/build/descriptor/validate.spec.js +0 -124
  241. package/build/dialect/Dialect.d.ts +0 -88
  242. package/build/dialect/Dialect.js +0 -2
  243. package/build/dialect/index.d.ts +0 -3
  244. package/build/dialect/index.js +0 -3
  245. package/build/dialect/load.d.ts +0 -4
  246. package/build/dialect/load.js +0 -7
  247. package/build/dialect/save.d.ts +0 -9
  248. package/build/dialect/save.js +0 -13
  249. package/build/dialect/validate.d.ts +0 -1
  250. package/build/dialect/validate.js +0 -4
  251. package/build/metadata/index.d.ts +0 -3
  252. package/build/metadata/index.js +0 -4
  253. package/build/metadata/load.d.ts +0 -10
  254. package/build/metadata/load.js +0 -55
  255. package/build/metadata/node.d.ts +0 -125
  256. package/build/metadata/node.js +0 -9
  257. package/build/metadata/save.d.ts +0 -8
  258. package/build/metadata/save.js +0 -17
  259. package/build/metadata/save.spec.js +0 -80
  260. package/build/metadata/validate.d.ts +0 -9
  261. package/build/metadata/validate.js +0 -14
  262. package/build/metadata/validate.spec.d.ts +0 -1
  263. package/build/metadata/validate.spec.js +0 -124
  264. package/build/package/Contributor.d.ts +0 -21
  265. package/build/package/Contributor.js +0 -2
  266. package/build/package/Package.d.ts +0 -65
  267. package/build/package/Package.js +0 -2
  268. package/build/package/index.d.ts +0 -4
  269. package/build/package/index.js +0 -3
  270. package/build/package/load.d.ts +0 -4
  271. package/build/package/load.js +0 -7
  272. package/build/package/save.d.ts +0 -9
  273. package/build/package/save.js +0 -13
  274. package/build/package/validate.d.ts +0 -1
  275. package/build/package/validate.js +0 -4
  276. package/build/resource/License.d.ts +0 -18
  277. package/build/resource/License.js +0 -2
  278. package/build/resource/Resource.d.ts +0 -67
  279. package/build/resource/Resource.js +0 -2
  280. package/build/resource/Source.d.ts +0 -17
  281. package/build/resource/Source.js +0 -2
  282. package/build/resource/index.d.ts +0 -5
  283. package/build/resource/index.js +0 -2
  284. package/build/resource/load.d.ts +0 -1
  285. package/build/resource/load.js +0 -2
  286. package/build/resource/save.d.ts +0 -9
  287. package/build/resource/save.js +0 -13
  288. package/build/resource/types/index.d.ts +0 -1
  289. package/build/resource/types/index.js +0 -2
  290. package/build/resource/types/table.d.ts +0 -29
  291. package/build/resource/types/table.js +0 -2
  292. package/build/resource/validate.d.ts +0 -1
  293. package/build/resource/validate.js +0 -4
  294. package/build/schema/Field.d.ts +0 -5
  295. package/build/schema/Field.js +0 -2
  296. package/build/schema/Schema.d.ts +0 -55
  297. package/build/schema/Schema.js +0 -2
  298. package/build/schema/fields/any.d.ts +0 -20
  299. package/build/schema/fields/any.js +0 -2
  300. package/build/schema/fields/array.d.ts +0 -32
  301. package/build/schema/fields/array.js +0 -2
  302. package/build/schema/fields/base.d.ts +0 -42
  303. package/build/schema/fields/base.js +0 -2
  304. package/build/schema/fields/boolean.d.ts +0 -28
  305. package/build/schema/fields/boolean.js +0 -2
  306. package/build/schema/fields/date.d.ts +0 -35
  307. package/build/schema/fields/date.js +0 -2
  308. package/build/schema/fields/datetime.d.ts +0 -35
  309. package/build/schema/fields/datetime.js +0 -2
  310. package/build/schema/fields/duration.d.ts +0 -28
  311. package/build/schema/fields/duration.js +0 -2
  312. package/build/schema/fields/geojson.d.ts +0 -26
  313. package/build/schema/fields/geojson.js +0 -2
  314. package/build/schema/fields/geopoint.d.ts +0 -27
  315. package/build/schema/fields/geopoint.js +0 -2
  316. package/build/schema/fields/index.d.ts +0 -16
  317. package/build/schema/fields/index.js +0 -17
  318. package/build/schema/fields/integer.d.ts +0 -37
  319. package/build/schema/fields/integer.js +0 -2
  320. package/build/schema/fields/list.d.ts +0 -36
  321. package/build/schema/fields/list.js +0 -2
  322. package/build/schema/fields/number.d.ts +0 -40
  323. package/build/schema/fields/number.js +0 -2
  324. package/build/schema/fields/object.d.ts +0 -32
  325. package/build/schema/fields/object.js +0 -2
  326. package/build/schema/fields/string.d.ts +0 -40
  327. package/build/schema/fields/string.js +0 -2
  328. package/build/schema/fields/time.d.ts +0 -35
  329. package/build/schema/fields/time.js +0 -2
  330. package/build/schema/fields/year.d.ts +0 -28
  331. package/build/schema/fields/year.js +0 -2
  332. package/build/schema/fields/yearmonth.d.ts +0 -28
  333. package/build/schema/fields/yearmonth.js +0 -2
  334. package/build/schema/index.d.ts +0 -4
  335. package/build/schema/index.js +0 -2
  336. package/build/schema/load.d.ts +0 -1
  337. package/build/schema/load.js +0 -2
  338. package/build/schema/save.d.ts +0 -9
  339. package/build/schema/save.js +0 -13
  340. package/build/schema/validate.d.ts +0 -1
  341. package/build/schema/validate.js +0 -4
  342. package/build/tsconfig.tsbuildinfo +0 -1
  343. package/index.ts +0 -0
  344. package/tsconfig.json +0 -10
  345. package/typedoc.json +0 -4
  346. /package/build/{descriptor/save.spec.d.ts → actions/changelog/build.unit.d.ts} +0 -0
  347. /package/build/{descriptor/validate.spec.d.ts → actions/config/define.unit.d.ts} +0 -0
  348. /package/build/{metadata/save.spec.d.ts → actions/config/load.unit.d.ts} +0 -0
@@ -0,0 +1,163 @@
1
+ @import "tailwindcss";
2
+ @import "tw-animate-css";
3
+ @plugin "@tailwindcss/typography";
4
+
5
+ @custom-variant dark (&:is(.dark *));
6
+
7
+ :root {
8
+ --background: oklch(1 0 0);
9
+ --foreground: oklch(0.145 0 0);
10
+ --card: oklch(1 0 0);
11
+ --card-foreground: oklch(0.145 0 0);
12
+ --popover: oklch(1 0 0);
13
+ --popover-foreground: oklch(0.145 0 0);
14
+ --primary: oklch(54.6% 0.245 262.881);
15
+ --primary-foreground: oklch(0.985 0 0);
16
+ --secondary: oklch(89.4% 0.057 293.283);
17
+ --secondary-foreground: oklch(0.205 0 0);
18
+ --muted: oklch(0.97 0 0);
19
+ --muted-foreground: oklch(0.5 0 0);
20
+ --accent: oklch(0.97 0 0);
21
+ --accent-foreground: oklch(0.205 0 0);
22
+ --destructive: oklch(0.577 0.245 27.325);
23
+ --destructive-foreground: oklch(0.577 0.245 27.325);
24
+ --border: oklch(0.922 0 0);
25
+ --input: oklch(0.922 0 0);
26
+ --ring: oklch(0.708 0 0);
27
+ --chart-1: oklch(0.646 0.222 41.116);
28
+ --chart-2: oklch(0.6 0.118 184.704);
29
+ --chart-3: oklch(0.398 0.07 227.392);
30
+ --chart-4: oklch(0.828 0.189 84.429);
31
+ --chart-5: oklch(0.769 0.188 70.08);
32
+ --radius: 0.625rem;
33
+ --sidebar: oklch(0.985 0 0);
34
+ --sidebar-foreground: oklch(0.145 0 0);
35
+ --sidebar-primary: oklch(0.205 0 0);
36
+ --sidebar-primary-foreground: oklch(0.985 0 0);
37
+ --sidebar-accent: oklch(0.97 0 0);
38
+ --sidebar-accent-foreground: oklch(0.205 0 0);
39
+ --sidebar-border: oklch(0.922 0 0);
40
+ --sidebar-ring: oklch(0.708 0 0);
41
+ }
42
+
43
+ .dark {
44
+ --background: oklch(0.145 0 0);
45
+ --foreground: oklch(0.985 0 0);
46
+ --card: oklch(0.145 0 0);
47
+ --card-foreground: oklch(0.985 0 0);
48
+ --popover: oklch(0.145 0 0);
49
+ --popover-foreground: oklch(0.985 0 0);
50
+ --primary: oklch(0.623 0.214 259.815);
51
+ --primary-foreground: oklch(0.985 0 0);
52
+ --secondary: oklch(0.269 0 0);
53
+ --secondary-foreground: oklch(0.985 0 0);
54
+ --muted: oklch(0.269 0 0);
55
+ --muted-foreground: oklch(0.708 0 0);
56
+ --accent: oklch(0.269 0 0);
57
+ --accent-foreground: oklch(0.985 0 0);
58
+ --destructive: oklch(0.396 0.141 25.723);
59
+ --destructive-foreground: oklch(0.637 0.237 25.331);
60
+ --border: oklch(0.269 0 0);
61
+ --input: oklch(0.269 0 0);
62
+ --ring: oklch(0.439 0 0);
63
+ --chart-1: oklch(0.488 0.243 264.376);
64
+ --chart-2: oklch(0.696 0.17 162.48);
65
+ --chart-3: oklch(0.769 0.188 70.08);
66
+ --chart-4: oklch(0.627 0.265 303.9);
67
+ --chart-5: oklch(0.645 0.246 16.439);
68
+ --sidebar: oklch(0.205 0 0);
69
+ --sidebar-foreground: oklch(0.985 0 0);
70
+ --sidebar-primary: oklch(0.488 0.243 264.376);
71
+ --sidebar-primary-foreground: oklch(0.985 0 0);
72
+ --sidebar-accent: oklch(0.269 0 0);
73
+ --sidebar-accent-foreground: oklch(0.985 0 0);
74
+ --sidebar-border: oklch(0.269 0 0);
75
+ --sidebar-ring: oklch(0.439 0 0);
76
+ }
77
+
78
+ @theme inline {
79
+ --color-background: var(--background);
80
+ --color-foreground: var(--foreground);
81
+ --color-card: var(--card);
82
+ --color-card-foreground: var(--card-foreground);
83
+ --color-popover: var(--popover);
84
+ --color-popover-foreground: var(--popover-foreground);
85
+ --color-primary: var(--primary);
86
+ --color-primary-foreground: var(--primary-foreground);
87
+ --color-secondary: var(--secondary);
88
+ --color-secondary-foreground: var(--secondary-foreground);
89
+ --color-muted: var(--muted);
90
+ --color-muted-foreground: var(--muted-foreground);
91
+ --color-accent: var(--accent);
92
+ --color-accent-foreground: var(--accent-foreground);
93
+ --color-destructive: var(--destructive);
94
+ --color-destructive-foreground: var(--destructive-foreground);
95
+ --color-border: var(--border);
96
+ --color-input: var(--input);
97
+ --color-ring: var(--ring);
98
+ --color-chart-1: var(--chart-1);
99
+ --color-chart-2: var(--chart-2);
100
+ --color-chart-3: var(--chart-3);
101
+ --color-chart-4: var(--chart-4);
102
+ --color-chart-5: var(--chart-5);
103
+ --radius-sm: calc(var(--radius) - 4px);
104
+ --radius-md: calc(var(--radius) - 2px);
105
+ --radius-lg: var(--radius);
106
+ --radius-xl: calc(var(--radius) + 4px);
107
+ --color-sidebar: var(--sidebar);
108
+ --color-sidebar-foreground: var(--sidebar-foreground);
109
+ --color-sidebar-primary: var(--sidebar-primary);
110
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
111
+ --color-sidebar-accent: var(--sidebar-accent);
112
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
113
+ --color-sidebar-border: var(--sidebar-border);
114
+ --color-sidebar-ring: var(--sidebar-ring);
115
+ }
116
+
117
+ @layer base {
118
+ * {
119
+ @apply border-border outline-ring/50;
120
+ }
121
+ body {
122
+ @apply bg-background text-foreground;
123
+ }
124
+
125
+ html {
126
+ scroll-behavior: smooth;
127
+ scrollbar-color: #ddd transparent;
128
+ scrollbar-gutter: stable;
129
+ }
130
+
131
+ button:not([disabled]),
132
+ [role="button"]:not([disabled]) {
133
+ cursor: pointer;
134
+ }
135
+
136
+ [data-slot="sidebar-content"] {
137
+ scrollbar-width: thin;
138
+ scrollbar-color: transparent transparent;
139
+ transition: scrollbar-color 0.2s;
140
+ }
141
+ [data-slot="sidebar-content"]:hover,
142
+ [data-slot="sidebar-content"]:focus-within {
143
+ scrollbar-color: color-mix(
144
+ in oklch,
145
+ var(--sidebar-foreground) 20%,
146
+ transparent
147
+ )
148
+ transparent;
149
+ }
150
+
151
+ [data-slot="sidebar-content"]::-webkit-scrollbar {
152
+ width: 8px;
153
+ }
154
+ [data-slot="sidebar-content"]::-webkit-scrollbar-thumb {
155
+ background: transparent;
156
+ border-radius: 9999px;
157
+ transition: background 0.2s;
158
+ }
159
+ [data-slot="sidebar-content"]:hover::-webkit-scrollbar-thumb,
160
+ [data-slot="sidebar-content"]:focus-within::-webkit-scrollbar-thumb {
161
+ background: color-mix(in oklch, var(--sidebar-foreground) 20%, transparent);
162
+ }
163
+ }
@@ -0,0 +1,214 @@
1
+ @import "katex/dist/katex.min.css";
2
+ @reference "./general.css";
3
+
4
+ @layer components {
5
+ .prose :is(h1, h2, h3, h4, h5, h6) {
6
+ @apply scroll-mt-28 md:scroll-mt-20;
7
+ }
8
+
9
+ .prose :is(h1, h2, h3, h4, h5, h6)[id] {
10
+ position: relative;
11
+ }
12
+
13
+ .prose :is(h1, h2, h3, h4, h5, h6)[id]::after {
14
+ content: "";
15
+ display: inline-block;
16
+ width: 0.6em;
17
+ height: 0.6em;
18
+ margin-left: 0.4em;
19
+ vertical-align: middle;
20
+ opacity: 0;
21
+ transition: opacity 0.15s;
22
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71'/%3E%3Cpath d='M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71'/%3E%3C/svg%3E");
23
+ background-size: contain;
24
+ background-repeat: no-repeat;
25
+ }
26
+
27
+ .prose :is(h1, h2, h3, h4, h5, h6)[id]:hover::after {
28
+ opacity: 0.5;
29
+ }
30
+
31
+ .prose :is(h1, h2, h3, h4, h5, h6)[id] a,
32
+ .prose :is(h1, h2, h3, h4, h5, h6)[id] a:hover {
33
+ color: inherit !important;
34
+ text-decoration: none !important;
35
+ }
36
+
37
+ .prose pre code .line {
38
+ @apply px-4;
39
+ }
40
+
41
+ .prose pre code .line[data-highlighted] {
42
+ @apply bg-primary/10;
43
+ }
44
+
45
+ .prose pre code .line[data-diff="add"] {
46
+ @apply bg-green-500/15;
47
+ }
48
+
49
+ .prose pre code .line[data-diff="remove"] {
50
+ @apply bg-red-500/15;
51
+ }
52
+
53
+ .prose pre code .line[data-diff="add"]::before {
54
+ content: "+";
55
+ @apply text-green-600 absolute left-1;
56
+ }
57
+
58
+ .prose pre code .line[data-diff="remove"]::before {
59
+ content: "-";
60
+ @apply text-red-600 absolute left-1;
61
+ }
62
+
63
+ .prose pre code .line[data-line-status="error"] {
64
+ @apply bg-red-500/15;
65
+ }
66
+
67
+ .prose pre code .line[data-line-status="warning"] {
68
+ @apply bg-yellow-500/15;
69
+ }
70
+
71
+ .prose pre[data-has-focus] code .line:not([data-focus]) {
72
+ @apply opacity-30;
73
+ }
74
+
75
+ .prose pre[data-has-focus] code .line[data-focus] {
76
+ @apply opacity-100;
77
+ }
78
+
79
+ .prose pre code [data-word-highlighted] {
80
+ @apply bg-primary/20 rounded px-0.5 py-0.5;
81
+ }
82
+
83
+ .prose pre code .line[data-line-number]::before {
84
+ content: attr(data-line-number);
85
+ display: inline-block;
86
+ width: 2rem;
87
+ margin-right: 1rem;
88
+ text-align: right;
89
+ color: var(--color-muted-foreground);
90
+ opacity: 0.5;
91
+ user-select: none;
92
+ }
93
+
94
+ .prose pre code .twoslash-popup-container {
95
+ @apply absolute z-10 translate-y-1 rounded-md border border-border bg-popover px-3 py-1.5 text-xs shadow-md;
96
+ }
97
+
98
+ .prose pre code .twoslash-popup-type {
99
+ @apply font-mono text-muted-foreground;
100
+ }
101
+
102
+ .prose pre code .twoslash-error-line {
103
+ @apply bg-red-500/10;
104
+ }
105
+
106
+ .prose pre code .twoslash-tag-line {
107
+ @apply opacity-50;
108
+ }
109
+
110
+ .prose pre code .twoslash-completion-list {
111
+ @apply absolute z-10 translate-y-1 rounded-md border border-border bg-popover p-1 text-xs shadow-md;
112
+ }
113
+
114
+ .prose pre code .twoslash-completion-list .twoslash-completion-item {
115
+ @apply px-2 py-0.5;
116
+ }
117
+
118
+ .prose pre code .twoslash-hover .twoslash-popup-container {
119
+ @apply hidden;
120
+ }
121
+
122
+ .prose pre code .twoslash-hover:hover .twoslash-popup-container {
123
+ @apply block;
124
+ }
125
+
126
+ .prose :not(pre) > code {
127
+ @apply bg-muted/70 border border-border rounded-md px-1.5 py-0.5 text-sm font-mono;
128
+ }
129
+
130
+ .prose :not(pre) > code::before,
131
+ .prose :not(pre) > code::after {
132
+ content: none !important;
133
+ }
134
+
135
+ .prose code.shiki-inline {
136
+ @apply bg-muted/70 border border-border rounded-md px-1.5 py-0.5 text-sm font-mono;
137
+ }
138
+
139
+ .prose code.shiki-inline .line {
140
+ display: inline;
141
+ }
142
+
143
+ .dark .shiki span {
144
+ color: var(--shiki-dark) !important;
145
+ }
146
+
147
+ .katex-display {
148
+ @apply overflow-x-auto overflow-y-hidden;
149
+ }
150
+
151
+ .katex {
152
+ @apply overflow-x-auto overflow-y-hidden;
153
+ }
154
+
155
+ .prose ul:has(> li > input[type="checkbox"]) {
156
+ padding-inline-start: 0.5em;
157
+ }
158
+
159
+ .prose ul > li:has(> input[type="checkbox"]) {
160
+ list-style-type: none;
161
+ padding-left: 0;
162
+ }
163
+
164
+ .prose [data-footnotes] {
165
+ @apply mt-8 border-t border-border pt-4 text-sm text-muted-foreground;
166
+ }
167
+
168
+ .prose [data-footnotes] ol {
169
+ @apply list-decimal pl-6;
170
+ }
171
+
172
+ .prose sup a[data-footnote-ref] {
173
+ @apply ml-0.5 px-0.5 text-primary text-xs no-underline font-medium;
174
+ }
175
+
176
+ .prose [data-footnotes] a[data-footnote-backref] {
177
+ @apply text-primary no-underline;
178
+ }
179
+
180
+ .prose dl {
181
+ @apply my-4;
182
+ }
183
+
184
+ .prose dt {
185
+ @apply font-semibold mt-4 first:mt-0;
186
+ }
187
+
188
+ .prose dd {
189
+ @apply ml-6 mt-1 text-muted-foreground;
190
+ }
191
+
192
+ .prose {
193
+ counter-reset: step;
194
+ }
195
+
196
+ .prose [data-step] {
197
+ counter-increment: step;
198
+ }
199
+
200
+ .prose [data-step]::before {
201
+ content: counter(step);
202
+ display: inline-flex;
203
+ align-items: center;
204
+ justify-content: center;
205
+ width: 1.5rem;
206
+ height: 1.5rem;
207
+ border-radius: 9999px;
208
+ background: var(--color-primary);
209
+ color: white;
210
+ font-size: 0.75rem;
211
+ font-weight: 600;
212
+ margin-right: 0.5rem;
213
+ }
214
+ }
@@ -0,0 +1,71 @@
1
+ import { existsSync, mkdirSync, writeFileSync } from "node:fs"
2
+ import { join, relative } from "node:path"
3
+ import contentCollections from "@content-collections/vite"
4
+ import tailwind from "@tailwindcss/vite"
5
+ import { devtools } from "@tanstack/devtools-vite"
6
+ import { tanstackStart } from "@tanstack/react-start/plugin/vite"
7
+ import {
8
+ physical,
9
+ rootRoute,
10
+ route,
11
+ type VirtualRouteNode,
12
+ } from "@tanstack/virtual-file-routes"
13
+ import react from "@vitejs/plugin-react"
14
+ import { defineConfig } from "vite"
15
+ import svgr from "vite-plugin-svgr"
16
+ import { loadConfig } from "../actions/config/load.ts"
17
+ import { WebsiteConfig } from "../models/config.ts"
18
+ import { livemark, OVERRIDE_SUBDIRS } from "./plugins/vite-livemark.ts"
19
+
20
+ const config = await loadConfig()
21
+ const websiteDir = import.meta.dirname
22
+ const websiteRelative = relative(config.root, websiteDir)
23
+ const overridesRoot = join(config.root, ".livemark")
24
+
25
+ // Seed `.livemark/.gitignore` on first run so Vite's build/cache artifacts
26
+ // never get committed by accident.
27
+ const gitignorePath = join(overridesRoot, ".gitignore")
28
+ if (!existsSync(gitignorePath)) {
29
+ mkdirSync(overridesRoot, { recursive: true })
30
+ writeFileSync(gitignorePath, "/build\n/cache\n")
31
+ }
32
+
33
+ const routeChildren: VirtualRouteNode[] = [route("/$", "$.tsx")]
34
+ if (existsSync(join(overridesRoot, "routes"))) {
35
+ routeChildren.push(physical("../../.livemark/routes"))
36
+ }
37
+
38
+ export default defineConfig({
39
+ root: config.root,
40
+ publicDir: join(config.root, ".livemark", "public"),
41
+ build: { outDir: ".livemark/build" },
42
+ define: {
43
+ "import.meta.env.CONFIG": JSON.stringify(WebsiteConfig.parse(config)),
44
+ },
45
+ plugins: [
46
+ livemark({
47
+ defaultsRoot: websiteDir,
48
+ overridesRoot,
49
+ subdirs: [...OVERRIDE_SUBDIRS],
50
+ configPath: config.configPath,
51
+ }),
52
+ devtools(),
53
+ tailwind(),
54
+ contentCollections({
55
+ configPath: join(websiteRelative, "content-collections.ts"),
56
+ }),
57
+ tanstackStart({
58
+ srcDirectory: websiteRelative,
59
+ pages: [{ path: "/" }],
60
+ prerender: { enabled: true, crawlLinks: true },
61
+ sitemap: config.site
62
+ ? { enabled: true, host: config.site }
63
+ : { enabled: false },
64
+ router: {
65
+ virtualRouteConfig: rootRoute("__root.tsx", routeChildren),
66
+ },
67
+ }),
68
+ react(),
69
+ svgr(),
70
+ ],
71
+ })
package/package.json CHANGED
@@ -1,21 +1,129 @@
1
1
  {
2
2
  "name": "livemark",
3
- "type": "module",
4
- "main": "build/index.js",
5
- "version": "0.2.0",
3
+ "version": "0.7.1",
4
+ "description": "Livemark description",
6
5
  "license": "MIT",
7
6
  "author": "Evgeny Karev",
8
7
  "repository": "https://github.com/datisthq/livemark",
9
- "description": "Livemark implementation in TypeScript.",
10
- "keywords": [
11
- "markdown",
12
- "typescript",
13
- "documentation",
14
- "quality",
15
- "testing",
16
- "cli"
8
+ "bin": {
9
+ "livemark": "./build/entrypoints/main.js"
10
+ },
11
+ "files": [
12
+ "build",
13
+ "skills"
17
14
  ],
15
+ "type": "module",
16
+ "sideEffects": false,
17
+ "imports": {
18
+ "#*": "./*"
19
+ },
20
+ "exports": {
21
+ ".": "./build/index.js",
22
+ "./components/*": "./build/website/components/*.tsx",
23
+ "./elements/*": "./build/website/elements/*.tsx",
24
+ "./styles/*": "./build/website/styles/*.css"
25
+ },
26
+ "dependencies": {
27
+ "@base-ui/react": "1.3.0",
28
+ "@content-collections/core": "0.14.3",
29
+ "@content-collections/mdx": "0.2.2",
30
+ "@content-collections/vite": "0.3.0",
31
+ "@orama/orama": "^3.1.18",
32
+ "@shikijs/rehype": "4.0.2",
33
+ "@shikijs/twoslash": "^4.0.2",
34
+ "@sindresorhus/slugify": "^3.0.0",
35
+ "@tailwindcss/typography": "^0.5.19",
36
+ "@tailwindcss/vite": "4.2.4",
37
+ "@tanstack/devtools-vite": "0.6.0",
38
+ "@tanstack/react-devtools": "0.10.0",
39
+ "@tanstack/react-hotkeys": "^0.9.1",
40
+ "@tanstack/react-query": "5.91.3",
41
+ "@tanstack/react-query-devtools": "5.91.3",
42
+ "@tanstack/react-router": "1.168.1",
43
+ "@tanstack/react-router-devtools": "1.166.10",
44
+ "@tanstack/react-router-ssr-query": "1.166.10",
45
+ "@tanstack/react-start": "1.167.2",
46
+ "@tanstack/virtual-file-routes": "^1.161.7",
47
+ "@types/mdast": "^4.0.4",
48
+ "@types/react": "19.2.14",
49
+ "@types/react-dom": "19.2.3",
50
+ "@vitejs/plugin-react": "6.0.1",
51
+ "class-variance-authority": "0.7.1",
52
+ "clsx": "2.1.1",
53
+ "cmdk": "1.1.1",
54
+ "commander": "14.0.3",
55
+ "embla-carousel-react": "8.6.0",
56
+ "es-toolkit": "1.44.0",
57
+ "github-slugger": "^2.0.0",
58
+ "input-otp": "1.4.2",
59
+ "katex": "^0.16.44",
60
+ "lucide-react": "0.577.0",
61
+ "mdast-util-directive": "^3.1.0",
62
+ "mdast-util-to-string": "^4.0.0",
63
+ "mermaid": "^11.14.0",
64
+ "npm-to-yarn": "^3.0.1",
65
+ "picocolors": "1.1.1",
66
+ "react": "19.2.4",
67
+ "react-day-picker": "9.14.0",
68
+ "react-dom": "19.2.4",
69
+ "react-medium-image-zoom": "^5.4.2",
70
+ "react-resizable-panels": "4.9.0",
71
+ "recharts": "3.8.1",
72
+ "rehype-katex": "7.0.1",
73
+ "rehype-sanitize": "6.0.0",
74
+ "rehype-slug": "^6.0.0",
75
+ "remark-definition-list": "^2.0.0",
76
+ "remark-directive": "^4.0.0",
77
+ "remark-gemoji": "^8.0.0",
78
+ "remark-gfm": "4.0.1",
79
+ "remark-math": "6.0.0",
80
+ "remark-parse": "^11.0.0",
81
+ "remark-stringify": "^11.0.0",
82
+ "shadcn": "3.7.0",
83
+ "shiki": "4.0.2",
84
+ "sonner": "2.0.7",
85
+ "tailwind-merge": "3.5.0",
86
+ "tailwindcss": "4.2.2",
87
+ "tw-animate-css": "1.4.0",
88
+ "unified": "^11.0.5",
89
+ "unist-util-visit": "^5.1.0",
90
+ "vaul": "1.1.2",
91
+ "vite": "8.0.10",
92
+ "vite-plugin-svgr": "5.2.0",
93
+ "zod": "4.3.6"
94
+ },
95
+ "devDependencies": {
96
+ "@semantic-release/exec": "7.1.0",
97
+ "@types/node": "24.2.0",
98
+ "@typescript/native-preview": "7.0.0-dev.20260316.1",
99
+ "@vitest/coverage-v8": "4.1.5",
100
+ "conventional-changelog-conventionalcommits": "9.1.0",
101
+ "husky": "9.1.7",
102
+ "is-ci": "4.1.0",
103
+ "lefthook": "2.1.1",
104
+ "npm-check-updates": "18.0.1",
105
+ "semantic-release": "24.2.9",
106
+ "tempy": "3.2.0",
107
+ "vite-plus": "0.1.19",
108
+ "vitest-polly": "2.1.0",
109
+ "wrangler": "4.85.0"
110
+ },
111
+ "engines": {
112
+ "node": "^24.0.0",
113
+ "pnpm": "^10.0.0"
114
+ },
18
115
  "scripts": {
19
- "build": "tsc --build"
116
+ "build": "tsgo && rm -rf build/website && cp -r website build",
117
+ "bump": "ncu -u",
118
+ "clean": "rm -rf pnpm-lock.yaml node_modules build",
119
+ "docs:build": "node entrypoints/main.ts build",
120
+ "docs:start": "node entrypoints/main.ts start",
121
+ "format": "vp fmt",
122
+ "lint": "vp fmt --check && vp lint",
123
+ "release": "pnpm publish --access public --ignore-scripts --no-git-checks",
124
+ "setversion": "pnpm version --no-git-tag-version",
125
+ "unit": "vp test",
126
+ "test": "pnpm lint && pnpm type && pnpm unit",
127
+ "type": "tsgo --noEmit"
20
128
  }
21
129
  }
@@ -0,0 +1,97 @@
1
+ ---
2
+ name: livemark-authoring
3
+ description: Use when adding or editing Markdown articles in a Livemark project — covers file placement under include globs, frontmatter fields, sidebar grouping, URL derivation, images/assets, and the patches mechanism for files that can't carry frontmatter.
4
+ ---
5
+
6
+ # Livemark Authoring
7
+
8
+ Guidance for writing and maintaining Markdown content in a Livemark project.
9
+
10
+ ## When to use this skill
11
+
12
+ Invoke when the user asks to:
13
+
14
+ - Add a new article, page, or docs section.
15
+ - Rename, reorder, hide, or regroup an existing article.
16
+ - Set metadata (title, icon, tags, date, author, OG image).
17
+ - Patch a file (typically `README.md`) that needs Livemark metadata without dirtying its upstream rendering.
18
+
19
+ ## Where articles live
20
+
21
+ - Livemark collects Markdown files that match the `include` glob(s) in `livemark.config.ts`. The default project layout is `docs/**/*.md`. Respect existing convention in the repo.
22
+ - Files ending in `.md` are supported by default. Drafts/partials can be co-located but excluded via the `exclude` glob (e.g. `docs/**/_*.md`).
23
+
24
+ ## Frontmatter template
25
+
26
+ Every field is optional. Livemark derives defaults from the file itself.
27
+
28
+ ```yaml
29
+ ---
30
+ title: Getting Started # default: first `# ` heading, else filename
31
+ label: Start # short variant used in sidebar/breadcrumbs
32
+ description: A one-line blurb. # used in <meta description> and OG
33
+ icon: rocket # lucide icon name
34
+ order: 1 # sidebar sort; negatives pin to end
35
+ group: Docs # sidebar section label
36
+ path: /getting-started/ # default: slugified filename + leading/trailing slashes
37
+ sidebar: true # false hides from nav but keeps URL reachable
38
+ toc: true # false suppresses right-hand TOC
39
+ image: ./cover.png # OG/social card; relative resolves against the file
40
+ author: Ada Lovelace # or [Ada Lovelace, Grace Hopper]
41
+ date: 2026-04-20 # ISO — drives blog section sort order
42
+ tags: [release, announcement] # blog-section tag pages /prefix/tags/<tag>/
43
+ ---
44
+ ```
45
+
46
+ ## Rules of thumb
47
+
48
+ 1. **One H1 per file.** Livemark uses the first `# ` for the title when frontmatter `title` is omitted. Don't add a duplicate H1 in the body if the frontmatter already sets `title`.
49
+ 2. **Order is piecewise.** Positive numbers sort first ascending, unordered articles come next, negative numbers land at the end (`-1` last, `-2` second-to-last). Leave the middle alone — only set `order` on items you want pinned.
50
+ 3. **Grouping.** Contiguous root-level articles with the same `group` string render under a labelled sidebar section. Mixing groups breaks visual grouping.
51
+ 4. **URLs.** Don't set `path` unless you need to override the default slug. Livemark derives `path` from the filename plus leading/trailing slashes.
52
+ 5. **Images.** Relative paths in `image`, Markdown `![](...)`, and MDX `<img src>` resolve against the article file — keep assets co-located or under `docs/images/`.
53
+
54
+ ## Patching a file you can't touch
55
+
56
+ When a file already lives on disk (for example `README.md` that GitHub renders) and you don't want to pollute it with frontmatter, inject metadata via `patches` in `livemark.config.ts`:
57
+
58
+ ```ts
59
+ patches: [
60
+ {
61
+ file: "README.md",
62
+ article: { title: "Overview", icon: "sparkles", order: 0 },
63
+ },
64
+ ]
65
+ ```
66
+
67
+ The `file` field is exact-match on the collection-relative path. `content` cannot be patched — zod rejects at config load.
68
+
69
+ ## Blog posts
70
+
71
+ For a blog section:
72
+
73
+ ```yaml
74
+ ---
75
+ title: "Announcing v0.3"
76
+ date: 2026-04-20
77
+ author: Livemark Team
78
+ tags: [release, announcement]
79
+ image: ./images/v0-3.png
80
+ description: What's new in 0.3, in 400 words.
81
+ ---
82
+ ```
83
+
84
+ `date` is required for correct chronological sort. `tags` drive the `/<prefix>/tags/<tag>/` pages.
85
+
86
+ ## Verification
87
+
88
+ After authoring, run:
89
+
90
+ - `pnpm docs:build` — confirms the file prerenders without error.
91
+ - Grep built HTML (`.livemark/build/client/<path>/index.html`) to confirm title and metadata land as intended.
92
+
93
+ ## References
94
+
95
+ - Full frontmatter reference: `docs/markdown/frontmatter.md`.
96
+ - Schema source of truth: `website/models/article.ts`.
97
+ - Transform pipeline: `website/content-collections.ts`.