@jahia/agentic 0.2.0 → 0.4.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 (238) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +28 -0
  3. package/dist/claude/.claude/agents/cnd-child-nodes.md +74 -0
  4. package/dist/claude/.claude/agents/cnd-jahia-mixins.md +113 -0
  5. package/dist/claude/.claude/agents/cnd-numbers-dates.md +61 -0
  6. package/dist/claude/.claude/agents/cnd-string-selectors.md +94 -0
  7. package/dist/claude/.claude/agents/jahia-cnd-author.md +130 -0
  8. package/dist/claude/.claude/agents/jahia-dev-worker.md +264 -0
  9. package/dist/claude/.claude/agents/jahia-reviewer.md +105 -0
  10. package/dist/claude/.claude/rules/jahia.md +15 -6
  11. package/dist/claude/.claude/skills/jahia/SKILL.md +23 -11
  12. package/dist/claude/.claude/skills/jahia-content/SKILL.md +102 -84
  13. package/dist/claude/.claude/skills/jahia-content-create-content/SKILL.md +255 -280
  14. package/dist/claude/.claude/skills/jahia-content-explore-structure/SKILL.md +187 -96
  15. package/dist/claude/.claude/skills/jahia-content-media-upload/SKILL.md +197 -0
  16. package/dist/claude/.claude/skills/jahia-content-move-content/SKILL.md +160 -165
  17. package/dist/claude/.claude/skills/jahia-content-organize/SKILL.md +209 -0
  18. package/dist/claude/.claude/skills/jahia-content-publish/SKILL.md +181 -0
  19. package/dist/claude/.claude/skills/jahia-content-query-content/SKILL.md +122 -92
  20. package/dist/claude/.claude/skills/jahia-content-translate-content/SKILL.md +154 -225
  21. package/dist/claude/.claude/skills/jahia-dev-accessibility/SKILL.md +3 -3
  22. package/dist/claude/.claude/skills/jahia-dev-build-component/SKILL.md +10 -7
  23. package/dist/claude/.claude/skills/jahia-dev-create-page-template/SKILL.md +59 -21
  24. package/dist/claude/.claude/skills/jahia-dev-create-template-set/SKILL.md +20 -47
  25. package/dist/claude/.claude/skills/jahia-dev-create-view/SKILL.md +3 -3
  26. package/dist/claude/.claude/skills/jahia-dev-cypress/SKILL.md +150 -330
  27. package/dist/claude/.claude/skills/jahia-dev-define-content-type/SKILL.md +43 -486
  28. package/dist/claude/.claude/skills/jahia-dev-define-content-type/references/modeling-decisions.md +52 -0
  29. package/dist/claude/.claude/skills/jahia-dev-query-content/SKILL.md +93 -296
  30. package/dist/claude/.claude/skills/jahia-dev-review-cnd/SKILL.md +79 -0
  31. package/dist/claude/.claude/skills/jahia-dev-review-cnd/scripts/check-cnd.d.mts +13 -0
  32. package/dist/claude/.claude/skills/jahia-dev-review-cnd/scripts/check-cnd.mjs +198 -0
  33. package/dist/claude/.claude/skills/jahia-dev-site-review/SKILL.md +70 -0
  34. package/dist/claude/.claude/skills/jahia-dev-site-review/scripts/review-pages.mjs +85 -0
  35. package/dist/claude/.claude/skills/jahia-dev-start-local/SKILL.md +18 -26
  36. package/dist/claude/.claude/skills/jahia-jcr-sql2/SKILL.md +258 -0
  37. package/dist/claude/.claude/skills/jahia-orchestrate/SKILL.md +148 -0
  38. package/dist/claude/.claude/skills/jahia-orchestrate/scripts/verify-pages.mjs +59 -0
  39. package/dist/claude/CLAUDE.md +16 -13
  40. package/dist/codex/.agents/skills/jahia/SKILL.md +23 -11
  41. package/dist/codex/.agents/skills/jahia-content/SKILL.md +102 -84
  42. package/dist/codex/.agents/skills/jahia-content-create-content/SKILL.md +255 -280
  43. package/dist/codex/.agents/skills/jahia-content-explore-structure/SKILL.md +187 -96
  44. package/dist/codex/.agents/skills/jahia-content-media-upload/SKILL.md +197 -0
  45. package/dist/codex/.agents/skills/jahia-content-move-content/SKILL.md +160 -165
  46. package/dist/codex/.agents/skills/jahia-content-organize/SKILL.md +209 -0
  47. package/dist/codex/.agents/skills/jahia-content-publish/SKILL.md +181 -0
  48. package/dist/codex/.agents/skills/jahia-content-query-content/SKILL.md +122 -92
  49. package/dist/codex/.agents/skills/jahia-content-translate-content/SKILL.md +154 -225
  50. package/dist/codex/.agents/skills/jahia-dev-accessibility/SKILL.md +3 -3
  51. package/dist/codex/.agents/skills/jahia-dev-build-component/SKILL.md +10 -7
  52. package/dist/codex/.agents/skills/jahia-dev-create-page-template/SKILL.md +59 -21
  53. package/dist/codex/.agents/skills/jahia-dev-create-template-set/SKILL.md +20 -47
  54. package/dist/codex/.agents/skills/jahia-dev-create-view/SKILL.md +3 -3
  55. package/dist/codex/.agents/skills/jahia-dev-cypress/SKILL.md +150 -330
  56. package/dist/codex/.agents/skills/jahia-dev-define-content-type/SKILL.md +43 -486
  57. package/dist/codex/.agents/skills/jahia-dev-define-content-type/references/modeling-decisions.md +52 -0
  58. package/dist/codex/.agents/skills/jahia-dev-query-content/SKILL.md +93 -296
  59. package/dist/codex/.agents/skills/jahia-dev-review-cnd/SKILL.md +79 -0
  60. package/dist/codex/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.d.mts +13 -0
  61. package/dist/codex/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.mjs +198 -0
  62. package/dist/codex/.agents/skills/jahia-dev-site-review/SKILL.md +70 -0
  63. package/dist/codex/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +85 -0
  64. package/dist/codex/.agents/skills/jahia-dev-start-local/SKILL.md +18 -26
  65. package/dist/codex/.agents/skills/jahia-jcr-sql2/SKILL.md +258 -0
  66. package/dist/codex/.agents/skills/jahia-orchestrate/SKILL.md +148 -0
  67. package/dist/codex/.agents/skills/jahia-orchestrate/scripts/verify-pages.mjs +59 -0
  68. package/dist/codex/.codex/agents/cnd-child-nodes.toml +3 -0
  69. package/dist/codex/.codex/agents/cnd-jahia-mixins.toml +3 -0
  70. package/dist/codex/.codex/agents/cnd-numbers-dates.toml +3 -0
  71. package/dist/codex/.codex/agents/cnd-string-selectors.toml +3 -0
  72. package/dist/codex/.codex/agents/jahia-cnd-author.toml +3 -0
  73. package/dist/codex/.codex/agents/jahia-dev-worker.toml +3 -0
  74. package/dist/codex/.codex/agents/jahia-reviewer.toml +3 -0
  75. package/dist/codex/AGENTS.md +17 -10
  76. package/dist/copilot/.agents/skills/jahia/SKILL.md +23 -11
  77. package/dist/copilot/.agents/skills/jahia-content/SKILL.md +102 -84
  78. package/dist/copilot/.agents/skills/jahia-content-create-content/SKILL.md +255 -280
  79. package/dist/copilot/.agents/skills/jahia-content-explore-structure/SKILL.md +187 -96
  80. package/dist/copilot/.agents/skills/jahia-content-media-upload/SKILL.md +197 -0
  81. package/dist/copilot/.agents/skills/jahia-content-move-content/SKILL.md +160 -165
  82. package/dist/copilot/.agents/skills/jahia-content-organize/SKILL.md +209 -0
  83. package/dist/copilot/.agents/skills/jahia-content-publish/SKILL.md +181 -0
  84. package/dist/copilot/.agents/skills/jahia-content-query-content/SKILL.md +122 -92
  85. package/dist/copilot/.agents/skills/jahia-content-translate-content/SKILL.md +154 -225
  86. package/dist/copilot/.agents/skills/jahia-dev-accessibility/SKILL.md +3 -3
  87. package/dist/copilot/.agents/skills/jahia-dev-build-component/SKILL.md +10 -7
  88. package/dist/copilot/.agents/skills/jahia-dev-create-page-template/SKILL.md +59 -21
  89. package/dist/copilot/.agents/skills/jahia-dev-create-template-set/SKILL.md +20 -47
  90. package/dist/copilot/.agents/skills/jahia-dev-create-view/SKILL.md +3 -3
  91. package/dist/copilot/.agents/skills/jahia-dev-cypress/SKILL.md +150 -330
  92. package/dist/copilot/.agents/skills/jahia-dev-define-content-type/SKILL.md +43 -486
  93. package/dist/copilot/.agents/skills/jahia-dev-define-content-type/references/modeling-decisions.md +52 -0
  94. package/dist/copilot/.agents/skills/jahia-dev-query-content/SKILL.md +93 -296
  95. package/dist/copilot/.agents/skills/jahia-dev-review-cnd/SKILL.md +79 -0
  96. package/dist/copilot/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.d.mts +13 -0
  97. package/dist/copilot/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.mjs +198 -0
  98. package/dist/copilot/.agents/skills/jahia-dev-site-review/SKILL.md +70 -0
  99. package/dist/copilot/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +85 -0
  100. package/dist/copilot/.agents/skills/jahia-dev-start-local/SKILL.md +18 -26
  101. package/dist/copilot/.agents/skills/jahia-jcr-sql2/SKILL.md +258 -0
  102. package/dist/copilot/.agents/skills/jahia-orchestrate/SKILL.md +148 -0
  103. package/dist/copilot/.agents/skills/jahia-orchestrate/scripts/verify-pages.mjs +59 -0
  104. package/dist/copilot/AGENTS.md +17 -10
  105. package/dist/cursor/.agents/skills/jahia/SKILL.md +23 -11
  106. package/dist/cursor/.agents/skills/jahia-content/SKILL.md +102 -84
  107. package/dist/cursor/.agents/skills/jahia-content-create-content/SKILL.md +255 -280
  108. package/dist/cursor/.agents/skills/jahia-content-explore-structure/SKILL.md +187 -96
  109. package/dist/cursor/.agents/skills/jahia-content-media-upload/SKILL.md +197 -0
  110. package/dist/cursor/.agents/skills/jahia-content-move-content/SKILL.md +160 -165
  111. package/dist/cursor/.agents/skills/jahia-content-organize/SKILL.md +209 -0
  112. package/dist/cursor/.agents/skills/jahia-content-publish/SKILL.md +181 -0
  113. package/dist/cursor/.agents/skills/jahia-content-query-content/SKILL.md +122 -92
  114. package/dist/cursor/.agents/skills/jahia-content-translate-content/SKILL.md +154 -225
  115. package/dist/cursor/.agents/skills/jahia-dev-accessibility/SKILL.md +3 -3
  116. package/dist/cursor/.agents/skills/jahia-dev-build-component/SKILL.md +10 -7
  117. package/dist/cursor/.agents/skills/jahia-dev-create-page-template/SKILL.md +59 -21
  118. package/dist/cursor/.agents/skills/jahia-dev-create-template-set/SKILL.md +20 -47
  119. package/dist/cursor/.agents/skills/jahia-dev-create-view/SKILL.md +3 -3
  120. package/dist/cursor/.agents/skills/jahia-dev-cypress/SKILL.md +150 -330
  121. package/dist/cursor/.agents/skills/jahia-dev-define-content-type/SKILL.md +43 -486
  122. package/dist/cursor/.agents/skills/jahia-dev-define-content-type/references/modeling-decisions.md +52 -0
  123. package/dist/cursor/.agents/skills/jahia-dev-query-content/SKILL.md +93 -296
  124. package/dist/cursor/.agents/skills/jahia-dev-review-cnd/SKILL.md +79 -0
  125. package/dist/cursor/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.d.mts +13 -0
  126. package/dist/cursor/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.mjs +198 -0
  127. package/dist/cursor/.agents/skills/jahia-dev-site-review/SKILL.md +70 -0
  128. package/dist/cursor/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +85 -0
  129. package/dist/cursor/.agents/skills/jahia-dev-start-local/SKILL.md +18 -26
  130. package/dist/cursor/.agents/skills/jahia-jcr-sql2/SKILL.md +258 -0
  131. package/dist/cursor/.agents/skills/jahia-orchestrate/SKILL.md +148 -0
  132. package/dist/cursor/.agents/skills/jahia-orchestrate/scripts/verify-pages.mjs +59 -0
  133. package/dist/cursor/.cursor/agents/cnd-child-nodes.md +74 -0
  134. package/dist/cursor/.cursor/agents/cnd-jahia-mixins.md +113 -0
  135. package/dist/cursor/.cursor/agents/cnd-numbers-dates.md +61 -0
  136. package/dist/cursor/.cursor/agents/cnd-string-selectors.md +94 -0
  137. package/dist/cursor/.cursor/agents/jahia-cnd-author.md +130 -0
  138. package/dist/cursor/.cursor/agents/jahia-dev-worker.md +264 -0
  139. package/dist/cursor/.cursor/agents/jahia-reviewer.md +105 -0
  140. package/dist/cursor/.cursor/rules/jahia.mdc +15 -6
  141. package/dist/gemini/.agents/skills/jahia/SKILL.md +23 -11
  142. package/dist/gemini/.agents/skills/jahia-content/SKILL.md +102 -84
  143. package/dist/gemini/.agents/skills/jahia-content-create-content/SKILL.md +255 -280
  144. package/dist/gemini/.agents/skills/jahia-content-explore-structure/SKILL.md +187 -96
  145. package/dist/gemini/.agents/skills/jahia-content-media-upload/SKILL.md +197 -0
  146. package/dist/gemini/.agents/skills/jahia-content-move-content/SKILL.md +160 -165
  147. package/dist/gemini/.agents/skills/jahia-content-organize/SKILL.md +209 -0
  148. package/dist/gemini/.agents/skills/jahia-content-publish/SKILL.md +181 -0
  149. package/dist/gemini/.agents/skills/jahia-content-query-content/SKILL.md +122 -92
  150. package/dist/gemini/.agents/skills/jahia-content-translate-content/SKILL.md +154 -225
  151. package/dist/gemini/.agents/skills/jahia-dev-accessibility/SKILL.md +3 -3
  152. package/dist/gemini/.agents/skills/jahia-dev-build-component/SKILL.md +10 -7
  153. package/dist/gemini/.agents/skills/jahia-dev-create-page-template/SKILL.md +59 -21
  154. package/dist/gemini/.agents/skills/jahia-dev-create-template-set/SKILL.md +20 -47
  155. package/dist/gemini/.agents/skills/jahia-dev-create-view/SKILL.md +3 -3
  156. package/dist/gemini/.agents/skills/jahia-dev-cypress/SKILL.md +150 -330
  157. package/dist/gemini/.agents/skills/jahia-dev-define-content-type/SKILL.md +43 -486
  158. package/dist/gemini/.agents/skills/jahia-dev-define-content-type/references/modeling-decisions.md +52 -0
  159. package/dist/gemini/.agents/skills/jahia-dev-query-content/SKILL.md +93 -296
  160. package/dist/gemini/.agents/skills/jahia-dev-review-cnd/SKILL.md +79 -0
  161. package/dist/gemini/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.d.mts +13 -0
  162. package/dist/gemini/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.mjs +198 -0
  163. package/dist/gemini/.agents/skills/jahia-dev-site-review/SKILL.md +70 -0
  164. package/dist/gemini/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +85 -0
  165. package/dist/gemini/.agents/skills/jahia-dev-start-local/SKILL.md +18 -26
  166. package/dist/gemini/.agents/skills/jahia-jcr-sql2/SKILL.md +258 -0
  167. package/dist/gemini/.agents/skills/jahia-orchestrate/SKILL.md +148 -0
  168. package/dist/gemini/.agents/skills/jahia-orchestrate/scripts/verify-pages.mjs +59 -0
  169. package/dist/gemini/AGENTS.md +17 -10
  170. package/dist/gemini/GEMINI.md +2 -2
  171. package/dist/index.js +13 -0
  172. package/dist/opencode/.agents/skills/jahia/SKILL.md +23 -11
  173. package/dist/opencode/.agents/skills/jahia-content/SKILL.md +102 -84
  174. package/dist/opencode/.agents/skills/jahia-content-create-content/SKILL.md +255 -280
  175. package/dist/opencode/.agents/skills/jahia-content-explore-structure/SKILL.md +187 -96
  176. package/dist/opencode/.agents/skills/jahia-content-media-upload/SKILL.md +197 -0
  177. package/dist/opencode/.agents/skills/jahia-content-move-content/SKILL.md +160 -165
  178. package/dist/opencode/.agents/skills/jahia-content-organize/SKILL.md +209 -0
  179. package/dist/opencode/.agents/skills/jahia-content-publish/SKILL.md +181 -0
  180. package/dist/opencode/.agents/skills/jahia-content-query-content/SKILL.md +122 -92
  181. package/dist/opencode/.agents/skills/jahia-content-translate-content/SKILL.md +154 -225
  182. package/dist/opencode/.agents/skills/jahia-dev-accessibility/SKILL.md +3 -3
  183. package/dist/opencode/.agents/skills/jahia-dev-build-component/SKILL.md +10 -7
  184. package/dist/opencode/.agents/skills/jahia-dev-create-page-template/SKILL.md +59 -21
  185. package/dist/opencode/.agents/skills/jahia-dev-create-template-set/SKILL.md +20 -47
  186. package/dist/opencode/.agents/skills/jahia-dev-create-view/SKILL.md +3 -3
  187. package/dist/opencode/.agents/skills/jahia-dev-cypress/SKILL.md +150 -330
  188. package/dist/opencode/.agents/skills/jahia-dev-define-content-type/SKILL.md +43 -486
  189. package/dist/opencode/.agents/skills/jahia-dev-define-content-type/references/modeling-decisions.md +52 -0
  190. package/dist/opencode/.agents/skills/jahia-dev-query-content/SKILL.md +93 -296
  191. package/dist/opencode/.agents/skills/jahia-dev-review-cnd/SKILL.md +79 -0
  192. package/dist/opencode/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.d.mts +13 -0
  193. package/dist/opencode/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.mjs +198 -0
  194. package/dist/opencode/.agents/skills/jahia-dev-site-review/SKILL.md +70 -0
  195. package/dist/opencode/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +85 -0
  196. package/dist/opencode/.agents/skills/jahia-dev-start-local/SKILL.md +18 -26
  197. package/dist/opencode/.agents/skills/jahia-jcr-sql2/SKILL.md +258 -0
  198. package/dist/opencode/.agents/skills/jahia-orchestrate/SKILL.md +148 -0
  199. package/dist/opencode/.agents/skills/jahia-orchestrate/scripts/verify-pages.mjs +59 -0
  200. package/dist/opencode/.opencode/agents/cnd-child-nodes.md +74 -0
  201. package/dist/opencode/.opencode/agents/cnd-jahia-mixins.md +113 -0
  202. package/dist/opencode/.opencode/agents/cnd-numbers-dates.md +61 -0
  203. package/dist/opencode/.opencode/agents/cnd-string-selectors.md +94 -0
  204. package/dist/opencode/.opencode/agents/jahia-cnd-author.md +130 -0
  205. package/dist/opencode/.opencode/agents/jahia-dev-worker.md +264 -0
  206. package/dist/opencode/.opencode/agents/jahia-reviewer.md +105 -0
  207. package/dist/opencode/AGENTS.md +17 -10
  208. package/dist/windsurf/.windsurf/rules/jahia.md +15 -6
  209. package/dist/windsurf/.windsurf/skills/jahia/SKILL.md +23 -11
  210. package/dist/windsurf/.windsurf/skills/jahia-content/SKILL.md +102 -84
  211. package/dist/windsurf/.windsurf/skills/jahia-content-create-content/SKILL.md +255 -280
  212. package/dist/windsurf/.windsurf/skills/jahia-content-explore-structure/SKILL.md +187 -96
  213. package/dist/windsurf/.windsurf/skills/jahia-content-media-upload/SKILL.md +197 -0
  214. package/dist/windsurf/.windsurf/skills/jahia-content-move-content/SKILL.md +160 -165
  215. package/dist/windsurf/.windsurf/skills/jahia-content-organize/SKILL.md +209 -0
  216. package/dist/windsurf/.windsurf/skills/jahia-content-publish/SKILL.md +181 -0
  217. package/dist/windsurf/.windsurf/skills/jahia-content-query-content/SKILL.md +122 -92
  218. package/dist/windsurf/.windsurf/skills/jahia-content-translate-content/SKILL.md +154 -225
  219. package/dist/windsurf/.windsurf/skills/jahia-dev-accessibility/SKILL.md +3 -3
  220. package/dist/windsurf/.windsurf/skills/jahia-dev-build-component/SKILL.md +10 -7
  221. package/dist/windsurf/.windsurf/skills/jahia-dev-create-page-template/SKILL.md +59 -21
  222. package/dist/windsurf/.windsurf/skills/jahia-dev-create-template-set/SKILL.md +20 -47
  223. package/dist/windsurf/.windsurf/skills/jahia-dev-create-view/SKILL.md +3 -3
  224. package/dist/windsurf/.windsurf/skills/jahia-dev-cypress/SKILL.md +150 -330
  225. package/dist/windsurf/.windsurf/skills/jahia-dev-define-content-type/SKILL.md +43 -486
  226. package/dist/windsurf/.windsurf/skills/jahia-dev-define-content-type/references/modeling-decisions.md +52 -0
  227. package/dist/windsurf/.windsurf/skills/jahia-dev-query-content/SKILL.md +93 -296
  228. package/dist/windsurf/.windsurf/skills/jahia-dev-review-cnd/SKILL.md +79 -0
  229. package/dist/windsurf/.windsurf/skills/jahia-dev-review-cnd/scripts/check-cnd.d.mts +13 -0
  230. package/dist/windsurf/.windsurf/skills/jahia-dev-review-cnd/scripts/check-cnd.mjs +198 -0
  231. package/dist/windsurf/.windsurf/skills/jahia-dev-site-review/SKILL.md +70 -0
  232. package/dist/windsurf/.windsurf/skills/jahia-dev-site-review/scripts/review-pages.mjs +85 -0
  233. package/dist/windsurf/.windsurf/skills/jahia-dev-start-local/SKILL.md +18 -26
  234. package/dist/windsurf/.windsurf/skills/jahia-jcr-sql2/SKILL.md +258 -0
  235. package/dist/windsurf/.windsurf/skills/jahia-orchestrate/SKILL.md +148 -0
  236. package/dist/windsurf/.windsurf/skills/jahia-orchestrate/scripts/verify-pages.mjs +59 -0
  237. package/dist/windsurf/AGENTS.md +17 -10
  238. package/package.json +3 -3
