@jahia/agentic 0.4.1 → 0.5.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.
- package/CHANGELOG.md +10 -0
- package/dist/antigravity/.agents/rules/jahia.md +51 -0
- package/dist/antigravity/.agents/skills/jahia-cnd-author/SKILL.md +94 -0
- package/dist/antigravity/.agents/skills/jahia-cnd-author/references/cnd-area-types.md +55 -0
- package/dist/antigravity/.agents/skills/jahia-cnd-author/references/cnd-authoring-experience.md +92 -0
- package/dist/antigravity/.agents/skills/jahia-cnd-author/references/cnd-child-nodes.md +74 -0
- package/dist/antigravity/.agents/skills/jahia-cnd-author/references/cnd-jahia-mixins.md +510 -0
- package/dist/antigravity/.agents/skills/jahia-cnd-author/references/cnd-modeling-decisions.md +87 -0
- package/dist/antigravity/.agents/skills/jahia-cnd-author/references/cnd-numbers-dates.md +92 -0
- package/dist/antigravity/.agents/skills/jahia-cnd-author/references/cnd-string-selectors.md +133 -0
- package/dist/antigravity/.agents/skills/jahia-cnd-author/references/cnd-syntax.md +119 -0
- package/dist/antigravity/.agents/skills/jahia-cnd-author/references/types-ts-mapping.md +73 -0
- package/dist/antigravity/.agents/skills/jahia-dev-accessibility/SKILL.md +11 -0
- package/dist/antigravity/.agents/skills/jahia-dev-build-component/SKILL.md +133 -0
- package/dist/antigravity/.agents/skills/jahia-dev-create-page-template/SKILL.md +341 -0
- package/dist/antigravity/.agents/skills/jahia-dev-create-template-set/SKILL.md +205 -0
- package/dist/antigravity/.agents/skills/jahia-dev-create-view/SKILL.md +896 -0
- package/dist/antigravity/.agents/skills/jahia-dev-debug/SKILL.md +176 -0
- package/dist/antigravity/.agents/skills/jahia-dev-import-from/SKILL.md +244 -0
- package/dist/antigravity/.agents/skills/jahia-dev-jexperience/SKILL.md +269 -0
- package/dist/antigravity/.agents/skills/jahia-dev-ops/SKILL.md +50 -0
- package/dist/antigravity/.agents/skills/jahia-dev-ops/references/docker.md +151 -0
- package/dist/antigravity/.agents/skills/jahia-dev-ops/references/monitoring.md +195 -0
- package/dist/antigravity/.agents/skills/jahia-dev-ops/references/provisioning.md +269 -0
- package/dist/antigravity/.agents/skills/jahia-dev-properties/SKILL.md +147 -0
- package/dist/antigravity/.agents/skills/jahia-dev-properties/references/all-properties.md +231 -0
- package/dist/antigravity/.agents/skills/jahia-dev-query-content/SKILL.md +204 -0
- package/dist/antigravity/.agents/skills/jahia-dev-review-cnd/SKILL.md +79 -0
- package/dist/antigravity/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.d.mts +13 -0
- package/dist/antigravity/.agents/skills/jahia-dev-review-cnd/scripts/check-cnd.mjs +198 -0
- package/dist/antigravity/.agents/skills/jahia-dev-screenshot/SKILL.md +177 -0
- package/dist/antigravity/.agents/skills/jahia-dev-start-local/SKILL.md +121 -0
- package/dist/antigravity/.agents/skills/jahia-jcr-sql2/SKILL.md +257 -0
- package/dist/antigravity/.agents/skills/jahia-review/SKILL.md +63 -0
- package/dist/{claude/.claude/skills/jahia-dev-review → antigravity/.agents/skills/jahia-review-code}/SKILL.md +3 -3
- package/dist/antigravity/.agents/skills/jahia-review-site/SKILL.md +52 -0
- package/dist/antigravity/.agents/skills/jahia-review-site/scripts/review-pages.mjs +74 -0
- package/dist/antigravity/AGENTS.md +62 -0
- package/dist/claude/.claude/rules/jahia.md +1 -1
- package/dist/claude/.claude/skills/jahia-dev-build-component/SKILL.md +2 -2
- package/dist/claude/.claude/skills/jahia-dev-create-view/SKILL.md +2 -2
- package/dist/claude/.claude/skills/jahia-dev-import-from/SKILL.md +1 -1
- package/dist/claude/.claude/skills/jahia-dev-properties/SKILL.md +1 -1
- package/dist/claude/.claude/skills/jahia-dev-query-content/SKILL.md +1 -1
- package/dist/claude/.claude/skills/jahia-jcr-sql2/SKILL.md +1 -2
- package/dist/claude/.claude/skills/jahia-review/SKILL.md +63 -0
- package/dist/{copilot/.agents/skills/jahia-dev-review → claude/.claude/skills/jahia-review-code}/SKILL.md +3 -3
- package/dist/claude/.claude/skills/jahia-review-site/SKILL.md +52 -0
- package/dist/claude/.claude/skills/jahia-review-site/scripts/review-pages.mjs +74 -0
- package/dist/claude/.mcp.json +11 -0
- package/dist/claude/CLAUDE.md +2 -2
- package/dist/codex/.agents/skills/jahia-dev-build-component/SKILL.md +2 -2
- package/dist/codex/.agents/skills/jahia-dev-create-view/SKILL.md +2 -2
- package/dist/codex/.agents/skills/jahia-dev-import-from/SKILL.md +1 -1
- package/dist/codex/.agents/skills/jahia-dev-properties/SKILL.md +1 -1
- package/dist/codex/.agents/skills/jahia-dev-query-content/SKILL.md +1 -1
- package/dist/codex/.agents/skills/jahia-jcr-sql2/SKILL.md +1 -2
- package/dist/codex/.agents/skills/jahia-review/SKILL.md +63 -0
- package/dist/{cursor/.agents/skills/jahia-dev-review → codex/.agents/skills/jahia-review-code}/SKILL.md +3 -3
- package/dist/codex/.agents/skills/jahia-review-site/SKILL.md +52 -0
- package/dist/codex/.agents/skills/jahia-review-site/scripts/review-pages.mjs +74 -0
- package/dist/codex/AGENTS.md +2 -2
- package/dist/copilot/.agents/skills/jahia-dev-build-component/SKILL.md +2 -2
- package/dist/copilot/.agents/skills/jahia-dev-create-view/SKILL.md +2 -2
- package/dist/copilot/.agents/skills/jahia-dev-import-from/SKILL.md +1 -1
- package/dist/copilot/.agents/skills/jahia-dev-properties/SKILL.md +1 -1
- package/dist/copilot/.agents/skills/jahia-dev-query-content/SKILL.md +1 -1
- package/dist/copilot/.agents/skills/jahia-jcr-sql2/SKILL.md +1 -2
- package/dist/copilot/.agents/skills/jahia-review/SKILL.md +63 -0
- package/dist/{codex/.agents/skills/jahia-dev-review → copilot/.agents/skills/jahia-review-code}/SKILL.md +3 -3
- package/dist/copilot/.agents/skills/jahia-review-site/SKILL.md +52 -0
- package/dist/copilot/.agents/skills/jahia-review-site/scripts/review-pages.mjs +74 -0
- package/dist/copilot/AGENTS.md +2 -2
- package/dist/cursor/.agents/skills/jahia-dev-build-component/SKILL.md +2 -2
- package/dist/cursor/.agents/skills/jahia-dev-create-view/SKILL.md +2 -2
- package/dist/cursor/.agents/skills/jahia-dev-import-from/SKILL.md +1 -1
- package/dist/cursor/.agents/skills/jahia-dev-properties/SKILL.md +1 -1
- package/dist/cursor/.agents/skills/jahia-dev-query-content/SKILL.md +1 -1
- package/dist/cursor/.agents/skills/jahia-jcr-sql2/SKILL.md +1 -2
- package/dist/cursor/.agents/skills/jahia-review/SKILL.md +63 -0
- package/dist/cursor/.agents/skills/jahia-review-code/SKILL.md +228 -0
- package/dist/cursor/.agents/skills/jahia-review-site/SKILL.md +52 -0
- package/dist/cursor/.agents/skills/jahia-review-site/scripts/review-pages.mjs +74 -0
- package/dist/cursor/.cursor/mcp.json +11 -0
- package/dist/cursor/.cursor/rules/jahia.mdc +1 -1
- package/dist/gemini/.agents/skills/jahia-dev-build-component/SKILL.md +2 -2
- package/dist/gemini/.agents/skills/jahia-dev-create-view/SKILL.md +2 -2
- package/dist/gemini/.agents/skills/jahia-dev-import-from/SKILL.md +1 -1
- package/dist/gemini/.agents/skills/jahia-dev-properties/SKILL.md +1 -1
- package/dist/gemini/.agents/skills/jahia-dev-query-content/SKILL.md +1 -1
- package/dist/gemini/.agents/skills/jahia-jcr-sql2/SKILL.md +1 -2
- package/dist/gemini/.agents/skills/jahia-review/SKILL.md +63 -0
- package/dist/gemini/.agents/skills/jahia-review-code/SKILL.md +228 -0
- package/dist/gemini/.agents/skills/jahia-review-site/SKILL.md +52 -0
- package/dist/gemini/.agents/skills/jahia-review-site/scripts/review-pages.mjs +74 -0
- package/dist/gemini/.gemini/settings.json +10 -0
- package/dist/gemini/AGENTS.md +2 -2
- package/dist/index.js +14 -2
- package/dist/kiro/.kiro/settings/mcp.json +10 -0
- package/dist/kiro/.kiro/skills/jahia-cnd-author/SKILL.md +94 -0
- package/dist/kiro/.kiro/skills/jahia-cnd-author/references/cnd-area-types.md +55 -0
- package/dist/kiro/.kiro/skills/jahia-cnd-author/references/cnd-authoring-experience.md +92 -0
- package/dist/kiro/.kiro/skills/jahia-cnd-author/references/cnd-child-nodes.md +74 -0
- package/dist/kiro/.kiro/skills/jahia-cnd-author/references/cnd-jahia-mixins.md +510 -0
- package/dist/kiro/.kiro/skills/jahia-cnd-author/references/cnd-modeling-decisions.md +87 -0
- package/dist/kiro/.kiro/skills/jahia-cnd-author/references/cnd-numbers-dates.md +92 -0
- package/dist/kiro/.kiro/skills/jahia-cnd-author/references/cnd-string-selectors.md +133 -0
- package/dist/kiro/.kiro/skills/jahia-cnd-author/references/cnd-syntax.md +119 -0
- package/dist/kiro/.kiro/skills/jahia-cnd-author/references/types-ts-mapping.md +73 -0
- package/dist/kiro/.kiro/skills/jahia-dev-accessibility/SKILL.md +11 -0
- package/dist/kiro/.kiro/skills/jahia-dev-build-component/SKILL.md +133 -0
- package/dist/kiro/.kiro/skills/jahia-dev-create-page-template/SKILL.md +341 -0
- package/dist/kiro/.kiro/skills/jahia-dev-create-template-set/SKILL.md +205 -0
- package/dist/kiro/.kiro/skills/jahia-dev-create-view/SKILL.md +896 -0
- package/dist/kiro/.kiro/skills/jahia-dev-debug/SKILL.md +176 -0
- package/dist/kiro/.kiro/skills/jahia-dev-import-from/SKILL.md +244 -0
- package/dist/kiro/.kiro/skills/jahia-dev-jexperience/SKILL.md +269 -0
- package/dist/kiro/.kiro/skills/jahia-dev-ops/SKILL.md +50 -0
- package/dist/kiro/.kiro/skills/jahia-dev-ops/references/docker.md +151 -0
- package/dist/kiro/.kiro/skills/jahia-dev-ops/references/monitoring.md +195 -0
- package/dist/kiro/.kiro/skills/jahia-dev-ops/references/provisioning.md +269 -0
- package/dist/kiro/.kiro/skills/jahia-dev-properties/SKILL.md +147 -0
- package/dist/kiro/.kiro/skills/jahia-dev-properties/references/all-properties.md +231 -0
- package/dist/kiro/.kiro/skills/jahia-dev-query-content/SKILL.md +204 -0
- package/dist/kiro/.kiro/skills/jahia-dev-review-cnd/SKILL.md +79 -0
- package/dist/kiro/.kiro/skills/jahia-dev-review-cnd/scripts/check-cnd.d.mts +13 -0
- package/dist/kiro/.kiro/skills/jahia-dev-review-cnd/scripts/check-cnd.mjs +198 -0
- package/dist/kiro/.kiro/skills/jahia-dev-screenshot/SKILL.md +177 -0
- package/dist/kiro/.kiro/skills/jahia-dev-start-local/SKILL.md +121 -0
- package/dist/kiro/.kiro/skills/jahia-jcr-sql2/SKILL.md +257 -0
- package/dist/kiro/.kiro/skills/jahia-review/SKILL.md +63 -0
- package/dist/kiro/.kiro/skills/jahia-review-code/SKILL.md +228 -0
- package/dist/kiro/.kiro/skills/jahia-review-site/SKILL.md +52 -0
- package/dist/kiro/.kiro/skills/jahia-review-site/scripts/review-pages.mjs +74 -0
- package/dist/kiro/.kiro/steering/jahia.md +55 -0
- package/dist/kiro/AGENTS.md +62 -0
- package/dist/opencode/.agents/skills/jahia-dev-build-component/SKILL.md +2 -2
- package/dist/opencode/.agents/skills/jahia-dev-create-view/SKILL.md +2 -2
- package/dist/opencode/.agents/skills/jahia-dev-import-from/SKILL.md +1 -1
- package/dist/opencode/.agents/skills/jahia-dev-properties/SKILL.md +1 -1
- package/dist/opencode/.agents/skills/jahia-dev-query-content/SKILL.md +1 -1
- package/dist/opencode/.agents/skills/jahia-jcr-sql2/SKILL.md +1 -2
- package/dist/opencode/.agents/skills/jahia-review/SKILL.md +63 -0
- package/dist/opencode/.agents/skills/jahia-review-code/SKILL.md +228 -0
- package/dist/opencode/.agents/skills/jahia-review-site/SKILL.md +52 -0
- package/dist/opencode/.agents/skills/jahia-review-site/scripts/review-pages.mjs +74 -0
- package/dist/opencode/AGENTS.md +2 -2
- package/dist/opencode/opencode.json +12 -0
- package/dist/windsurf/.windsurf/rules/jahia.md +1 -1
- package/dist/windsurf/.windsurf/skills/jahia-dev-build-component/SKILL.md +2 -2
- package/dist/windsurf/.windsurf/skills/jahia-dev-create-view/SKILL.md +2 -2
- package/dist/windsurf/.windsurf/skills/jahia-dev-import-from/SKILL.md +1 -1
- package/dist/windsurf/.windsurf/skills/jahia-dev-properties/SKILL.md +1 -1
- package/dist/windsurf/.windsurf/skills/jahia-dev-query-content/SKILL.md +1 -1
- package/dist/windsurf/.windsurf/skills/jahia-jcr-sql2/SKILL.md +1 -2
- package/dist/windsurf/.windsurf/skills/jahia-review/SKILL.md +63 -0
- package/dist/windsurf/.windsurf/skills/jahia-review-code/SKILL.md +228 -0
- package/dist/windsurf/.windsurf/skills/jahia-review-site/SKILL.md +52 -0
- package/dist/windsurf/.windsurf/skills/jahia-review-site/scripts/review-pages.mjs +74 -0
- package/dist/windsurf/AGENTS.md +2 -2
- package/package.json +1 -1
- package/dist/claude/.claude/skills/jahia-dev-site-review/SKILL.md +0 -70
- package/dist/claude/.claude/skills/jahia-dev-site-review/scripts/review-pages.mjs +0 -85
- package/dist/codex/.agents/skills/jahia-dev-site-review/SKILL.md +0 -70
- package/dist/codex/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +0 -85
- package/dist/copilot/.agents/skills/jahia-dev-site-review/SKILL.md +0 -70
- package/dist/copilot/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +0 -85
- package/dist/cursor/.agents/skills/jahia-dev-site-review/SKILL.md +0 -70
- package/dist/cursor/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +0 -85
- package/dist/gemini/.agents/skills/jahia-dev-review/SKILL.md +0 -228
- package/dist/gemini/.agents/skills/jahia-dev-site-review/SKILL.md +0 -70
- package/dist/gemini/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +0 -85
- package/dist/opencode/.agents/skills/jahia-dev-review/SKILL.md +0 -228
- package/dist/opencode/.agents/skills/jahia-dev-site-review/SKILL.md +0 -70
- package/dist/opencode/.agents/skills/jahia-dev-site-review/scripts/review-pages.mjs +0 -85
- package/dist/windsurf/.windsurf/skills/jahia-dev-review/SKILL.md +0 -228
- package/dist/windsurf/.windsurf/skills/jahia-dev-site-review/SKILL.md +0 -70
- package/dist/windsurf/.windsurf/skills/jahia-dev-site-review/scripts/review-pages.mjs +0 -85
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: jahia-dev-debug
|
|
3
|
+
description: Debugs a Jahia JavaScript module end-to-end — build, deploy, and runtime errors. Finds the first error after deployment using live Docker logs.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Skill: jahia-dev-debug
|
|
7
|
+
|
|
8
|
+
Diagnoses why a Jahia JavaScript module fails to load. Follows the deployment pipeline from source to runtime.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Step 1 — Build
|
|
13
|
+
|
|
14
|
+
From the module directory (where `package.json` is):
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
yarn build
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
- **Build fails** → fix the TypeScript / bundling error shown and stop here. Do not proceed to deploy until the build is clean.
|
|
21
|
+
- **Build succeeds** → proceed to Step 2.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Step 2 — Deploy
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
yarn jahia-deploy
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Interpret the output:
|
|
32
|
+
- `"Operation successful"` in the response → deployment was accepted. Proceed to Step 3 — the module may still fail at runtime.
|
|
33
|
+
- `"{}"` or empty JSON → deployment was **rejected** (usually a CND parse error or missing dependency). Proceed to Step 3 to find the cause in the logs.
|
|
34
|
+
- Any other error → fix the connection issue (is Docker running?) then retry.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Step 3 — Watch live Docker logs
|
|
39
|
+
|
|
40
|
+
> Do NOT analyse logs that already exist — an old error is not necessarily the cause of the current issue. Start a fresh log stream, then deploy again to capture only what happens as a result of this deployment.
|
|
41
|
+
|
|
42
|
+
### 3a — Start watching logs in the background
|
|
43
|
+
|
|
44
|
+
Find the Jahia container name:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
docker ps --format '{{.Names}}' | grep -i jahia | head -1
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Then start tailing:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
docker logs -f <container-name> 2>&1 | grep -v "^\s*$" &
|
|
54
|
+
LOG_PID=$!
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 3b — Deploy again while logs are streaming
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
yarn jahia-deploy
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 3c — Wait ~15 seconds, then stop the log stream
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
sleep 15 && kill $LOG_PID 2>/dev/null
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 3d — Verify component registration
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
docker logs <container-name> 2>&1 | grep "Registered Jahia component"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Expected: one line per view registered, e.g.:
|
|
76
|
+
```
|
|
77
|
+
Registered Jahia component: mymodule_view_ns:hero_default
|
|
78
|
+
Registered Jahia component: mymodule_view_ns:hero_small
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
If a component you just deployed is **absent** from this list, its `jahiaComponent` call was never reached — usually a syntax/import error in the view file that prevented the module from fully loading.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Step 4 — Find the first error
|
|
86
|
+
|
|
87
|
+
Scan the captured log output for the **first** error that appears **after** the deploy timestamp. Common patterns to look for:
|
|
88
|
+
|
|
89
|
+
| Pattern | Likely cause |
|
|
90
|
+
|---|---|
|
|
91
|
+
| `CND parse error` / `invalid node type` | CND syntax error or illegal field declaration |
|
|
92
|
+
| `NoSuchNodeTypeException` | A referenced type doesn't exist (wrong namespace, typo, missing dependency) |
|
|
93
|
+
| `ClassNotFoundException` / `NoClassDefFoundError` | Java dependency missing |
|
|
94
|
+
| `Cannot set property` / `TypeError` in JS stack | View runtime error |
|
|
95
|
+
| `Module ... failed to start` | Any of the above |
|
|
96
|
+
| `Unresolved requirement` | OSGi dependency not satisfied |
|
|
97
|
+
| Missing `Registered Jahia component` for a specific type | View file has a syntax/import error, or `jahiaComponent` not reached |
|
|
98
|
+
|
|
99
|
+
**Focus on the first error, not the last.** Later errors are often cascading failures caused by the first one.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Step 5 — Fix and retry
|
|
104
|
+
|
|
105
|
+
Once the root cause is identified:
|
|
106
|
+
|
|
107
|
+
1. Fix the issue in the source files
|
|
108
|
+
2. Run `yarn build` again
|
|
109
|
+
3. Go back to Step 2
|
|
110
|
+
|
|
111
|
+
Repeat until `yarn jahia-deploy` succeeds and the module loads cleanly (no errors in the 15-second window after deploy).
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Common fixes by error type
|
|
116
|
+
|
|
117
|
+
### CND: `j:linknode` or `j:url` declared explicitly
|
|
118
|
+
These fields are injected by Jahia's `linkTypeInitializer` mixin. Remove them from the CND.
|
|
119
|
+
|
|
120
|
+
### CND: unknown mixin or type
|
|
121
|
+
Check that the namespace is declared at the top of `settings/definitions.cnd` and that all referenced types exist.
|
|
122
|
+
|
|
123
|
+
### import.xml: reference to a non-existent type
|
|
124
|
+
Any `jcr:primaryType` or `jcr:mixinTypes` value in `import.xml` must exist in the deployed CND. Check for typos.
|
|
125
|
+
|
|
126
|
+
### import.xml: `jmix:nolive` used as `jcr:primaryType`
|
|
127
|
+
`jmix:nolive` is a mixin — it goes in `jcr:mixinTypes`, not `jcr:primaryType`.
|
|
128
|
+
|
|
129
|
+
### import.xml: OSGi fails with `missing requirement … (nodetypes=jmix:nolive)`
|
|
130
|
+
Every `jcr:mixinTypes` value in `import.xml` is scanned by the OSGi bundle resolver. If the mixin is not declared in the module's own CND and is not provided by a resolvable dependency, the bundle will not start. Correct spelling is `jmix:nolive` (all lowercase). Verify the mixin exists in your Jahia instance before using it in `import.xml`.
|
|
131
|
+
|
|
132
|
+
### View: module loads but page is blank
|
|
133
|
+
Run `yarn dev` and check the Vite / SSR console for a React render error.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## GraalJS (server-side JS) debugging with Chrome DevTools
|
|
138
|
+
|
|
139
|
+
Use this when you need to step through server-side view code running inside GraalVM.
|
|
140
|
+
|
|
141
|
+
### Step 1 — Enable the inspector via GraphQL
|
|
142
|
+
|
|
143
|
+
In Jahia's Developer Tools > GraphQL editor, run:
|
|
144
|
+
|
|
145
|
+
```graphql
|
|
146
|
+
mutation {
|
|
147
|
+
admin {
|
|
148
|
+
jahia {
|
|
149
|
+
configuration(pid: "org.jahia.modules.javascript.modules.engine.jsengine.GraalVMEngine") {
|
|
150
|
+
polyGlotInspect: value(name: "polyglot.inspect", value: "0.0.0.0:9229")
|
|
151
|
+
polyGlotInspectSuspend: value(name: "polyglot.inspect.Suspend", value: "false")
|
|
152
|
+
polyGlotInspectSecure: value(name: "polyglot.inspect.Secure", value: "false")
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Step 2 — Map the port
|
|
160
|
+
|
|
161
|
+
If running in Docker, ensure port `9229` is mapped in `docker-compose.yml`:
|
|
162
|
+
|
|
163
|
+
```yaml
|
|
164
|
+
ports:
|
|
165
|
+
- "9229:9229"
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Step 3 — Connect Chrome
|
|
169
|
+
|
|
170
|
+
After the mutation, Jahia logs a `devtools://...` URL. Open it in Chrome (use latest; Chrome 117–118 had known debugger bugs).
|
|
171
|
+
|
|
172
|
+
### Step 4 — Set a breakpoint and debug
|
|
173
|
+
|
|
174
|
+
In Chrome DevTools Sources tab, open `<module>/dist/main.js`, set a breakpoint, then reload the page. The server-side render pauses at the breakpoint. Full scope inspection, step-over, and continue are supported.
|
|
175
|
+
|
|
176
|
+
The config file `org.jahia.modules.javascript.modules.engine.jsengine.GraalVMEngine.cfg` accepts any `polyglot.*` key as an engine option — you can persist these settings there instead of using the GraphQL mutation.
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: jahia-dev-import-from
|
|
3
|
+
description: Builds a Jahia component inspired by a component on an external URL. Fetches the page, lets the developer target one section, extracts its HTML structure and CSS/JS dependencies, then creates a proper CND + view. Use when asked to "create a component like the one on this page".
|
|
4
|
+
allowed-tools: Bash, Read, Write, Edit, WebFetch
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Skill: jahia-dev-import-from
|
|
8
|
+
|
|
9
|
+
Turns a component on an external website into a Jahia component. This is a developer workflow — the result uses CSS Modules, proper Jahia architecture, and is maintainable code. It is not a wholesale site clone.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Step 1 — Fetch and map the page
|
|
14
|
+
|
|
15
|
+
Fetch the URL with `WebFetch`. If WebFetch fails (403/503), fall back to:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
wget --quiet --user-agent="Mozilla/5.0" -O /tmp/imported-page.html "<URL>"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Scan the HTML for semantic section boundaries (`<section>`, `<article>`, `<header>`, `<footer>`, `<main>`, or `<div>` with class names matching patterns like `hero`, `banner`, `card`, `grid`, `slider`, `features`).
|
|
22
|
+
|
|
23
|
+
Print a numbered text map:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
[1] HEADER — logo + nav + CTA button
|
|
27
|
+
[2] HERO — animated text + background image + scroll indicator
|
|
28
|
+
[3] FEATURES — 3-column icon grid
|
|
29
|
+
[4] CAROUSEL — auto-sliding testimonials (Swiper)
|
|
30
|
+
[5] FOOTER — 4-column links + social icons
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Ask the developer: **"Which section do you want to implement?"**
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Step 2 — Extract the HTML fragment
|
|
38
|
+
|
|
39
|
+
Locate the target section in the fetched HTML. Extract the **complete HTML block** — every element, every attribute, every nesting level. Do not simplify, summarize, or rewrite any part of it.
|
|
40
|
+
|
|
41
|
+
**For repeating patterns** (card grid, carousel), copy the wrapper structure **plus one complete child item** with all its attributes.
|
|
42
|
+
|
|
43
|
+
**Replace only dynamic content** with typed placeholders:
|
|
44
|
+
|
|
45
|
+
| Source HTML | Replacement |
|
|
46
|
+
|---|---|
|
|
47
|
+
| Text inside an element | `{title}`, `{description}`, etc. |
|
|
48
|
+
| Image `src` / `data-bg` / `data-src` URL | `{image}` (will become a `weakreference` field) |
|
|
49
|
+
| Link `href` | `{href}` (will become `j:linkType` / `j:linknode`) |
|
|
50
|
+
|
|
51
|
+
**Keep verbatim:**
|
|
52
|
+
- All CSS classes
|
|
53
|
+
- All `data-*` attributes (animation libraries, carousel config, IDs)
|
|
54
|
+
- `aria-*` and `role` attributes
|
|
55
|
+
- `<noscript>` blocks and `<picture>/<source>` elements
|
|
56
|
+
- Carousel/slider wrapper `id`s — JS libraries use these for initialization
|
|
57
|
+
|
|
58
|
+
> ⚠️ Self-check: count the attributes on 2–3 key elements in the source HTML. If your extraction has fewer, you dropped something — re-extract.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Step 3 — Identify content fields vs structural HTML
|
|
63
|
+
|
|
64
|
+
Show the developer a proposed split:
|
|
65
|
+
|
|
66
|
+
**Will become CND fields (editable in Jahia):**
|
|
67
|
+
- User-facing text: titles, subtitles, descriptions, button labels
|
|
68
|
+
- Images (→ `weakreference, picker[type='image']`)
|
|
69
|
+
- Links (→ `j:linkType / j:linknode / j:url`)
|
|
70
|
+
- Any value that should vary between instances
|
|
71
|
+
|
|
72
|
+
**Will be hardcoded in the view:**
|
|
73
|
+
- Layout wrapper divs
|
|
74
|
+
- Icon SVGs that are decorative / never change
|
|
75
|
+
- Animation class names and `data-*` config attributes
|
|
76
|
+
- ARIA labels that are structural (e.g. `aria-label="Main navigation"`)
|
|
77
|
+
|
|
78
|
+
Ask the developer to confirm or adjust. If they want something to be editable that wasn't identified, add it as a field.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Step 4 — Identify CSS and JS dependencies
|
|
83
|
+
|
|
84
|
+
Scan the page `<head>` for resources that the target component depends on:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# From downloaded HTML, extract stylesheet and script references
|
|
88
|
+
grep -E '<link[^>]+stylesheet|<script[^>]+src' /tmp/imported-page.html | head -30
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Categorize findings:
|
|
92
|
+
|
|
93
|
+
| Type | Examples | Action |
|
|
94
|
+
|---|---|---|
|
|
95
|
+
| **Animation library** | AOS, GSAP, ScrollReveal, Animate.css | Likely needed — check npm first |
|
|
96
|
+
| **Carousel/slider** | Swiper, Glide, Owl Carousel, Splide | Likely needed — check npm first |
|
|
97
|
+
| **Utility CSS** | Bootstrap, Tailwind | May already be in the module or can be imported |
|
|
98
|
+
| **Site-specific CSS** | `main.css`, `theme.css` | Targeted import only (see Step 5b) |
|
|
99
|
+
| **Fonts** | Google Fonts, custom woff2 | Import if not already in the module |
|
|
100
|
+
|
|
101
|
+
Report findings, then ask: **"Should I import any of these? (yes / no / specific ones)"**
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Step 5 — Create the Jahia component
|
|
106
|
+
|
|
107
|
+
### Step 5a — CND and view
|
|
108
|
+
|
|
109
|
+
Using the confirmed field split from Step 3, run the `jahia-cnd-author` and `jahia-dev-create-view` patterns to create:
|
|
110
|
+
|
|
111
|
+
- `src/components/<Category>/<Name>/definition.cnd`
|
|
112
|
+
- `src/components/<Category>/<Name>/types.ts`
|
|
113
|
+
- `src/components/<Category>/<Name>/default.server.tsx`
|
|
114
|
+
- `src/components/<Category>/<Name>/component.module.css`
|
|
115
|
+
|
|
116
|
+
**TSX conversion rules** (mechanical, not creative):
|
|
117
|
+
|
|
118
|
+
1. `class="foo bar"` → `className="foo bar"` — keep class strings as-is if vendor CSS is imported, OR map to `classes.fooBar` if authoring new CSS
|
|
119
|
+
2. Void elements: `<img>`, `<input>`, `<br>` → add ` />`
|
|
120
|
+
3. `{placeholder}` → `{propName}` matching `Props`
|
|
121
|
+
4. Every `data-*`, `aria-*`, `id`, `<noscript>`, `<source>` stays in the TSX
|
|
122
|
+
|
|
123
|
+
**CSS Modules:** Write new CSS in `component.module.css` that achieves the same visual result. Rename source class names to semantic camelCase keys (`hero__title` → `.heroTitle`). Exception: if you're importing the original CSS as a static asset, use the original class names as plain strings — CSS Modules would rename them and break the imported CSS.
|
|
124
|
+
|
|
125
|
+
**Interactive components** (animations, carousels, event handlers) → Island architecture:
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
// default.server.tsx — passes config, initializes nothing
|
|
129
|
+
({ title, subtitle }: Props, { renderContext }) => (
|
|
130
|
+
<Island component={MyComponentClient} props={{ title, subtitle }} />
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
// MyComponent.client.tsx — owns the browser-side lifecycle
|
|
134
|
+
import { useEffect } from "react";
|
|
135
|
+
|
|
136
|
+
export default function MyComponentClient({ title, subtitle }: Props) {
|
|
137
|
+
useEffect(() => {
|
|
138
|
+
import("aos").then(({ default: AOS }) => AOS.init({ duration: 800 }));
|
|
139
|
+
}, []);
|
|
140
|
+
|
|
141
|
+
return (
|
|
142
|
+
<div data-aos="fade-up" className="hero">
|
|
143
|
+
<h1>{title}</h1>
|
|
144
|
+
</div>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Edit mode for carousels/sliders:** Render all items flat so editors can see and reorder them:
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
({ slides }, { renderContext }) =>
|
|
153
|
+
renderContext.isEditMode() ? (
|
|
154
|
+
<div className={classes.editStack}>
|
|
155
|
+
<RenderChildren />
|
|
156
|
+
<p className={classes.hint}>Carousel — add or reorder slides above</p>
|
|
157
|
+
</div>
|
|
158
|
+
) : (
|
|
159
|
+
<Island component={CarouselClient} props={{ count: slides?.length }} />
|
|
160
|
+
)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
### Step 5b — Import static assets (if confirmed in Step 4)
|
|
166
|
+
|
|
167
|
+
For each confirmed CSS file:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
mkdir -p static/css
|
|
171
|
+
curl -sL "<css-url>" -o "static/css/<filename>.css"
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
For JS libraries — prefer npm over manual download:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
# Check if available on npm
|
|
178
|
+
npm info <library-name> version 2>/dev/null
|
|
179
|
+
|
|
180
|
+
# If available:
|
|
181
|
+
yarn add <library-name>
|
|
182
|
+
# Then import in the .client.tsx: import AOS from "aos";
|
|
183
|
+
|
|
184
|
+
# If not on npm, download to static:
|
|
185
|
+
mkdir -p static/js
|
|
186
|
+
curl -sL "<js-url>" -o "static/js/<filename>.js"
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
For fonts:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
mkdir -p static/fonts
|
|
193
|
+
curl -sL "<font-url>" -o "static/fonts/<filename>.woff2"
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Update the module's `Layout` template (`src/templates/Layout.server.tsx` or `src/templates/Layout.jsx`) to include the assets:
|
|
197
|
+
|
|
198
|
+
```tsx
|
|
199
|
+
import { AddResources, buildModuleFileUrl } from "@jahia/javascript-modules-library";
|
|
200
|
+
|
|
201
|
+
// In the <head> section:
|
|
202
|
+
<AddResources type="css" url={buildModuleFileUrl("static/css/vendor.css")} />
|
|
203
|
+
<AddResources type="javascript" url={buildModuleFileUrl("static/js/aos.js")} />
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Update `package.json` → `jahia.static-resources` to expose the static directories:
|
|
207
|
+
|
|
208
|
+
```json
|
|
209
|
+
{
|
|
210
|
+
"jahia": {
|
|
211
|
+
"static-resources": "/dist/client,/dist/assets,/locales,/static/css,/static/js,/static/fonts"
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
> **Never hardcode `/modules/<name>/...` paths** — use `buildModuleFileUrl` so the path resolves correctly across environments and module name changes.
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Step 6 — Build, deploy, and verify
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
yarn build && yarn jahia-deploy
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Verify the component registered:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
docker logs $(docker ps --format '{{.Names}}' | grep -i jahia | head -1) 2>&1 \
|
|
230
|
+
| grep "Registered Jahia component" | grep "<ComponentName>"
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Expected: one line per view. If absent, check the build output for TypeScript errors in the new view file.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Rules that always apply
|
|
238
|
+
|
|
239
|
+
- **CSS Modules for authored styles** — use `classes.propertyName`, not plain string class names
|
|
240
|
+
- **Vendor class names stay as-is** — when importing external CSS, don't route those classes through CSS Modules
|
|
241
|
+
- **No hardcoded links** — `href` and `src` must come from JCR props or `buildModuleFileUrl`
|
|
242
|
+
- **Island for anything interactive** — animations, browser events, `useState`, third-party JS → `.client.tsx`
|
|
243
|
+
- **All props optional in `types.ts`** — even CND `mandatory` fields
|
|
244
|
+
- **Edit mode awareness** — carousels, sliders, and tabs should render flat in edit mode
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: jahia-dev-jexperience
|
|
3
|
+
description: Integrate a Jahia JavaScript module with jExperience and jCustomer — set up the local stack, push visitor events from client components, visualize data in Kibana, and package dashboards for deployment.
|
|
4
|
+
allowed-tools: Bash, Read, Write, Edit
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## What is jExperience / jCustomer?
|
|
8
|
+
|
|
9
|
+
**jCustomer** (built on Apache Unomi) collects and processes visitor events to create personalized digital experiences. **jExperience** is the Jahia module that bridges Jahia with jCustomer — it injects the `window.wem` tracker into every page and exposes dashboards inside jContent.
|
|
10
|
+
|
|
11
|
+
Together they form Jahia's **DXP** (Digital Experience Platform). You only need this skill when you want to track interactions, build personalization, or visualize visitor data.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Step 1 — Set up jCustomer locally
|
|
16
|
+
|
|
17
|
+
### 1a — Update `docker-compose.yml`
|
|
18
|
+
|
|
19
|
+
Give the `jahia` service a static IP, add three containers, and declare the subnet:
|
|
20
|
+
|
|
21
|
+
```yaml
|
|
22
|
+
services:
|
|
23
|
+
jahia:
|
|
24
|
+
# ... existing config ...
|
|
25
|
+
networks:
|
|
26
|
+
default:
|
|
27
|
+
ipv4_address: 172.16.1.100
|
|
28
|
+
|
|
29
|
+
elasticsearch:
|
|
30
|
+
image: elasticsearch:7.17.28
|
|
31
|
+
ports:
|
|
32
|
+
- 9200:9200
|
|
33
|
+
environment:
|
|
34
|
+
discovery.type: single-node
|
|
35
|
+
cluster.name: jahia-es-cluster
|
|
36
|
+
|
|
37
|
+
kibana:
|
|
38
|
+
image: kibana:7.17.28
|
|
39
|
+
ports:
|
|
40
|
+
- 5601:5601
|
|
41
|
+
environment:
|
|
42
|
+
discovery.type: single-node
|
|
43
|
+
elasticsearch.hosts: http://elasticsearch:9200
|
|
44
|
+
|
|
45
|
+
jcustomer:
|
|
46
|
+
image: jahia/jcustomer:2.6
|
|
47
|
+
depends_on:
|
|
48
|
+
- elasticsearch
|
|
49
|
+
ports:
|
|
50
|
+
- 9443:9443
|
|
51
|
+
- 8181:8181
|
|
52
|
+
- 8102:8102
|
|
53
|
+
environment:
|
|
54
|
+
UNOMI_ELASTICSEARCH_ADDRESSES: elasticsearch:9200
|
|
55
|
+
UNOMI_ELASTICSEARCH_CLUSTERNAME: jahia-es-cluster
|
|
56
|
+
UNOMI_CLUSTER_PUBLIC_ADDRESS: http://localhost:8181
|
|
57
|
+
UNOMI_CLUSTER_INTERNAL_ADDRESS: https://jcustomer:9443
|
|
58
|
+
UNOMI_THIRDPARTY_PROVIDER1_IPADDRESSES: 172.16.1.100
|
|
59
|
+
UNOMI_THIRDPARTY_PROVIDER1_ALLOWEDEVENTS: login,updateProperties
|
|
60
|
+
UNOMI_ROOT_PASSWORD: karaf
|
|
61
|
+
UNOMI_HAZELCAST_TCPIP_MEMBERS: jcustomer
|
|
62
|
+
|
|
63
|
+
networks:
|
|
64
|
+
default:
|
|
65
|
+
ipam:
|
|
66
|
+
config:
|
|
67
|
+
- subnet: 172.16.1.0/24
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 1b — Update `docker/provisioning.yml`
|
|
71
|
+
|
|
72
|
+
Append at the end of the file:
|
|
73
|
+
|
|
74
|
+
```yaml
|
|
75
|
+
# Install and start jExperience
|
|
76
|
+
- installModule:
|
|
77
|
+
- "mvn:org.jahia.modules/jexperience/3.6.2"
|
|
78
|
+
- "mvn:org.jahia.modules/jexperience-dashboards/1.0.0"
|
|
79
|
+
autoStart: true
|
|
80
|
+
uninstallPreviousVersion: true
|
|
81
|
+
|
|
82
|
+
# Connect jExperience to jCustomer
|
|
83
|
+
- editConfiguration: "org.jahia.modules.jexperience.settings"
|
|
84
|
+
configIdentifier: "global"
|
|
85
|
+
properties:
|
|
86
|
+
jexperience.jCustomerURL: "https://jcustomer:9443"
|
|
87
|
+
jexperience.jCustomerUsername: "karaf"
|
|
88
|
+
jexperience.jCustomerPassword: "karaf"
|
|
89
|
+
jexperience.jCustomerTrustAllCertificates: "true"
|
|
90
|
+
jexperience.jCustomerUsePublicAddressesForAdmin: "false"
|
|
91
|
+
jexperience.jCustomerKey: "670c26d1cc413346c3b2fd9ce65dab41"
|
|
92
|
+
|
|
93
|
+
# Configure Kibana dashboards proxy
|
|
94
|
+
- editConfiguration: "org.jahia.modules.kibana_dashboards_provider"
|
|
95
|
+
properties:
|
|
96
|
+
kibana_dashboards_provider.kibanaURL: "http://kibana:5601"
|
|
97
|
+
kibana_dashboards_provider.kibanaUser: "elastic"
|
|
98
|
+
kibana_dashboards_provider.kibanaPassword: "ELASTIC_PASSWORD"
|
|
99
|
+
kibana_dashboards_provider.KibanaProxy.enable: "true"
|
|
100
|
+
kibana_dashboards_provider.KibanaProxy.cloud: "true"
|
|
101
|
+
- installModule:
|
|
102
|
+
- "mvn:org.jahia.modules/kibana-dashboards-provider/1.4.0"
|
|
103
|
+
autoStart: true
|
|
104
|
+
uninstallPreviousVersion: true
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 1c — Start the stack
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
docker compose down jahia && docker compose up --wait
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 1d — Enable jExperience on the site
|
|
114
|
+
|
|
115
|
+
1. Open **Administration → Modules → jExperience → Usage in sites**
|
|
116
|
+
2. Check the box next to your site. Repeat for **jExperience Dashboards**.
|
|
117
|
+
3. Open jContent — a new **jExperience** tab should appear in the vertical bar (refresh if needed).
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Step 2 — Push events from a client component
|
|
122
|
+
|
|
123
|
+
jExperience injects `window.wem` (Web Experience Manager) into every page. It is only available in the browser — use it inside `.client.tsx` files.
|
|
124
|
+
|
|
125
|
+
### Event model
|
|
126
|
+
|
|
127
|
+
Every event has two parts:
|
|
128
|
+
|
|
129
|
+
| Part | What it is | Helper |
|
|
130
|
+
|------|------------|--------|
|
|
131
|
+
| **source** | Where the event happened (usually the current page) | `wem.buildSourcePage()` |
|
|
132
|
+
| **target** | What happened (the action) | `wem.buildTarget(id, type, properties)` |
|
|
133
|
+
|
|
134
|
+
### Full example — feedback widget
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
// src/components/FeedbackWidget/definition.cnd
|
|
138
|
+
// [hydrogen:feedbackWidget] > jnt:content, hydrogenmix:component
|
|
139
|
+
// - question (string) = 'Was this helpful?'
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
// Widget.client.tsx
|
|
144
|
+
import { useState } from "react";
|
|
145
|
+
|
|
146
|
+
export default function Widget({ question }: { question: string }) {
|
|
147
|
+
const [sent, setSent] = useState(false);
|
|
148
|
+
|
|
149
|
+
const handler = (happy: boolean) => () => {
|
|
150
|
+
const source = wem.buildSourcePage();
|
|
151
|
+
const target = wem.buildTarget("feedback", "click", { happy });
|
|
152
|
+
const event = wem.buildEvent("click", target, source);
|
|
153
|
+
wem.collectEvents({ events: [event] });
|
|
154
|
+
setSent(true);
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
if (sent) return <aside>Thank you for your feedback!</aside>;
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<aside>
|
|
161
|
+
{question}
|
|
162
|
+
<button type="button" onClick={handler(true)}>Yes</button>
|
|
163
|
+
<button type="button" onClick={handler(false)}>No</button>
|
|
164
|
+
</aside>
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
```tsx
|
|
170
|
+
// default.server.tsx
|
|
171
|
+
import { jahiaComponent, Island } from "@jahia/javascript-modules-library";
|
|
172
|
+
import Widget from "./Widget.client.jsx";
|
|
173
|
+
|
|
174
|
+
interface Props { question: string; }
|
|
175
|
+
|
|
176
|
+
jahiaComponent(
|
|
177
|
+
{ nodeType: "hydrogen:feedbackWidget", componentType: "view" },
|
|
178
|
+
({ question }: Props) => (
|
|
179
|
+
<Island clientOnly component={Widget} props={{ question }}>
|
|
180
|
+
Loading…
|
|
181
|
+
</Island>
|
|
182
|
+
),
|
|
183
|
+
);
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### `window.wem` API reference
|
|
187
|
+
|
|
188
|
+
| Method | Signature | Returns |
|
|
189
|
+
|--------|-----------|---------|
|
|
190
|
+
| `buildSourcePage` | `()` | Source object for the current page |
|
|
191
|
+
| `buildTarget` | `(id: string, type: string, properties?: object)` | Target object |
|
|
192
|
+
| `buildEvent` | `(eventType: string, target, source)` | Event object |
|
|
193
|
+
| `collectEvents` | `({ events: Event[] })` | Sends events to jCustomer |
|
|
194
|
+
|
|
195
|
+
`buildTarget` properties are free-form — pass any serializable data you want to analyse downstream (e.g. `{ happy: true }`, `{ productId: "p-123" }`).
|
|
196
|
+
|
|
197
|
+
> The `window.wem` object comes from the [apache/unomi-tracker](https://github.com/apache/unomi-tracker) package. Refer to its documentation for advanced event types.
|
|
198
|
+
|
|
199
|
+
### Google Tag Manager alternative
|
|
200
|
+
|
|
201
|
+
If your site uses GTM instead of jCustomer:
|
|
202
|
+
|
|
203
|
+
```tsx
|
|
204
|
+
dataLayer.push({ event: "feedback", happy });
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Step 3 — Verify events in Kibana
|
|
210
|
+
|
|
211
|
+
1. Open [localhost:5601](http://localhost:5601)
|
|
212
|
+
2. Go to **Discover**, select the `*-event` index, and expand the time range
|
|
213
|
+
3. Browse an event — confirm the `source.properties.pageInfo.pagePath` and `target.properties.happy` fields are present
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Step 4 — Create a Kibana dashboard
|
|
218
|
+
|
|
219
|
+
### Create a saved search
|
|
220
|
+
|
|
221
|
+
In **Discover**, add column filters for:
|
|
222
|
+
- `eventType` = `click`
|
|
223
|
+
- `itemType` = `event`
|
|
224
|
+
- `target.itemId` = `feedback`
|
|
225
|
+
- `target.itemType` = `click`
|
|
226
|
+
|
|
227
|
+
Add display columns: `source.properties.pageInfo.pagePath`, `target.properties.happy`. Save as e.g. **All Feedbacks**.
|
|
228
|
+
|
|
229
|
+
### Create the dashboard
|
|
230
|
+
|
|
231
|
+
1. **Dashboards → Create dashboard**
|
|
232
|
+
2. **Add from library** → add the saved search (table of all feedbacks)
|
|
233
|
+
3. **Create visualization** → paste this KQL filter into the search bar:
|
|
234
|
+
```
|
|
235
|
+
eventType: click and itemType: event and target.itemId: feedback and target.itemType: click
|
|
236
|
+
```
|
|
237
|
+
4. Drop **Records** onto the panel, then in **Break down by** select `target.properties.happy`. Use the **Status** color palette for red/green.
|
|
238
|
+
5. **Save and return**, then **Save** the dashboard with a meaningful name — this name becomes the entry label inside Jahia's jExperience tab.
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Step 5 — Package the dashboard in the module
|
|
243
|
+
|
|
244
|
+
Dashboards exported from Kibana are automatically imported when the module is deployed.
|
|
245
|
+
|
|
246
|
+
1. In Kibana go to **Analytics → Overview → Manage → Saved Objects**
|
|
247
|
+
2. Select your dashboard, click **Export** — you get a `.ndjson` file
|
|
248
|
+
3. Save it to your module:
|
|
249
|
+
```
|
|
250
|
+
settings/kibana-dashboard/dashboards/<dashboard-name>.ndjson
|
|
251
|
+
```
|
|
252
|
+
4. Deploy the module — the dashboard will appear in the jExperience tab on any Jahia instance running the module.
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Validation checklist
|
|
257
|
+
- [ ] `docker compose up --wait` completed with elasticsearch, kibana, jcustomer healthy
|
|
258
|
+
- [ ] jExperience and jExperience Dashboards enabled on the target site
|
|
259
|
+
- [ ] jExperience tab visible in jContent
|
|
260
|
+
- [ ] Client component uses `.client.tsx` extension and `Island clientOnly`
|
|
261
|
+
- [ ] `wem.collectEvents` called with a valid event (source + target)
|
|
262
|
+
- [ ] Events visible in Kibana Discover under `*-event` index
|
|
263
|
+
- [ ] Dashboard saved and visible under the jExperience tab in Jahia
|
|
264
|
+
- [ ] Dashboard `.ndjson` saved to `settings/kibana-dashboard/dashboards/` for packaging
|
|
265
|
+
|
|
266
|
+
## References
|
|
267
|
+
- Apache Unomi tracker: https://github.com/apache/unomi-tracker
|
|
268
|
+
- KQL query syntax: https://www.elastic.co/guide/en/kibana/current/kuery-query.html
|
|
269
|
+
- jExperience guide: https://github.com/Jahia/javascript-modules/blob/main/docs/2-guides/1-building-a-feedback-form/README.md
|