@betterstart/cli 0.1.3 → 0.1.5

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 (234) hide show
  1. package/README.md +133 -0
  2. package/dist/cli.d.ts +1 -9
  3. package/dist/cli.js +13585 -367
  4. package/dist/cli.js.map +1 -1
  5. package/dist/index.d.ts +24 -266
  6. package/dist/index.js +4 -11378
  7. package/dist/index.js.map +1 -1
  8. package/package.json +29 -42
  9. package/templates/schema.json +959 -0
  10. package/templates/tiptap/hooks/use-composed-ref.ts +43 -0
  11. package/templates/tiptap/hooks/use-cursor-visibility.ts +68 -0
  12. package/templates/tiptap/hooks/use-element-rect.ts +166 -0
  13. package/templates/tiptap/hooks/use-is-breakpoint.ts +32 -0
  14. package/templates/tiptap/hooks/use-menu-navigation.ts +182 -0
  15. package/templates/tiptap/hooks/use-scrolling.ts +64 -0
  16. package/templates/tiptap/hooks/use-throttled-callback.ts +146 -0
  17. package/templates/tiptap/hooks/use-tiptap-editor.ts +46 -0
  18. package/templates/tiptap/hooks/use-unmount.ts +21 -0
  19. package/templates/tiptap/hooks/use-window-size.ts +87 -0
  20. package/templates/tiptap/lib/tiptap-utils.ts +587 -0
  21. package/templates/tiptap/styles/_keyframe-animations.scss +91 -0
  22. package/templates/tiptap/styles/_variables.scss +296 -0
  23. package/templates/tiptap/tiptap-extension/node-background-extension.ts +138 -0
  24. package/templates/tiptap/tiptap-icons/align-center-icon.tsx +38 -0
  25. package/templates/tiptap/tiptap-icons/align-justify-icon.tsx +38 -0
  26. package/templates/tiptap/tiptap-icons/align-left-icon.tsx +38 -0
  27. package/templates/tiptap/tiptap-icons/align-right-icon.tsx +38 -0
  28. package/templates/tiptap/tiptap-icons/arrow-left-icon.tsx +24 -0
  29. package/templates/tiptap/tiptap-icons/ban-icon.tsx +26 -0
  30. package/templates/tiptap/tiptap-icons/blockquote-icon.tsx +44 -0
  31. package/templates/tiptap/tiptap-icons/bold-icon.tsx +26 -0
  32. package/templates/tiptap/tiptap-icons/chevron-down-icon.tsx +26 -0
  33. package/templates/tiptap/tiptap-icons/close-icon.tsx +24 -0
  34. package/templates/tiptap/tiptap-icons/code-block-icon.tsx +38 -0
  35. package/templates/tiptap/tiptap-icons/code2-icon.tsx +32 -0
  36. package/templates/tiptap/tiptap-icons/corner-down-left-icon.tsx +26 -0
  37. package/templates/tiptap/tiptap-icons/external-link-icon.tsx +28 -0
  38. package/templates/tiptap/tiptap-icons/heading-five-icon.tsx +28 -0
  39. package/templates/tiptap/tiptap-icons/heading-four-icon.tsx +28 -0
  40. package/templates/tiptap/tiptap-icons/heading-icon.tsx +24 -0
  41. package/templates/tiptap/tiptap-icons/heading-one-icon.tsx +28 -0
  42. package/templates/tiptap/tiptap-icons/heading-six-icon.tsx +30 -0
  43. package/templates/tiptap/tiptap-icons/heading-three-icon.tsx +36 -0
  44. package/templates/tiptap/tiptap-icons/heading-two-icon.tsx +28 -0
  45. package/templates/tiptap/tiptap-icons/highlighter-icon.tsx +26 -0
  46. package/templates/tiptap/tiptap-icons/image-plus-icon.tsx +26 -0
  47. package/templates/tiptap/tiptap-icons/italic-icon.tsx +24 -0
  48. package/templates/tiptap/tiptap-icons/link-icon.tsx +28 -0
  49. package/templates/tiptap/tiptap-icons/list-icon.tsx +56 -0
  50. package/templates/tiptap/tiptap-icons/list-ordered-icon.tsx +56 -0
  51. package/templates/tiptap/tiptap-icons/list-todo-icon.tsx +50 -0
  52. package/templates/tiptap/tiptap-icons/moon-star-icon.tsx +30 -0
  53. package/templates/tiptap/tiptap-icons/redo2-icon.tsx +26 -0
  54. package/templates/tiptap/tiptap-icons/strike-icon.tsx +28 -0
  55. package/templates/tiptap/tiptap-icons/subscript-icon.tsx +38 -0
  56. package/templates/tiptap/tiptap-icons/sun-icon.tsx +58 -0
  57. package/templates/tiptap/tiptap-icons/superscript-icon.tsx +38 -0
  58. package/templates/tiptap/tiptap-icons/trash-icon.tsx +26 -0
  59. package/templates/tiptap/tiptap-icons/underline-icon.tsx +26 -0
  60. package/templates/tiptap/tiptap-icons/undo2-icon.tsx +26 -0
  61. package/templates/tiptap/tiptap-node/blockquote-node/blockquote-node.scss +37 -0
  62. package/templates/tiptap/tiptap-node/code-block-node/code-block-node.scss +54 -0
  63. package/templates/tiptap/tiptap-node/heading-node/heading-node.scss +45 -0
  64. package/templates/tiptap/tiptap-node/horizontal-rule-node/horizontal-rule-node-extension.ts +10 -0
  65. package/templates/tiptap/tiptap-node/horizontal-rule-node/horizontal-rule-node.scss +25 -0
  66. package/templates/tiptap/tiptap-node/image-node/image-node.scss +35 -0
  67. package/templates/tiptap/tiptap-node/image-upload-node/image-upload-node-extension.ts +154 -0
  68. package/templates/tiptap/tiptap-node/image-upload-node/image-upload-node.scss +249 -0
  69. package/templates/tiptap/tiptap-node/image-upload-node/image-upload-node.tsx +522 -0
  70. package/templates/tiptap/tiptap-node/image-upload-node/index.tsx +1 -0
  71. package/templates/tiptap/tiptap-node/list-node/list-node.scss +208 -0
  72. package/templates/tiptap/tiptap-node/paragraph-node/paragraph-node.scss +273 -0
  73. package/templates/tiptap/tiptap-ui/blockquote-button/blockquote-button.tsx +104 -0
  74. package/templates/tiptap/tiptap-ui/blockquote-button/index.tsx +2 -0
  75. package/templates/tiptap/tiptap-ui/blockquote-button/use-blockquote.ts +252 -0
  76. package/templates/tiptap/tiptap-ui/code-block-button/code-block-button.tsx +106 -0
  77. package/templates/tiptap/tiptap-ui/code-block-button/index.tsx +2 -0
  78. package/templates/tiptap/tiptap-ui/code-block-button/use-code-block.ts +261 -0
  79. package/templates/tiptap/tiptap-ui/color-highlight-button/color-highlight-button.scss +49 -0
  80. package/templates/tiptap/tiptap-ui/color-highlight-button/color-highlight-button.tsx +153 -0
  81. package/templates/tiptap/tiptap-ui/color-highlight-button/index.tsx +2 -0
  82. package/templates/tiptap/tiptap-ui/color-highlight-button/use-color-highlight.ts +345 -0
  83. package/templates/tiptap/tiptap-ui/color-highlight-popover/color-highlight-popover.tsx +207 -0
  84. package/templates/tiptap/tiptap-ui/color-highlight-popover/index.tsx +1 -0
  85. package/templates/tiptap/tiptap-ui/heading-button/heading-button.tsx +107 -0
  86. package/templates/tiptap/tiptap-ui/heading-button/index.tsx +2 -0
  87. package/templates/tiptap/tiptap-ui/heading-button/use-heading.ts +314 -0
  88. package/templates/tiptap/tiptap-ui/heading-dropdown-menu/heading-dropdown-menu.tsx +131 -0
  89. package/templates/tiptap/tiptap-ui/heading-dropdown-menu/index.tsx +2 -0
  90. package/templates/tiptap/tiptap-ui/heading-dropdown-menu/use-heading-dropdown-menu.ts +130 -0
  91. package/templates/tiptap/tiptap-ui/image-upload-button/image-upload-button.tsx +114 -0
  92. package/templates/tiptap/tiptap-ui/image-upload-button/index.tsx +2 -0
  93. package/templates/tiptap/tiptap-ui/image-upload-button/use-image-upload.ts +192 -0
  94. package/templates/tiptap/tiptap-ui/link-popover/index.tsx +2 -0
  95. package/templates/tiptap/tiptap-ui/link-popover/link-popover.tsx +285 -0
  96. package/templates/tiptap/tiptap-ui/link-popover/use-link-popover.ts +286 -0
  97. package/templates/tiptap/tiptap-ui/list-button/index.tsx +2 -0
  98. package/templates/tiptap/tiptap-ui/list-button/list-button.tsx +108 -0
  99. package/templates/tiptap/tiptap-ui/list-button/use-list.ts +329 -0
  100. package/templates/tiptap/tiptap-ui/list-dropdown-menu/index.tsx +1 -0
  101. package/templates/tiptap/tiptap-ui/list-dropdown-menu/list-dropdown-menu.tsx +123 -0
  102. package/templates/tiptap/tiptap-ui/list-dropdown-menu/use-list-dropdown-menu.ts +203 -0
  103. package/templates/tiptap/tiptap-ui/mark-button/index.tsx +2 -0
  104. package/templates/tiptap/tiptap-ui/mark-button/mark-button.tsx +107 -0
  105. package/templates/tiptap/tiptap-ui/mark-button/use-mark.ts +206 -0
  106. package/templates/tiptap/tiptap-ui/text-align-button/index.tsx +2 -0
  107. package/templates/tiptap/tiptap-ui/text-align-button/text-align-button.tsx +118 -0
  108. package/templates/tiptap/tiptap-ui/text-align-button/use-text-align.ts +212 -0
  109. package/templates/tiptap/tiptap-ui/undo-redo-button/index.tsx +2 -0
  110. package/templates/tiptap/tiptap-ui/undo-redo-button/undo-redo-button.tsx +105 -0
  111. package/templates/tiptap/tiptap-ui/undo-redo-button/use-undo-redo.ts +173 -0
  112. package/templates/tiptap/tiptap-ui-primitive/badge/badge-colors.scss +395 -0
  113. package/templates/tiptap/tiptap-ui-primitive/badge/badge-group.scss +16 -0
  114. package/templates/tiptap/tiptap-ui-primitive/badge/badge.scss +99 -0
  115. package/templates/tiptap/tiptap-ui-primitive/badge/badge.tsx +46 -0
  116. package/templates/tiptap/tiptap-ui-primitive/badge/index.tsx +1 -0
  117. package/templates/tiptap/tiptap-ui-primitive/button/button-colors.scss +429 -0
  118. package/templates/tiptap/tiptap-ui-primitive/button/button-group.scss +22 -0
  119. package/templates/tiptap/tiptap-ui-primitive/button/button.scss +314 -0
  120. package/templates/tiptap/tiptap-ui-primitive/button/button.tsx +102 -0
  121. package/templates/tiptap/tiptap-ui-primitive/button/index.tsx +1 -0
  122. package/templates/tiptap/tiptap-ui-primitive/card/card.scss +77 -0
  123. package/templates/tiptap/tiptap-ui-primitive/card/card.tsx +59 -0
  124. package/templates/tiptap/tiptap-ui-primitive/card/index.tsx +1 -0
  125. package/templates/tiptap/tiptap-ui-primitive/dropdown-menu/dropdown-menu.scss +63 -0
  126. package/templates/tiptap/tiptap-ui-primitive/dropdown-menu/dropdown-menu.tsx +95 -0
  127. package/templates/tiptap/tiptap-ui-primitive/dropdown-menu/index.tsx +1 -0
  128. package/templates/tiptap/tiptap-ui-primitive/input/index.tsx +1 -0
  129. package/templates/tiptap/tiptap-ui-primitive/input/input.scss +45 -0
  130. package/templates/tiptap/tiptap-ui-primitive/input/input.tsx +18 -0
  131. package/templates/tiptap/tiptap-ui-primitive/popover/index.tsx +1 -0
  132. package/templates/tiptap/tiptap-ui-primitive/popover/popover.scss +63 -0
  133. package/templates/tiptap/tiptap-ui-primitive/popover/popover.tsx +33 -0
  134. package/templates/tiptap/tiptap-ui-primitive/separator/index.tsx +1 -0
  135. package/templates/tiptap/tiptap-ui-primitive/separator/separator.scss +23 -0
  136. package/templates/tiptap/tiptap-ui-primitive/separator/separator.tsx +33 -0
  137. package/templates/tiptap/tiptap-ui-primitive/spacer/index.tsx +1 -0
  138. package/templates/tiptap/tiptap-ui-primitive/spacer/spacer.tsx +21 -0
  139. package/templates/tiptap/tiptap-ui-primitive/toolbar/index.tsx +1 -0
  140. package/templates/tiptap/tiptap-ui-primitive/toolbar/toolbar.scss +98 -0
  141. package/templates/tiptap/tiptap-ui-primitive/toolbar/toolbar.tsx +113 -0
  142. package/templates/tiptap/tiptap-ui-primitive/tooltip/index.tsx +1 -0
  143. package/templates/tiptap/tiptap-ui-primitive/tooltip/tooltip.scss +43 -0
  144. package/templates/tiptap/tiptap-ui-primitive/tooltip/tooltip.tsx +223 -0
  145. package/templates/ui/accordion.tsx +52 -0
  146. package/templates/ui/alert-dialog.tsx +116 -0
  147. package/templates/ui/alert.tsx +48 -0
  148. package/templates/ui/aspect-ratio.tsx +7 -0
  149. package/templates/ui/avatar.tsx +46 -0
  150. package/templates/ui/badge.tsx +32 -0
  151. package/templates/ui/breadcrumb.tsx +98 -0
  152. package/templates/ui/button-group.tsx +77 -0
  153. package/templates/ui/button.tsx +48 -0
  154. package/templates/ui/calendar.tsx +176 -0
  155. package/templates/ui/card.tsx +54 -0
  156. package/templates/ui/carousel.tsx +234 -0
  157. package/templates/ui/chart.tsx +349 -0
  158. package/templates/ui/checkbox.tsx +27 -0
  159. package/templates/ui/collapsible.tsx +11 -0
  160. package/templates/ui/command.tsx +142 -0
  161. package/templates/ui/context-menu.tsx +188 -0
  162. package/templates/ui/curriculum-editor.tsx +601 -0
  163. package/templates/ui/date-picker.tsx +70 -0
  164. package/templates/ui/dialog.tsx +103 -0
  165. package/templates/ui/drawer.tsx +99 -0
  166. package/templates/ui/dropdown-menu.tsx +185 -0
  167. package/templates/ui/dynamic-list-field.tsx +95 -0
  168. package/templates/ui/empty.tsx +90 -0
  169. package/templates/ui/field.tsx +231 -0
  170. package/templates/ui/file-upload-example.tsx +113 -0
  171. package/templates/ui/form.tsx +172 -0
  172. package/templates/ui/hover-card.tsx +28 -0
  173. package/templates/ui/icon-picker.tsx +435 -0
  174. package/templates/ui/icons-data.ts +6 -0
  175. package/templates/ui/image-upload-field.tsx +360 -0
  176. package/templates/ui/input-group.tsx +160 -0
  177. package/templates/ui/input-otp.tsx +70 -0
  178. package/templates/ui/input.tsx +21 -0
  179. package/templates/ui/item.tsx +171 -0
  180. package/templates/ui/kbd.tsx +28 -0
  181. package/templates/ui/label.tsx +20 -0
  182. package/templates/ui/logo.tsx +113 -0
  183. package/templates/ui/markdown-editor.tsx +303 -0
  184. package/templates/ui/markdown-utils.ts +128 -0
  185. package/templates/ui/media-upload-field.tsx +255 -0
  186. package/templates/ui/menubar.tsx +230 -0
  187. package/templates/ui/navigation-menu.tsx +119 -0
  188. package/templates/ui/pagination.tsx +96 -0
  189. package/templates/ui/placeholder.tsx +25 -0
  190. package/templates/ui/popover.tsx +32 -0
  191. package/templates/ui/progress.tsx +24 -0
  192. package/templates/ui/radio-group.tsx +37 -0
  193. package/templates/ui/resizable.tsx +41 -0
  194. package/templates/ui/rich-text-editor.tsx +374 -0
  195. package/templates/ui/scroll-area.tsx +45 -0
  196. package/templates/ui/select.tsx +151 -0
  197. package/templates/ui/separator.tsx +25 -0
  198. package/templates/ui/sheet.tsx +120 -0
  199. package/templates/ui/sidebar.tsx +687 -0
  200. package/templates/ui/skeleton.tsx +7 -0
  201. package/templates/ui/slider.tsx +24 -0
  202. package/templates/ui/sonner.tsx +29 -0
  203. package/templates/ui/spinner.tsx +15 -0
  204. package/templates/ui/switch.tsx +28 -0
  205. package/templates/ui/table.tsx +93 -0
  206. package/templates/ui/tabs.tsx +54 -0
  207. package/templates/ui/textarea.tsx +20 -0
  208. package/templates/ui/toast.tsx +127 -0
  209. package/templates/ui/toggle-group.tsx +56 -0
  210. package/templates/ui/toggle.tsx +43 -0
  211. package/templates/ui/tooltip.tsx +31 -0
  212. package/templates/ui/use-mobile.tsx +19 -0
  213. package/templates/ui/video-upload-field.tsx +368 -0
  214. package/dist/chunk-EIH4RRIJ.js +0 -183
  215. package/dist/chunk-EIH4RRIJ.js.map +0 -1
  216. package/dist/chunk-NKRQYAS6.js +0 -260
  217. package/dist/chunk-NKRQYAS6.js.map +0 -1
  218. package/dist/chunk-QLVSHP7X.js +0 -235
  219. package/dist/chunk-QLVSHP7X.js.map +0 -1
  220. package/dist/chunk-WY6BC55D.js +0 -357
  221. package/dist/chunk-WY6BC55D.js.map +0 -1
  222. package/dist/config/index.d.ts +0 -93
  223. package/dist/config/index.js +0 -58
  224. package/dist/config/index.js.map +0 -1
  225. package/dist/core/index.d.ts +0 -415
  226. package/dist/core/index.js +0 -906
  227. package/dist/core/index.js.map +0 -1
  228. package/dist/import-resolver-BaZ-rzkH.d.ts +0 -123
  229. package/dist/logger-awLb347n.d.ts +0 -81
  230. package/dist/plugins/index.d.ts +0 -213
  231. package/dist/plugins/index.js +0 -365
  232. package/dist/plugins/index.js.map +0 -1
  233. package/dist/types-ByX_gl6y.d.ts +0 -232
  234. package/dist/types-eI549DEG.d.ts +0 -331