@@ -1,53 +1,41 @@
1
1
  ---
2
2
  name: jahia-dev-query-content
3
- description: Writes JCR-SQL2 queries to list and filter Jahia content. Use when asked to list articles, display content from a folder, filter by date, or build a content listing.
4
- allowed-tools: Bash, Read, Write, Edit, WebFetch
3
+ description: Designs JCR-SQL2 content queries for Jahia page-builder listings and JS module views. Use when asked to list content from folders, filter items, sort results, or wire `useJCRQuery` into a template-set component.
5
4
  ---
6
5
 
7
- ## Overview
8
-
9
- Jahia stores all content in a tree-based **Java Content Repository (JCR)**. Content can be queried using **JCR-SQL2**, a SQL-like language. This is used to build listings (blogs, news, team members, etc.) from content stored in **Content Folders**.
6
+ # Skill: jahia-dev-query-content
10
7
 
11
- There are **three ways** to query content in Jahia JS modules:
12
- 1. **No-code**: built-in `Jahia - Queries` component in Page Builder
13
- 2. **Server-side hook**: `useJCRQuery` in a `.server.tsx` view
14
- 3. **Client-side hook**: `useJCRQuery` in a `.client.tsx` island (for dynamic, browser-triggered queries)
8
+ Use this skill when building content listings in Jahia template sets.
9
+ For pure JCR-SQL2 language rules, full-text syntax, joins, pagination, and performance guardrails, also use `/jahia-jcr-sql2`.
15
10
 
16
11
  ---
17
12
 
18
- ## Step 1 — Understand Content Folders
13
+ ## Overview
19
14
 
20
- Instead of placing content directly on a page, reusable content (blog posts, team members, etc.) is stored in **Content Folders** under the `contents/` tree of the site.
15
+ Jahia stores editorial content in the JCR. In template sets, you usually query it in one of three ways:
21
16
 
22
- To create a content folder in Jahia UI:
23
- 1. Open **jContent** (the content manager)
24
- 2. Navigate to **Content Folders** in the left sidebar
25
- 3. Right-click → **New Folder**, name it (e.g. `blog`)
26
- 4. Create content items inside this folder
17
+ 1. **Page Builder query component** no-code listing using a JCR query string
18
+ 2. **Server-side view** `useJCRQuery` inside a `.server.tsx` component
19
+ 3. **Client-driven experience** use a dedicated API strategy only when a server-side query is not enough
27
20
 
28
21
  ---
29
22
 
30
- ## Step 2Use the built-in query component (no code)
23
+ ## Step 1Understand where content lives
31
24
 
32
- For simple listings, use the built-in **Jahia - Queries > Content items using JCR Query** component in Page Builder. Enter your JCR-SQL2 query in the query field.
25
+ Reusable content usually lives under `/sites/<siteKey>/contents/...` instead of directly under pages.
26
+ Create and manage those folders in jContent.
33
27
 