@@ -0,0 +1,959 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://betterstart.dev/schemas/schema.json",
4
+ "title": "BetterStart Schema Definition",
5
+ "description": "JSON Schema for validating custom schema files (courses.json, testimonials.json, instructors.json, events.json, etc.)",
6
+ "type": "object",
7
+ "required": ["name", "label", "fields"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "$schema": {
11
+ "type": "string",
12
+ "description": "JSON Schema reference (typically './schema.json')"
13
+ },
14
+ "name": {
15
+ "type": "string",
16
+ "description": "Unique identifier for the schema (e.g., 'courses', 'site-settings')",
17
+ "pattern": "^[a-z][a-zA-Z0-9-]*$"
18
+ },
19
+ "label": {
20
+ "type": "string",
21
+ "description": "Human-readable display name for the schema"
22
+ },
23
+ "description": {
24
+ "type": "string",
25
+ "description": "Brief description of what this schema represents"
26
+ },
27
+ "icon": {
28
+ "type": "string",
29
+ "description": "Icon name from the icon library (e.g., 'BookOpen', 'Package')"
30
+ },
31
+ "type": {
32
+ "type": "string",
33
+ "description": "Schema type: 'entity' for CRUD list (default), 'single' for singleton record (site settings, about page), 'github' for GitHub-synced content",
34
+ "enum": ["entity", "single", "github"]
35
+ },
36
+ "username": {
37
+ "type": "string",
38
+ "description": "GitHub username or organization for GitHub-type schemas"
39
+ },
40
+ "repos": {
41
+ "type": "array",
42
+ "description": "GitHub repository configurations for syncing content",
43
+ "items": {
44
+ "$ref": "#/$defs/repoConfig"
45
+ }
46
+ },
47
+ "fields": {
48
+ "type": "array",
49
+ "description": "Array of field definitions",
50
+ "items": {
51
+ "$ref": "#/$defs/field"
52
+ },
53
+ "minItems": 1
54
+ },
55
+ "columns": {
56
+ "type": "array",
57
+ "description": "Table column definitions for list views",
58
+ "items": {
59
+ "$ref": "#/$defs/column"
60
+ }
61
+ },
62
+ "actions": {
63
+ "$ref": "#/$defs/actions"
64
+ },
65
+ "search": {
66
+ "$ref": "#/$defs/search"
67
+ },
68
+ "filters": {
69
+ "$ref": "#/$defs/filters"
70
+ },
71
+ "autoCategorize": {
72
+ "$ref": "#/$defs/autoCategorize"
73
+ },
74
+ "autoSlugify": {
75
+ "$ref": "#/$defs/autoSlugify"
76
+ },
77
+ "githubSyncPage": {
78
+ "$ref": "#/$defs/githubSyncPage"
79
+ }
80
+ },
81
+ "$defs": {
82
+ "field": {
83
+ "type": "object",
84
+ "description": "A field definition",
85
+ "oneOf": [
86
+ { "$ref": "#/$defs/serialField" },
87
+ { "$ref": "#/$defs/stringField" },
88
+ { "$ref": "#/$defs/textField" },
89
+ { "$ref": "#/$defs/markdownField" },
90
+ { "$ref": "#/$defs/richtextField" },
91
+ { "$ref": "#/$defs/imageField" },
92
+ { "$ref": "#/$defs/dateField" },
93
+ { "$ref": "#/$defs/booleanField" },
94
+ { "$ref": "#/$defs/timestampField" },
95
+ { "$ref": "#/$defs/numberField" },
96
+ { "$ref": "#/$defs/decimalField" },
97
+ { "$ref": "#/$defs/selectField" },
98
+ { "$ref": "#/$defs/listField" },
99
+ { "$ref": "#/$defs/groupField" },
100
+ { "$ref": "#/$defs/tabsField" },
101
+ { "$ref": "#/$defs/relationshipField" },
102
+ { "$ref": "#/$defs/separatorField" },
103
+ { "$ref": "#/$defs/videoField" },
104
+ { "$ref": "#/$defs/mediaField" },
105
+ { "$ref": "#/$defs/githubRepoField" },
106
+ { "$ref": "#/$defs/githubBranchField" },
107
+ { "$ref": "#/$defs/githubDirectoryField" },
108
+ { "$ref": "#/$defs/githubChaptersField" },
109
+ { "$ref": "#/$defs/curriculumField" }
110
+ ]
111
+ },
112
+ "baseFieldProperties": {
113
+ "type": "object",
114
+ "properties": {
115
+ "name": {
116
+ "type": "string",
117
+ "description": "Field identifier (camelCase)",
118
+ "pattern": "^[a-zA-Z][a-zA-Z0-9]*$"
119
+ },
120
+ "label": {
121
+ "type": "string",
122
+ "description": "Human-readable field label"
123
+ },
124
+ "required": {
125
+ "type": "boolean",
126
+ "description": "Whether this field is required",
127
+ "default": false
128
+ },
129
+ "hint": {
130
+ "type": "string",
131
+ "description": "Helper text displayed below the field"
132
+ },
133
+ "showWhen": {
134
+ "$ref": "#/$defs/showWhenCondition"
135
+ },
136
+ "dependsOn": {
137
+ "$ref": "#/$defs/dependsOnCondition"
138
+ }
139
+ }
140
+ },
141
+ "dependsOnCondition": {
142
+ "type": "object",
143
+ "description": "For cascading fields - specifies which sibling field(s) this field depends on",
144
+ "additionalProperties": false,
145
+ "properties": {
146
+ "repo": {
147
+ "type": "string",
148
+ "description": "Name of the repo field for branch/directory selectors"
149
+ },
150
+ "branch": {
151
+ "type": "string",
152
+ "description": "Name of the branch field for directory selectors"
153
+ },
154
+ "directory": {
155
+ "type": "string",
156
+ "description": "Name of the directory field for chapters loader"
157
+ }
158
+ }
159
+ },
160
+ "showWhenCondition": {
161
+ "type": "object",
162
+ "description": "Conditional visibility based on sibling field value",
163
+ "required": ["field", "value"],
164
+ "additionalProperties": false,
165
+ "properties": {
166
+ "field": {
167
+ "type": "string",
168
+ "description": "Name of the sibling field to watch"
169
+ },
170
+ "value": {
171
+ "oneOf": [{ "type": "boolean" }, { "type": "string" }, { "type": "number" }],
172
+ "description": "Value that makes this field visible"
173
+ }
174
+ }
175
+ },
176
+ "serialField": {
177
+ "type": "object",
178
+ "description": "Auto-incrementing primary key field",
179
+ "required": ["name", "type"],
180
+ "additionalProperties": false,
181
+ "properties": {
182
+ "name": { "type": "string" },
183
+ "type": { "const": "serial" },
184
+ "primaryKey": {
185
+ "type": "boolean",
186
+ "description": "Whether this is the primary key",
187
+ "default": true
188
+ }
189
+ }
190
+ },
191
+ "stringField": {
192
+ "type": "object",
193
+ "description": "Single-line text input field",
194
+ "required": ["name", "type"],
195
+ "additionalProperties": false,
196
+ "properties": {
197
+ "name": { "type": "string" },
198
+ "type": { "const": "string" },
199
+ "label": { "type": "string" },
200
+ "required": { "type": "boolean" },
201
+ "length": {
202
+ "type": "integer",
203
+ "description": "Maximum character length",
204
+ "minimum": 1,
205
+ "maximum": 65535
206
+ },
207
+ "hint": { "type": "string" },
208
+ "placeholder": {
209
+ "type": "string",
210
+ "description": "Placeholder text displayed in the input field"
211
+ },
212
+ "default": { "type": "string" },
213
+ "hasIcon": {
214
+ "type": "boolean",
215
+ "description": "Whether this field has an associated icon picker"
216
+ },
217
+ "hidden": {
218
+ "type": "boolean",
219
+ "description": "Whether this field is hidden from the form UI but still exists in the database"
220
+ },
221
+ "showWhen": { "$ref": "#/$defs/showWhenCondition" }
222
+ }
223
+ },
224
+ "textField": {
225
+ "type": "object",
226
+ "description": "Multi-line text area field",
227
+ "required": ["name", "type"],
228
+ "additionalProperties": false,
229
+ "properties": {
230
+ "name": { "type": "string" },
231
+ "type": { "const": "text" },
232
+ "label": { "type": "string" },
233
+ "required": { "type": "boolean" },
234
+ "length": {
235
+ "type": "integer",
236
+ "description": "Maximum character length",
237
+ "minimum": 1
238
+ },
239
+ "hint": { "type": "string" },
240
+ "placeholder": {
241
+ "type": "string",
242
+ "description": "Placeholder text displayed in the text area"
243
+ },
244
+ "default": { "type": "string" },
245
+ "hidden": {
246
+ "type": "boolean",
247
+ "description": "Whether this field is hidden from the form UI but still exists in the database"
248
+ },
249
+ "showWhen": { "$ref": "#/$defs/showWhenCondition" }
250
+ }
251
+ },
252
+ "markdownField": {
253
+ "type": "object",
254
+ "description": "Rich text editor with markdown support",
255
+ "required": ["name", "type"],
256
+ "additionalProperties": false,
257
+ "properties": {
258
+ "name": { "type": "string" },
259
+ "type": { "const": "markdown" },
260
+ "label": { "type": "string" },
261
+ "required": { "type": "boolean" },
262
+ "hint": { "type": "string" },
263
+ "placeholder": {
264
+ "type": "string",
265
+ "description": "Placeholder text displayed in the markdown editor"
266
+ },
267
+ "hidden": {
268
+ "type": "boolean",
269
+ "description": "Whether this field is hidden from the form UI but still exists in the database"
270
+ },
271
+ "showWhen": { "$ref": "#/$defs/showWhenCondition" }
272
+ }
273
+ },
274
+ "richtextField": {
275
+ "type": "object",
276
+ "description": "WYSIWYG rich text editor with markdown storage",
277
+ "required": ["name", "type"],
278
+ "additionalProperties": false,
279
+ "properties": {
280
+ "name": { "type": "string" },
281
+ "type": { "const": "richtext" },
282
+ "label": { "type": "string" },
283
+ "required": { "type": "boolean" },
284
+ "hint": { "type": "string" },
285
+ "placeholder": {
286
+ "type": "string",
287
+ "description": "Placeholder text displayed in the rich text editor"
288
+ },
289
+ "hidden": {
290
+ "type": "boolean",
291
+ "description": "Whether this field is hidden from the form UI but still exists in the database"
292
+ },
293
+ "showWhen": { "$ref": "#/$defs/showWhenCondition" }
294
+ }
295
+ },
296
+ "imageField": {
297
+ "type": "object",
298
+ "description": "Image upload field",
299
+ "required": ["name", "type"],
300
+ "additionalProperties": false,
301
+ "properties": {
302
+ "name": { "type": "string" },
303
+ "type": { "const": "image" },
304
+ "label": { "type": "string" },
305
+ "required": { "type": "boolean" },
306
+ "length": {
307
+ "type": "integer",
308
+ "description": "Maximum URL length"
309
+ },
310
+ "hint": { "type": "string" },
311
+ "hidden": {
312
+ "type": "boolean",
313
+ "description": "Whether this field is hidden from the form UI but still exists in the database"
314
+ }
315
+ }
316
+ },
317
+ "dateField": {
318
+ "type": "object",
319
+ "description": "Date picker field",
320
+ "required": ["name", "type"],
321
+ "additionalProperties": false,
322
+ "properties": {
323
+ "name": { "type": "string" },
324
+ "type": { "const": "date" },
325
+ "label": { "type": "string" },
326
+ "required": { "type": "boolean" },
327
+ "default": { "type": "string" },
328
+ "hint": { "type": "string" },
329
+ "hidden": {
330
+ "type": "boolean",
331
+ "description": "Whether this field is hidden from the form UI but still exists in the database"
332
+ }
333
+ }
334
+ },
335
+ "booleanField": {
336
+ "type": "object",
337
+ "description": "Toggle/checkbox field",
338
+ "required": ["name", "type"],
339
+ "additionalProperties": false,
340
+ "properties": {
341
+ "name": { "type": "string" },
342
+ "type": { "const": "boolean" },
343
+ "label": { "type": "string" },
344
+ "required": { "type": "boolean" },
345
+ "default": { "type": "boolean" },
346
+ "hint": { "type": "string" },
347
+ "hidden": {
348
+ "type": "boolean",
349
+ "description": "Whether this field is hidden from the form UI but still exists in the database"
350
+ }
351
+ }
352
+ },
353
+ "timestampField": {
354
+ "type": "object",
355
+ "description": "Timestamp field (typically auto-generated)",
356
+ "required": ["name", "type"],
357
+ "additionalProperties": false,
358
+ "properties": {
359
+ "name": { "type": "string" },
360
+ "type": { "const": "timestamp" },
361
+ "label": { "type": "string" },
362
+ "required": { "type": "boolean" },
363
+ "hidden": {
364
+ "type": "boolean",
365
+ "description": "Whether this field is hidden from the form UI but still exists in the database"
366
+ }
367
+ }
368
+ },
369
+ "numberField": {
370
+ "type": "object",
371
+ "description": "Integer number input field",
372
+ "required": ["name", "type"],
373
+ "additionalProperties": false,
374
+ "properties": {
375
+ "name": { "type": "string" },
376
+ "type": { "const": "number" },
377
+ "label": { "type": "string" },
378
+ "required": { "type": "boolean" },
379
+ "default": { "type": "integer" },
380
+ "hint": { "type": "string" },
381
+ "placeholder": {
382
+ "type": "string",
383
+ "description": "Placeholder text displayed in the number input"
384
+ },
385
+ "min": { "type": "integer" },
386
+ "max": { "type": "integer" },
387
+ "hidden": {
388
+ "type": "boolean",
389
+ "description": "Whether this field is hidden from the form UI but still exists in the database"
390
+ }
391
+ }
392
+ },
393
+ "decimalField": {
394
+ "type": "object",
395
+ "description": "Decimal number field (for prices, percentages, etc.)",
396
+ "required": ["name", "type"],
397
+ "additionalProperties": false,
398
+ "properties": {
399
+ "name": { "type": "string" },
400
+ "type": { "const": "decimal" },
401
+ "label": { "type": "string" },
402
+ "required": { "type": "boolean" },
403
+ "format": {
404
+ "type": "string",
405
+ "description": "Display format",
406
+ "enum": ["currency", "percentage", "plain"]
407
+ },
408
+ "precision": {
409
+ "type": "integer",
410
+ "description": "Total number of digits",
411
+ "minimum": 1,
412
+ "maximum": 65
413
+ },
414
+ "scale": {
415
+ "type": "integer",
416
+ "description": "Number of decimal places",
417
+ "minimum": 0,
418
+ "maximum": 30
419
+ },
420
+ "hint": { "type": "string" },
421
+ "placeholder": {
422
+ "type": "string",
423
+ "description": "Placeholder text displayed in the decimal input"
424
+ },
425
+ "default": { "type": "number" },
426
+ "hidden": {
427
+ "type": "boolean",
428
+ "description": "Whether this field is hidden from the form UI but still exists in the database"
429
+ }
430
+ }
431
+ },
432
+ "selectField": {
433
+ "type": "object",
434
+ "description": "Dropdown select field",
435
+ "required": ["name", "type", "options"],
436
+ "additionalProperties": false,
437
+ "properties": {
438
+ "name": { "type": "string" },
439
+ "type": { "const": "select" },
440
+ "label": { "type": "string" },
441
+ "required": { "type": "boolean" },
442
+ "hint": { "type": "string" },
443
+ "options": {
444
+ "type": "array",
445
+ "description": "Available options for the select",
446
+ "items": {
447
+ "type": "object",
448
+ "required": ["label", "value"],
449
+ "additionalProperties": false,
450
+ "properties": {
451
+ "label": {
452
+ "type": "string",
453
+ "description": "Display label"
454
+ },
455
+ "value": {
456
+ "type": "string",
457
+ "description": "Value stored in database"
458
+ }
459
+ }
460
+ },
461
+ "minItems": 1
462
+ },
463
+ "default": { "type": "string" },
464
+ "hidden": {
465
+ "type": "boolean",
466
+ "description": "Whether this field is hidden from the form UI but still exists in the database"
467
+ }
468
+ }
469
+ },
470
+ "listField": {
471
+ "type": "object",
472
+ "description": "Repeatable list of items with nested fields",
473
+ "required": ["name", "type"],
474
+ "additionalProperties": false,
475
+ "properties": {
476
+ "name": { "type": "string" },
477
+ "type": { "const": "list" },
478
+ "label": { "type": "string" },
479
+ "required": { "type": "boolean" },
480
+ "maxItems": {
481
+ "type": "integer",
482
+ "description": "Maximum number of items allowed",
483
+ "minimum": 1
484
+ },
485
+ "length": {
486
+ "type": "integer",
487
+ "description": "Maximum length for simple list items"
488
+ },
489
+ "hint": { "type": "string" },
490
+ "hidden": {
491
+ "type": "boolean",
492
+ "description": "Whether this field is hidden from the form UI but still exists in the database"
493
+ },
494
+ "showWhen": { "$ref": "#/$defs/showWhenCondition" },
495
+ "fields": {
496
+ "type": "array",
497
+ "description": "Nested field definitions for complex list items",
498
+ "items": {
499
+ "$ref": "#/$defs/field"
500
+ }
501
+ },
502
+ "items": {
503
+ "description": "Single field definition for simple list items",
504
+ "$ref": "#/$defs/simpleListItem"
505
+ }
506
+ }
507
+ },
508
+ "simpleListItem": {
509
+ "type": "object",
510
+ "description": "Simple list item definition",
511
+ "required": ["name", "type"],
512
+ "additionalProperties": false,
513
+ "properties": {
514
+ "name": { "type": "string" },
515
+ "type": { "type": "string" },
516
+ "label": { "type": "string" },
517
+ "required": { "type": "boolean" },
518
+ "length": { "type": "integer" }
519
+ }
520
+ },
521
+ "groupField": {
522
+ "type": "object",
523
+ "description": "Group of fields displayed together",
524
+ "required": ["name", "type", "fields"],
525
+ "additionalProperties": false,
526
+ "properties": {
527
+ "name": { "type": "string" },
528
+ "type": { "const": "group" },
529
+ "label": { "type": "string" },
530
+ "columns": {
531
+ "type": "integer",
532
+ "description": "Number of columns for layout",
533
+ "minimum": 1,
534
+ "maximum": 4
535
+ },
536
+ "fields": {
537
+ "type": "array",
538
+ "description": "Nested field definitions",
539
+ "items": {
540
+ "$ref": "#/$defs/field"
541
+ },
542
+ "minItems": 1
543
+ }
544
+ }
545
+ },
546
+ "tabsField": {
547
+ "type": "object",
548
+ "description": "Tabbed interface for organizing fields",
549
+ "required": ["name", "type", "tabs"],
550
+ "additionalProperties": false,
551
+ "properties": {
552
+ "name": { "type": "string" },
553
+ "type": { "const": "tabs" },
554
+ "tabs": {
555
+ "type": "array",
556
+ "description": "Tab definitions",
557
+ "items": {
558
+ "$ref": "#/$defs/tab"
559
+ },
560
+ "minItems": 1
561
+ }
562
+ }
563
+ },
564
+ "relationshipField": {
565
+ "type": "object",
566
+ "description": "Relationship field linking to another schema/entity",
567
+ "required": ["name", "type", "relationship"],
568
+ "additionalProperties": false,
569
+ "properties": {
570
+ "name": { "type": "string" },
571
+ "type": { "const": "relationship" },
572
+ "relationship": {
573
+ "type": "string",
574
+ "description": "Name of the related schema/entity (e.g., 'instructors', 'courses')"
575
+ },
576
+ "label": { "type": "string" },
577
+ "required": { "type": "boolean" },
578
+ "hint": { "type": "string" },
579
+ "multiple": {
580
+ "type": "boolean",
581
+ "description": "Whether multiple items can be selected",
582
+ "default": false
583
+ },
584
+ "hidden": {
585
+ "type": "boolean",
586
+ "description": "Whether this field is hidden from the form UI but still exists in the database"
587
+ },
588
+ "showWhen": { "$ref": "#/$defs/showWhenCondition" }
589
+ }
590
+ },
591
+ "separatorField": {
592
+ "type": "object",
593
+ "description": "Visual separator between form fields",
594
+ "required": ["type"],
595
+ "additionalProperties": false,
596
+ "properties": {
597
+ "name": { "type": "string" },
598
+ "type": { "const": "separator" },
599
+ "label": {
600
+ "type": "string",
601
+ "description": "Optional label to display with the separator"
602
+ }
603
+ }
604
+ },
605
+ "videoField": {
606
+ "type": "object",
607
+ "description": "Video upload field",
608
+ "required": ["name", "type"],
609
+ "additionalProperties": false,
610
+ "properties": {
611
+ "name": { "type": "string" },
612
+ "type": { "const": "video" },
613
+ "label": { "type": "string" },
614
+ "required": { "type": "boolean" },
615
+ "hint": { "type": "string" },
616
+ "maxSizeInMB": {
617
+ "type": "integer",
618
+ "description": "Maximum file size in megabytes",
619
+ "default": 100
620
+ },
621
+ "hidden": {
622
+ "type": "boolean",
623
+ "description": "Whether this field is hidden from the form UI but still exists in the database"
624
+ }
625
+ }
626
+ },
627
+ "mediaField": {
628
+ "type": "object",
629
+ "description": "Media upload field supporting both images and videos",
630
+ "required": ["name", "type"],
631
+ "additionalProperties": false,
632
+ "properties": {
633
+ "name": { "type": "string" },
634
+ "type": { "const": "media" },
635
+ "label": { "type": "string" },
636
+ "required": { "type": "boolean" },
637
+ "hint": { "type": "string" },
638
+ "maxSizeInMB": {
639
+ "type": "integer",
640
+ "description": "Maximum file size in megabytes",
641
+ "default": 100
642
+ },
643
+ "hidden": {
644
+ "type": "boolean",
645
+ "description": "Whether this field is hidden from the form UI but still exists in the database"
646
+ }
647
+ }
648
+ },
649
+ "githubRepoField": {
650
+ "type": "object",
651
+ "description": "GitHub repository selection combobox field",
652
+ "required": ["name", "type"],
653
+ "additionalProperties": false,
654
+ "properties": {
655
+ "name": { "type": "string" },
656
+ "type": { "const": "github-repo" },
657
+ "label": { "type": "string" },
658
+ "required": { "type": "boolean" },
659
+ "hint": { "type": "string" },
660
+ "showWhen": { "$ref": "#/$defs/showWhenCondition" }
661
+ }
662
+ },
663
+ "githubBranchField": {
664
+ "type": "object",
665
+ "description": "GitHub branch selection combobox field (depends on a repo field)",
666
+ "required": ["name", "type", "dependsOn"],
667
+ "additionalProperties": false,
668
+ "properties": {
669
+ "name": { "type": "string" },
670
+ "type": { "const": "github-branch" },
671
+ "label": { "type": "string" },
672
+ "required": { "type": "boolean" },
673
+ "hint": { "type": "string" },
674
+ "showWhen": { "$ref": "#/$defs/showWhenCondition" },
675
+ "dependsOn": { "$ref": "#/$defs/dependsOnCondition" }
676
+ }
677
+ },
678
+ "githubDirectoryField": {
679
+ "type": "object",
680
+ "description": "GitHub directory selection combobox field (depends on repo and branch fields)",
681
+ "required": ["name", "type", "dependsOn"],
682
+ "additionalProperties": false,
683
+ "properties": {
684
+ "name": { "type": "string" },
685
+ "type": { "const": "github-directory" },
686
+ "label": { "type": "string" },
687
+ "required": { "type": "boolean" },
688
+ "hint": { "type": "string" },
689
+ "showWhen": { "$ref": "#/$defs/showWhenCondition" },
690
+ "dependsOn": { "$ref": "#/$defs/dependsOnCondition" }
691
+ }
692
+ },
693
+ "githubChaptersField": {
694
+ "type": "object",
695
+ "description": "GitHub chapters loader field - loads markdown files from a directory as chapters",
696
+ "required": ["name", "type", "dependsOn", "fields"],
697
+ "additionalProperties": false,
698
+ "properties": {
699
+ "name": { "type": "string" },
700
+ "type": { "const": "github-chapters" },
701
+ "label": { "type": "string" },
702
+ "required": { "type": "boolean" },
703
+ "hint": { "type": "string" },
704
+ "showWhen": { "$ref": "#/$defs/showWhenCondition" },
705
+ "dependsOn": { "$ref": "#/$defs/dependsOnCondition" },
706
+ "fields": {
707
+ "type": "array",
708
+ "items": { "$ref": "#/$defs/field" },
709
+ "description": "Fields for each chapter (title, slug, description)"
710
+ }
711
+ }
712
+ },
713
+ "curriculumField": {
714
+ "type": "object",
715
+ "description": "Curriculum editor field with sequential or weekly mode support",
716
+ "required": ["name", "type"],
717
+ "additionalProperties": false,
718
+ "properties": {
719
+ "name": { "type": "string" },
720
+ "type": { "const": "curriculum" },
721
+ "label": { "type": "string" },
722
+ "required": { "type": "boolean" },
723
+ "hint": { "type": "string" },
724
+ "hidden": {
725
+ "type": "boolean",
726
+ "description": "Whether this field is hidden from the form UI but still exists in the database"
727
+ }
728
+ }
729
+ },
730
+ "tab": {
731
+ "type": "object",
732
+ "description": "A single tab containing fields",
733
+ "required": ["name", "label", "fields"],
734
+ "additionalProperties": false,
735
+ "properties": {
736
+ "name": {
737
+ "type": "string",
738
+ "description": "Tab identifier"
739
+ },
740
+ "label": {
741
+ "type": "string",
742
+ "description": "Tab display label"
743
+ },
744
+ "fields": {
745
+ "type": "array",
746
+ "description": "Fields within this tab",
747
+ "items": {
748
+ "$ref": "#/$defs/field"
749
+ },
750
+ "minItems": 1
751
+ }
752
+ }
753
+ },
754
+ "column": {
755
+ "type": "object",
756
+ "description": "Table column definition for list views",
757
+ "required": ["accessorKey", "header"],
758
+ "additionalProperties": false,
759
+ "properties": {
760
+ "accessorKey": {
761
+ "type": "string",
762
+ "description": "Field name to access data from"
763
+ },
764
+ "header": {
765
+ "type": "string",
766
+ "description": "Column header text"
767
+ },
768
+ "type": {
769
+ "type": "string",
770
+ "description": "Column display type",
771
+ "enum": ["image", "text", "badge", "date", "number", "link"]
772
+ },
773
+ "sortable": {
774
+ "type": "boolean",
775
+ "description": "Whether the column is sortable",
776
+ "default": false
777
+ },
778
+ "format": {
779
+ "type": "string",
780
+ "description": "Display format (e.g., 'currency' for numbers)",
781
+ "enum": ["currency", "percentage"]
782
+ }
783
+ }
784
+ },
785
+ "actions": {
786
+ "type": "object",
787
+ "description": "CRUD action configuration",
788
+ "additionalProperties": false,
789
+ "properties": {
790
+ "draft": {
791
+ "type": "boolean",
792
+ "description": "Enable draft/publish workflow",
793
+ "default": false
794
+ },
795
+ "create": {
796
+ "type": "boolean",
797
+ "description": "Enable create action",
798
+ "default": true
799
+ },
800
+ "edit": {
801
+ "type": "boolean",
802
+ "description": "Enable edit action",
803
+ "default": true
804
+ },
805
+ "delete": {
806
+ "type": "boolean",
807
+ "description": "Enable delete action",
808
+ "default": true
809
+ }
810
+ }
811
+ },
812
+ "search": {
813
+ "type": "object",
814
+ "description": "Backend search configuration for admin tables",
815
+ "additionalProperties": false,
816
+ "required": ["fields"],
817
+ "properties": {
818
+ "fields": {
819
+ "type": "array",
820
+ "description": "Array of field names to search across (should be text-type columns like string, text, varchar)",
821
+ "items": {
822
+ "type": "string",
823
+ "description": "Field name to include in search"
824
+ },
825
+ "minItems": 1
826
+ }
827
+ }
828
+ },
829
+ "filters": {
830
+ "type": "array",
831
+ "description": "Filter configuration for admin tables",
832
+ "items": {
833
+ "$ref": "#/$defs/filter"
834
+ }
835
+ },
836
+ "filter": {
837
+ "type": "object",
838
+ "description": "Filter definition for admin tables",
839
+ "required": ["field", "label"],
840
+ "additionalProperties": false,
841
+ "properties": {
842
+ "field": {
843
+ "type": "string",
844
+ "description": "Field name to filter by"
845
+ },
846
+ "label": {
847
+ "type": "string",
848
+ "description": "Label for the filter dropdown"
849
+ },
850
+ "type": {
851
+ "type": "string",
852
+ "description": "Filter type",
853
+ "enum": ["select"],
854
+ "default": "select"
855
+ }
856
+ }
857
+ },
858
+ "repoConfig": {
859
+ "type": "object",
860
+ "description": "GitHub repository configuration for syncing content",
861
+ "required": ["path", "branch"],
862
+ "additionalProperties": false,
863
+ "properties": {
864
+ "path": {
865
+ "type": "string",
866
+ "description": "GitHub repository path (e.g., 'owner/repo')"
867
+ },
868
+ "branch": {
869
+ "type": "string",
870
+ "description": "Git branch to sync from"
871
+ },
872
+ "basePath": {
873
+ "type": "string",
874
+ "description": "Base path within the repository to sync files from"
875
+ }
876
+ }
877
+ },
878
+ "autoCategorize": {
879
+ "type": "object",
880
+ "description": "Auto-categorization configuration for GitHub-synced schemas",
881
+ "additionalProperties": false,
882
+ "properties": {
883
+ "enabled": {
884
+ "type": "boolean",
885
+ "description": "Enable automatic categorization during GitHub sync",
886
+ "default": true
887
+ },
888
+ "useRepoName": {
889
+ "type": "boolean",
890
+ "description": "Automatically create/assign category based on repository name",
891
+ "default": true
892
+ },
893
+ "keywords": {
894
+ "type": "array",
895
+ "description": "Keyword-based categorization rules",
896
+ "items": {
897
+ "$ref": "#/$defs/categoryKeyword"
898
+ }
899
+ }
900
+ }
901
+ },
902
+ "categoryKeyword": {
903
+ "type": "object",
904
+ "description": "Keyword rule for auto-categorization",
905
+ "required": ["category", "patterns"],
906
+ "additionalProperties": false,
907
+ "properties": {
908
+ "category": {
909
+ "type": "string",
910
+ "description": "Category name to assign when patterns match"
911
+ },
912
+ "patterns": {
913
+ "type": "array",
914
+ "description": "Array of keywords/patterns to match against title and content",
915
+ "items": {
916
+ "type": "string"
917
+ },
918
+ "minItems": 1
919
+ }
920
+ }
921
+ },
922
+ "autoSlugify": {
923
+ "type": "object",
924
+ "description": "Auto-slugification configuration for generating URL-friendly slugs from fields",
925
+ "additionalProperties": false,
926
+ "properties": {
927
+ "enabled": {
928
+ "type": "boolean",
929
+ "description": "Enable automatic slug generation",
930
+ "default": true
931
+ },
932
+ "sourceField": {
933
+ "type": "string",
934
+ "description": "Field to use as source for slug generation (e.g., 'name', 'title')"
935
+ },
936
+ "targetField": {
937
+ "type": "string",
938
+ "description": "Field to store the generated slug (typically 'slug')"
939
+ }
940
+ }
941
+ },
942
+ "githubSyncPage": {
943
+ "type": "object",
944
+ "description": "GitHub sync page configuration for displaying sync status and controls",
945
+ "additionalProperties": false,
946
+ "properties": {
947
+ "enabled": {
948
+ "type": "boolean",
949
+ "description": "Enable GitHub sync page",
950
+ "default": false
951
+ },
952
+ "route": {
953
+ "type": "string",
954
+ "description": "Route path for the sync page (e.g., 'github-sync')"
955
+ }
956
+ }
957
+ }
958
+ }
959
+ }