34
- ---
35
-
36
- ## Step 2b — Make content folders editable in jContent
37
-
38
- Content folders are browsable via **jContent** by default, but if editors need to manage content directly from the **Content Tree** in Page Builder, add `jmix:visibleInContentTree` to the folder node type:
28
+ If editors need the folder visible in the Page Builder content tree, add `jmix:visibleInContentTree` to the folder type:
39
29
 
40
30
  ```cnd
41
31
  [namespace:blogFolder] > jnt:contentFolder, jmix:visibleInContentTree
42
32
  ```
43
33
 
44
- This makes the folder appear in the left sidebar of Page Builder, enabling drag-and-drop management.
45
-
46
34
  ---
47
35
 
48
- ## Step 3Write a JCR-SQL2 query
36
+ ## Step 2Start with the right SQL2 shape
49
37
 
50
- ### Basic query — list all items of a type
38
+ ### List all items of a type under a folder
51
39
 
52
40
  ```sql
53
41
  SELECT *
@@ -55,137 +43,93 @@ FROM [namespace:typeName] AS item
55
43
  WHERE ISDESCENDANTNODE(item, '/sites/<siteKey>/contents/<folderName>')
56
44
  ```
57
45
 
58
- Replace `<siteKey>` with the site key set during site creation.
59
-
60
- ### Filter out drafts (items without a date)
46
+ ### Only direct children of a folder
61
47
 
62
48
  ```sql
63
49
  SELECT *
64
50
  FROM [namespace:blogPost] AS post
65
- WHERE ISDESCENDANTNODE(post, '/sites/<siteKey>/contents/blog')
66
- AND post.[publicationDate] IS NOT NULL
67
- ORDER BY post.[publicationDate] DESC
51
+ WHERE ISCHILDNODE(post, '/sites/<siteKey>/contents/blog')
68
52
  ```
69
53
 
70
- ### Query all descendants (not just direct children)
71
-
72
- Use `ISDESCENDANTNODE` for nested folder structures:
54
+ ### Filter drafts and sort newest first
73
55
 
74
56
  ```sql
75
- -- All blog posts anywhere under /contents/blog (including subfolders)
76
- SELECT * FROM [namespace:blogPost] AS post
57
+ SELECT *
58
+ FROM [namespace:blogPost] AS post
77
59
  WHERE ISDESCENDANTNODE(post, '/sites/<siteKey>/contents/blog')
60
+ AND post.[publicationDate] IS NOT NULL
61
+ ORDER BY post.[publicationDate] DESC
78
62
  ```
79
63
 
80
- Use `ISCHILDNODE` when you want only direct children of a folder:
81
-
82
- ```sql
83
- -- Only direct children of /contents/blog
84
- SELECT * FROM [namespace:blogPost] AS post
85
- WHERE ISCHILDNODE(post, '/sites/<siteKey>/contents/blog')
86
- ```
87
-
88
- ### Common query clauses
89
-
90
- | Clause | Usage |
91
- |---|---|
92
- | `ISDESCENDANTNODE(x, '/path')` | Filter by location in the tree |
93
- | `x.[prop] IS NOT NULL` | Exclude items without a property (draft filter) |
94
- | `x.[prop] = 'value'` | Filter by property value |
95
- | `ORDER BY x.[prop] DESC` | Sort descending |
96
- | `ORDER BY x.[prop] ASC` | Sort ascending |
97
-
98
64
  ---
99
65
 
100
- ## Step 4Make a content type accessible at its own URL
66
+ ## Step 3Use the right SQL2 clauses
101
67
 
102
- Use `jmix:mainResource` **only** for content that needs **both a listing card AND a full detail page** (e.g. blog posts, team member profiles). Do not add it to visual composition types or navigation-only content.
68
+ | Need | Pattern |
69
+ |------|---------|
70
+ | Recursive subtree | `ISDESCENDANTNODE(alias, '/path')` |
71
+ | Direct children only | `ISCHILDNODE(alias, '/path')` |
72
+ | Property equality | `alias.[prop] = 'value'` |
73
+ | Pattern match | `alias.[prop] LIKE '%keyword%'` |
74
+ | Exclude empty values | `alias.[prop] IS NOT NULL` |
75
+ | Sort | `ORDER BY alias.[prop] DESC` |
76
+ | Full-text | `CONTAINS(alias.*, 'term')` |
77
+ | Relevance sort | `ORDER BY SCORE(alias) DESC` |
103
78
 
104
- To allow a blog post to be viewed as a full page, add `jmix:mainResource` to its CND definition:
105
-
106
- ```cnd
107
- [namespace:blogPost] > jnt:content, mix:title, jmix:mainResource, namespacemix:component
108
- ```
109
-
110
- Then create a full-page view for it:
111
-
112
- ```tsx
113
- // src/components/BlogPost/fullPage.server.tsx
114
- // NOTE: componentType is "view" (NOT "template") — the MainResource template
115
- // at src/templates/MainResource/default.server.tsx routes to this view automatically
116
- import { jahiaComponent } from "@jahia/javascript-modules-library";
117
- import type { Props } from "./types.js";
118
- import classes from "./component.module.css";
119
-
120
- jahiaComponent(
121
- {
122
- componentType: "view", // ← "view", NOT "template"
123
- nodeType: "namespace:blogPost",
124
- displayName: "Blog Post Full Page",
125
- name: "fullPage", // ← this name is what MainResource routes to
126
- },
127
- ({ "jcr:title": title, body, subtitle }: Props) => (
128
- <article className={classes.article}>
129
- <h1>{title}</h1>
130
- <p>{subtitle}</p>
131
- <div dangerouslySetInnerHTML={{ __html: body }} />
132
- </article>
133
- ),
134
- );
135
- ```
136
-
137
- ### Link to a full-page content item
138
-
139
- Use `buildNodeUrl(currentNode)` to generate the URL to the item:
140
-
141
- ```tsx
142
- <a href={buildNodeUrl(currentNode)}>{title}</a>
143
- ```
79
+ **Performance rule:** always constrain queries by path.
144
80
 
145
81
  ---
146
82
 
147
- ## Step 5Draft/publish pattern
83
+ ## Step 4Add full-text and filtering when needed
148
84
 
149
- A common pattern is to use a `publicationDate` property as a draft gate:
85
+ ### Phrase search sorted by relevance
150
86
 
151
- ```cnd
152
- - publicationDate (date)
87
+ ```sql
88
+ SELECT *
89
+ FROM [namespace:blogPost] AS post
90
+ WHERE ISDESCENDANTNODE(post, '/sites/<siteKey>/contents/blog')
91
+ AND CONTAINS(post.*, '"annual report"')
92
+ ORDER BY SCORE(post) DESC
153
93
  ```
154
94
 
155
- Note: do **not** mark it as `mandatory` — that would be a breaking change on an existing type, and it doubles as the draft indicator (no date = draft).
156
-
157
- In the query, filter published posts only:
95
+ ### Search one property only
158
96
 
159
97
  ```sql
160
- AND post.[publicationDate] IS NOT NULL
98
+ SELECT *
99
+ FROM [namespace:blogPost] AS post
100
+ WHERE ISDESCENDANTNODE(post, '/sites/<siteKey>/contents/blog')
101
+ AND CONTAINS(post.[jcr:title], 'welcome')
161
102
  ORDER BY post.[publicationDate] DESC
162
103
  ```
163
104
 
164
- Display the date in the view:
105
+ ### Filter by date
165
106
 
166
- ```tsx
167
- {publicationDate && (
168
- <time dateTime={publicationDate}>
169
- {new Date(publicationDate).toLocaleDateString(
170
- currentResource.getLocale().toString(),
171
- { dateStyle: "long" }
172
- )}
173
- </time>
174
- )}
107
+ ```sql
108
+ SELECT *
109
+ FROM [namespace:blogPost] AS post
110
+ WHERE ISDESCENDANTNODE(post, '/sites/<siteKey>/contents/blog')
111
+ AND post.[publicationDate] > CAST('2026-01-01T00:00:00.000Z' AS DATE)
112
+ ORDER BY post.[publicationDate] DESC
175
113
  ```
176
114
 
115
+ Use the millisecond form `yyyy-MM-dd'T'HH:mm:ss.SSSX` for SQL2 date casts.
116
+
177
117
  ---
178
118
 
179
- ## Step 6Query in code with `useJCRQuery`
119
+ ## Step 5Use queries in Jahia UI or code
120
+
121
+ ### Page Builder query component
180
122
 
181
- For custom listing components (rather than using the built-in query component), use `useJCRQuery` from the library inside a `.server.tsx` view:
123
+ For a simple listing, use **Jahia - Queries > Content items using JCR Query** and paste the SQL2 query there.
124
+
125
+ ### `useJCRQuery` in a `.server.tsx` view
182
126
 
183
127
  ```tsx
184
- import { jahiaComponent, useJCRQuery, Render } from "@jahia/javascript-modules-library";
185
- import type { JCRNodeWrapper } from "org.jahia.services.content";
128
+ import { jahiaComponent, useJCRQuery, Render } from '@jahia/javascript-modules-library';
129
+ import type { JCRNodeWrapper } from 'org.jahia.services.content';
186
130
 
187
131
  jahiaComponent(
188
- { componentType: "view", nodeType: "namespace:blogListing" },
132
+ { componentType: 'view', nodeType: 'namespace:blogListing' },
189
133
  (_, { renderContext }) => {
190
134
  const siteKey = renderContext.getSite().getName();
191
135
  const posts = useJCRQuery({
@@ -206,202 +150,55 @@ jahiaComponent(
206
150
  );
207
151
  ```
208
152
 
209
- > `useJCRQuery` is server-side only (`.server.tsx`). For client-side dynamic queries triggered by user interaction, use the GraphQL approach in a `.client.tsx` island.
210
-
211
153
  ---
212
154
 
213
- ## Step 7Language switcher with `getSiteLocales`
155
+ ## Step 6Patterns commonly needed in template sets
214
156
 
215
- For sites with multiple languages, build a language switcher by combining `getSiteLocales()` with `j:invalidLanguages` and `node.hasI18N()`. Filter out disabled or untranslated locales before generating URLs.
157
+ ### Make a content type renderable at its own URL
216
158
 
217
- ```tsx
218
- import { getSiteLocales, buildNodeUrl, jahiaComponent } from "@jahia/javascript-modules-library";
159
+ Use `jmix:mainResource` only for content that needs both a listing card and a full detail page.
219
160
 
220
- jahiaComponent(
221
- { componentType: "view", nodeType: "ns:languageSwitcher" },
222
- (_, { currentNode }) => {
223
- const locales = getSiteLocales(); // Record<string, java.util.Locale>
224
-
225
- // Read j:invalidLanguages (languages disabled on this node)
226
- const invalidCodes = currentNode.hasProperty("j:invalidLanguages")
227
- ? currentNode.getProperty("j:invalidLanguages").getValues().map((v: any) => v.getString())
228
- : [];
229
- const invalidSet = new Set(invalidCodes);
230
-
231
- const links = Object.entries(locales)
232
- .filter(([code, locale]) =>
233
- !invalidSet.has(code) && currentNode.hasI18N(locale),
234
- )
235
- .map(([code]) => ({
236
- code,
237
- url: buildNodeUrl(currentNode, { language: code }),
238
- }));
239
-
240
- return (
241
- <nav aria-label="Language switcher">
242
- {links.map(({ code, url }) => (
243
- <a key={code} href={url} lang={code} hrefLang={code}>
244
- {code.toUpperCase()}
245
- </a>
246
- ))}
247
- </nav>
248
- );
249
- },
250
- );
251
- ```
252
-
253
- > `getSiteLocales()` returns all locales configured for the site — not just the active language. Always filter by `j:invalidLanguages` and `hasI18N()` before displaying.
254
-
255
- ---
256
-
257
- ## Step 7b — Query via GraphQL with `useGQLQuery`
258
-
259
- For complex queries that span multiple nodes or need field-level projection, `useGQLQuery` is more efficient than `useJCRQuery`. It runs synchronously on the server using the current user's session.
260
-
261
- ```tsx
262
- import { useGQLQuery, jahiaComponent } from "@jahia/javascript-modules-library";
263
- import { gql } from "graphql-tag";
264
-
265
- const BLOG_QUERY = gql`
266
- query LatestPosts($path: String!) {
267
- jcr {
268
- nodeByPath(path: $path) {
269
- descendants(typesFilter: { types: ["namespace:blogPost"] }, fieldFilter: {
270
- filters: [{ fieldName: "publicationDate", evaluation: NOT_EMPTY }]
271
- }) {
272
- nodes {
273
- name
274
- path
275
- displayName
276
- property(name: "publicationDate") { value }
277
- property(name: "jcr:title") { value }
278
- }
279
- }
280
- }
281
- }
282
- }
283
- `;
284
-
285
- jahiaComponent(
286
- { componentType: "view", nodeType: "namespace:blogListing" },
287
- (_, { renderContext }) => {
288
- const siteKey = renderContext.getSite().getName();
289
- const data = useGQLQuery(BLOG_QUERY, { path: `/sites/${siteKey}/contents/blog` });
290
- const posts = data?.jcr?.nodeByPath?.descendants?.nodes ?? [];
291
-
292
- return (
293
- <ul>
294
- {posts.map((post: any) => (
295
- <li key={post.path}>
296
- <a href={post.path}>{post.property?.value ?? post.displayName}</a>
297
- </li>
298
- ))}
299
- </ul>
300
- );
301
- },
302
- );
161
+ ```cnd
162
+ [namespace:blogPost] > jnt:content, mix:title, jmix:mainResource, namespacemix:component
303
163
  ```
304
164
 
305
- ---
306
-
307
- ## Step 8 — Hierarchical content with nested folders
308
-
309
- Content folders can be nested to create sections (e.g. `tutorials/front-end/`, `tutorials/editors/`). Use `ISDESCENDANTNODE` in queries to automatically include all levels — no query changes needed as you add sub-folders.
165
+ Then add a `fullPage.server.tsx` view and link to the node with `buildNodeUrl(currentNode)`.
310
166
 
311
- For **sidebar navigation** or **tree panels**, traverse the JCR hierarchy directly instead of querying:
167
+ ### Draft gate with `publicationDate`
312
168
 
313
- ### Get a JCR node by path
169
+ A common pattern is:
314
170
 
315
- ```tsx
316
- import { useServerContext } from "@jahia/javascript-modules-library";
317
- import type { JCRNodeWrapper } from "org.jahia.services.content";
318
-
319
- const { renderContext } = useServerContext();
320
- const folderNode = renderContext.getMainResource().getNode().getSession().getNode(
321
- `/sites/${siteKey}/contents/tutorials`
322
- ) as JCRNodeWrapper;
171
+ ```cnd
172
+ - publicationDate (date)
323
173
  ```
324
174
 
325
- ### Walk up to the section root
175
+ and the query:
326
176
 
327
- ```tsx
328
- function findSectionRoot(node: JCRNodeWrapper): JCRNodeWrapper {
329
- const parts = node.getPath().split("/");
330
- const contentsPath = parts.slice(0, 4).join("/"); // /sites/siteKey/contents
331
- let current = node;
332
- while (current.getParent() && (current.getParent() as JCRNodeWrapper).getPath() !== contentsPath) {
333
- current = current.getParent() as JCRNodeWrapper;
334
- }
335
- return current;
336
- }
177
+ ```sql
178
+ AND post.[publicationDate] IS NOT NULL
179
+ ORDER BY post.[publicationDate] DESC
337
180
  ```
338
181
 
339
- > ⚠️ `getParent()` returns `Node` (JCR base type), not `JCRNodeWrapper`. Always cast: `current.getParent() as JCRNodeWrapper`.
182
+ ### Nested content folders
340
183
 
341
- ### Recursively render a folder tree
184
+ Use `ISDESCENDANTNODE` to cover nested folder trees automatically. Switch to `ISCHILDNODE` only when you intentionally want one level.
342
185
 
343
- Use a plain function (not a React component) for recursive tree rendering — avoids hook scope issues:
186
+ ---
344
187
 
345
- ```tsx
346
- import type { ReactElement } from "react";
347
- import { buildNodeUrl } from "@jahia/javascript-modules-library";
348
- import type { JCRNodeWrapper } from "org.jahia.services.content";
349
-
350
- function renderTree(
351
- folder: JCRNodeWrapper,
352
- contentNodeType: string,
353
- depth: number = 0,
354
- ): ReactElement | null {
355
- const items: Array<{ type: "folder" | "item"; node: JCRNodeWrapper }> = [];
356
- const iter = folder.getNodes();
357
- while (iter.hasNext()) {
358
- const node = iter.nextNode() as JCRNodeWrapper;
359
- if (node.isNodeType("jnt:contentFolder")) items.push({ type: "folder", node });
360
- else if (node.isNodeType(contentNodeType)) items.push({ type: "item", node });
361
- }
362
- if (items.length === 0) return null;
363
-
364
- return (
365
- <ul>
366
- {items.map(({ type, node }) => {
367
- const key = node.getPath();
368
- if (type === "folder") {
369
- return (
370
- <li key={key}>
371
- <strong>{node.getPropertyAsString("jcr:title") || node.getName()}</strong>
372
- {renderTree(node, contentNodeType, depth + 1)}
373
- </li>
374
- );
375
- }
376
- return (
377
- <li key={key}>
378
- <a href={buildNodeUrl(node)}>
379
- {node.getPropertyAsString("jcr:title") || node.getName()}
380
- </a>
381
- </li>
382
- );
383
- })}
384
- </ul>
385
- );
386
- }
387
- ```
188
+ ## Query checklist
388
189
 
389
- Use `folder.getNodes()` (returns a `NodeIterator`) call `.hasNext()` / `.nextNode()` to iterate. The iterator preserves orderable-folder order (creation/manual reordering in jContent), which `ORDER BY jcr:name` would not.
190
+ - [ ] Query is constrained to `/sites/<siteKey>/contents/...` or another specific subtree
191
+ - [ ] Node type is specific, not overly broad
192
+ - [ ] Sort order matches the UX need
193
+ - [ ] Draft or publish filtering is explicit
194
+ - [ ] Detail-page types use `jmix:mainResource` only when needed
195
+ - [ ] The query has been validated against `/jahia-jcr-sql2` guardrails
390
196
 
391
197
  ---
392
198
 
393
- - **JCR repository browser**: http://localhost:8080/modules/tools/jcrBrowser.jsp
394
- - **Installed definitions browser**: http://localhost:8080/modules/tools/definitionsBrowser.jsp
395
-
396
- ---
199
+ ## Related skills
397
200
 
398
- ## Validation checklist
399
- - [ ] Content folder exists in Jahia UI under `contents/`
400
- - [ ] Site key in query matches the actual site key (use `renderContext.getSite().getName()` in code)
401
- - [ ] Query returns expected results in the built-in query component
402
- - [ ] `jmix:mainResource` added if items need a full-page view
403
- - [ ] Draft/publish filtering works correctly
404
- - [ ] `buildNodeUrl(currentNode)` used for item links
201
+ - `/jahia-jcr-sql2` — SQL2 syntax, full-text, joins, pagination, and performance
202
+ - `/jahia-dev-build-component` build the listing component that renders query results
203
+ - `/jahia-dev-define-content-type` create the queried content type and folder types
405
204
 
406
- ## Troubleshooting
407
- > https://academy.jahia.com/tutorials-get-started/front-end-developer/making-a-blog
@@ -0,0 +1,79 @@
1
+ ---
2
+ name: jahia-dev-review-cnd
3
+ description: Use after writing any CND file to validate it against Jahia best practices. Runs the deterministic cnd-checker script and reports PASS / FAIL with file:line citations and fixes. Run /jahia-dev-review-cnd <path> to check a specific file or directory, or without arguments to check all CND files in the current module.
4
+ allowed-tools: Bash
5
+ ---
6
+
7
+ ## Step 1 — Run the checker
8
+
9
+ ```bash
10
+ CND_SCRIPT=$(find .claude .agents -name "check-cnd.mjs" 2>/dev/null | head -1)
11
+ node "$CND_SCRIPT" <path-to-file-or-directory>
12
+ # or, to check all CND files in the module:
13
+ node "$CND_SCRIPT" src/
14
+ ```
15
+
16
+ The script exits with code 0 for PASS and code 1 for FAIL.
17
+
18
+ ## Step 2 — Fix and repeat until clean
19
+
20
+ This is a loop. Run the checker, fix every issue reported, run it again. Repeat until the result is `PASS`.
21
+
22
+ - **FAIL** — fix every issue, re-run. Do not proceed until exit code is 0.
23
+ - **PASS** — clean. Continue.
24
+
25
+ ---
26
+
27
+ ## Antipattern reference
28
+
29
+ The checker enforces these patterns. Use this as a guide when interpreting output or fixing issues manually.
30
+
31
+ ### `rawStringLink`
32
+ Property whose name contains `link`, `url`, `href`, or `path` declared as `(string)`.
33
+ **Fix**: Use the link picker:
34
+ ```cnd
35
+ - j:linkType (string, choicelist[linkTypeInitializer]) mandatory
36
+ ```
37
+
38
+ ### `singleHardcodedCta`
39
+ A type with both a CTA label (`ctaText`, `ctaLabel`, `buttonText`, `buttonLabel`) and a CTA link (`ctaLink`, `ctaUrl`, `ctaHref`, `buttonLink`) as flat properties, with no child node.
40
+ **Fix**: Replace with a child node:
41
+ ```cnd
42
+ + * (ns:cta)
43
+
44
+ [ns:cta] > jnt:content, nsmix:component
45
+ - label (string) i18n mandatory
46
+ - j:linkType (string, choicelist[linkTypeInitializer]) mandatory
47
+ ```
48
+
49
+ ### `directDroppable`
50
+ A concrete type extending `jmix:droppableContent` directly.
51
+ **Fix**: Extend the module mixin: `[ns:hero] > jnt:content, nsmix:component`
52
+
53
+ ### `missingRatingConstraint`
54
+ `rating (long)` without a range constraint — unconstrained ratings cause data integrity issues.
55
+ **Fix**: Add `< "[1,5]"`
56
+
57
+ ### `redundantImageAlt`
58
+ `imageAlt (string)` alongside an image weakreference. The image node already has `jcr:title`.
59
+ **Fix**: Remove `imageAlt`. In the view: `image.getPropertyAsString("jcr:title") ?? ""`
60
+
61
+ ### `rawTitleProp`
62
+ Property named `title`, `heroTitle`, `pageTitle`, or `sectionTitle` typed as `(string)`.
63
+ **Fix**: Remove it, extend `mix:title`. Access as `props["jcr:title"]`.
64
+
65
+ ### `weakrefNoConstraint`
66
+ `(weakreference)` with no `< ` type constraint.
67
+ **Fix**: Add constraint — `< jmix:image` for images, `< jnt:file` for files.
68
+
69
+ ### `weakrefWrongConstraint`
70
+ `< 'jnt:file'` (quoted form).
71
+ **Fix**: `< jmix:image` (unquoted).
72
+
73
+ ### `missingI18n`
74
+ User-visible string (`title`, `text`, `label`, `description`, `subtitle`, `caption`, `alt`, `heading`, `summary`, `excerpt`, `body`) without `i18n`.
75
+ **Fix**: Add `i18n` after the type declaration.
76
+
77
+ ### `studioOnly`
78
+ Any use of `jmix:studioOnly`.
79
+ **Fix**: Replace with `jmix:hiddenType`.
@@ -0,0 +1,13 @@
1
+ export interface CndIssue {
2
+ file: string;
3
+ line?: number;
4
+ pattern: string;
5
+ message: string;
6
+ fix: string;
7
+ }
8
+
9
+ export function checkCndFiles(projectDir: string): {
10
+ score: number;
11
+ issues: CndIssue[];
12
+ filesChecked: number;
13
+ };