@jahia/agentic 0.0.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.
- package/README.md +48 -0
- package/dist/claude/.claude/rules/jahia.md +76 -0
- package/dist/claude/.claude/skills/jahia/SKILL.md +136 -0
- package/dist/claude/.claude/skills/jahia-content/SKILL.md +139 -0
- package/dist/claude/.claude/skills/jahia-content-create-content/SKILL.md +384 -0
- package/dist/claude/.claude/skills/jahia-content-explore-structure/SKILL.md +164 -0
- package/dist/claude/.claude/skills/jahia-content-move-content/SKILL.md +236 -0
- package/dist/claude/.claude/skills/jahia-content-query-content/SKILL.md +144 -0
- package/dist/claude/.claude/skills/jahia-content-translate-content/SKILL.md +297 -0
- package/dist/claude/.claude/skills/jahia-dev/SKILL.md +124 -0
- package/dist/claude/.claude/skills/jahia-dev-accessibility/SKILL.md +271 -0
- package/dist/claude/.claude/skills/jahia-dev-apis/SKILL.md +52 -0
- package/dist/claude/.claude/skills/jahia-dev-apis/references/authentication.md +484 -0
- package/dist/claude/.claude/skills/jahia-dev-apis/references/graphql.md +657 -0
- package/dist/claude/.claude/skills/jahia-dev-apis/references/jcr-api.md +465 -0
- package/dist/claude/.claude/skills/jahia-dev-apis/references/security.md +541 -0
- package/dist/claude/.claude/skills/jahia-dev-build-component/SKILL.md +140 -0
- package/dist/claude/.claude/skills/jahia-dev-create-page-template/SKILL.md +303 -0
- package/dist/claude/.claude/skills/jahia-dev-create-template-set/SKILL.md +232 -0
- package/dist/claude/.claude/skills/jahia-dev-create-view/SKILL.md +838 -0
- package/dist/claude/.claude/skills/jahia-dev-cypress/SKILL.md +445 -0
- package/dist/claude/.claude/skills/jahia-dev-debug/SKILL.md +176 -0
- package/dist/claude/.claude/skills/jahia-dev-define-content-type/SKILL.md +536 -0
- package/dist/claude/.claude/skills/jahia-dev-import-from/SKILL.md +244 -0
- package/dist/claude/.claude/skills/jahia-dev-java/SKILL.md +105 -0
- package/dist/claude/.claude/skills/jahia-dev-java/references/backend.md +331 -0
- package/dist/claude/.claude/skills/jahia-dev-java/references/content-types.md +273 -0
- package/dist/claude/.claude/skills/jahia-dev-java/references/modules.md +218 -0
- package/dist/claude/.claude/skills/jahia-dev-java/references/osgi.md +208 -0
- package/dist/claude/.claude/skills/jahia-dev-java/references/rendering.md +191 -0
- package/dist/claude/.claude/skills/jahia-dev-java/references/ui-extensions.md +344 -0
- package/dist/claude/.claude/skills/jahia-dev-jexperience/SKILL.md +269 -0
- package/dist/claude/.claude/skills/jahia-dev-ops/SKILL.md +50 -0
- package/dist/claude/.claude/skills/jahia-dev-ops/references/docker.md +151 -0
- package/dist/claude/.claude/skills/jahia-dev-ops/references/monitoring.md +195 -0
- package/dist/claude/.claude/skills/jahia-dev-ops/references/provisioning.md +269 -0
- package/dist/claude/.claude/skills/jahia-dev-osgi-module/SKILL.md +297 -0
- package/dist/claude/.claude/skills/jahia-dev-properties/SKILL.md +147 -0
- package/dist/claude/.claude/skills/jahia-dev-properties/references/all-properties.md +231 -0
- package/dist/claude/.claude/skills/jahia-dev-query-content/SKILL.md +407 -0
- package/dist/claude/.claude/skills/jahia-dev-review/SKILL.md +228 -0
- package/dist/claude/.claude/skills/jahia-dev-screenshot/SKILL.md +177 -0
- package/dist/claude/.claude/skills/jahia-dev-start-local/SKILL.md +129 -0
- package/dist/claude/.claude/skills/jahia-dev-ui-extension/SKILL.md +559 -0
- package/dist/claude/CLAUDE.md +90 -0
- package/dist/codex/.agents/skills/jahia/SKILL.md +136 -0
- package/dist/codex/.agents/skills/jahia-content/SKILL.md +139 -0
- package/dist/codex/.agents/skills/jahia-content-create-content/SKILL.md +384 -0
- package/dist/codex/.agents/skills/jahia-content-explore-structure/SKILL.md +164 -0
- package/dist/codex/.agents/skills/jahia-content-move-content/SKILL.md +236 -0
- package/dist/codex/.agents/skills/jahia-content-query-content/SKILL.md +144 -0
- package/dist/codex/.agents/skills/jahia-content-translate-content/SKILL.md +297 -0
- package/dist/codex/.agents/skills/jahia-dev/SKILL.md +124 -0
- package/dist/codex/.agents/skills/jahia-dev-accessibility/SKILL.md +271 -0
- package/dist/codex/.agents/skills/jahia-dev-apis/SKILL.md +52 -0
- package/dist/codex/.agents/skills/jahia-dev-apis/references/authentication.md +484 -0
- package/dist/codex/.agents/skills/jahia-dev-apis/references/graphql.md +657 -0
- package/dist/codex/.agents/skills/jahia-dev-apis/references/jcr-api.md +465 -0
- package/dist/codex/.agents/skills/jahia-dev-apis/references/security.md +541 -0
- package/dist/codex/.agents/skills/jahia-dev-build-component/SKILL.md +140 -0
- package/dist/codex/.agents/skills/jahia-dev-create-page-template/SKILL.md +303 -0
- package/dist/codex/.agents/skills/jahia-dev-create-template-set/SKILL.md +232 -0
- package/dist/codex/.agents/skills/jahia-dev-create-view/SKILL.md +838 -0
- package/dist/codex/.agents/skills/jahia-dev-cypress/SKILL.md +445 -0
- package/dist/codex/.agents/skills/jahia-dev-debug/SKILL.md +176 -0
- package/dist/codex/.agents/skills/jahia-dev-define-content-type/SKILL.md +536 -0
- package/dist/codex/.agents/skills/jahia-dev-import-from/SKILL.md +244 -0
- package/dist/codex/.agents/skills/jahia-dev-java/SKILL.md +105 -0
- package/dist/codex/.agents/skills/jahia-dev-java/references/backend.md +331 -0
- package/dist/codex/.agents/skills/jahia-dev-java/references/content-types.md +273 -0
- package/dist/codex/.agents/skills/jahia-dev-java/references/modules.md +218 -0
- package/dist/codex/.agents/skills/jahia-dev-java/references/osgi.md +208 -0
- package/dist/codex/.agents/skills/jahia-dev-java/references/rendering.md +191 -0
- package/dist/codex/.agents/skills/jahia-dev-java/references/ui-extensions.md +344 -0
- package/dist/codex/.agents/skills/jahia-dev-jexperience/SKILL.md +269 -0
- package/dist/codex/.agents/skills/jahia-dev-ops/SKILL.md +50 -0
- package/dist/codex/.agents/skills/jahia-dev-ops/references/docker.md +151 -0
- package/dist/codex/.agents/skills/jahia-dev-ops/references/monitoring.md +195 -0
- package/dist/codex/.agents/skills/jahia-dev-ops/references/provisioning.md +269 -0
- package/dist/codex/.agents/skills/jahia-dev-osgi-module/SKILL.md +297 -0
- package/dist/codex/.agents/skills/jahia-dev-properties/SKILL.md +147 -0
- package/dist/codex/.agents/skills/jahia-dev-properties/references/all-properties.md +231 -0
- package/dist/codex/.agents/skills/jahia-dev-query-content/SKILL.md +407 -0
- package/dist/codex/.agents/skills/jahia-dev-review/SKILL.md +228 -0
- package/dist/codex/.agents/skills/jahia-dev-screenshot/SKILL.md +177 -0
- package/dist/codex/.agents/skills/jahia-dev-start-local/SKILL.md +129 -0
- package/dist/codex/.agents/skills/jahia-dev-ui-extension/SKILL.md +559 -0
- package/dist/codex/AGENTS.md +89 -0
- package/dist/copilot/.agents/skills/jahia/SKILL.md +136 -0
- package/dist/copilot/.agents/skills/jahia-content/SKILL.md +139 -0
- package/dist/copilot/.agents/skills/jahia-content-create-content/SKILL.md +384 -0
- package/dist/copilot/.agents/skills/jahia-content-explore-structure/SKILL.md +164 -0
- package/dist/copilot/.agents/skills/jahia-content-move-content/SKILL.md +236 -0
- package/dist/copilot/.agents/skills/jahia-content-query-content/SKILL.md +144 -0
- package/dist/copilot/.agents/skills/jahia-content-translate-content/SKILL.md +297 -0
- package/dist/copilot/.agents/skills/jahia-dev/SKILL.md +124 -0
- package/dist/copilot/.agents/skills/jahia-dev-accessibility/SKILL.md +271 -0
- package/dist/copilot/.agents/skills/jahia-dev-apis/SKILL.md +52 -0
- package/dist/copilot/.agents/skills/jahia-dev-apis/references/authentication.md +484 -0
- package/dist/copilot/.agents/skills/jahia-dev-apis/references/graphql.md +657 -0
- package/dist/copilot/.agents/skills/jahia-dev-apis/references/jcr-api.md +465 -0
- package/dist/copilot/.agents/skills/jahia-dev-apis/references/security.md +541 -0
- package/dist/copilot/.agents/skills/jahia-dev-build-component/SKILL.md +140 -0
- package/dist/copilot/.agents/skills/jahia-dev-create-page-template/SKILL.md +303 -0
- package/dist/copilot/.agents/skills/jahia-dev-create-template-set/SKILL.md +232 -0
- package/dist/copilot/.agents/skills/jahia-dev-create-view/SKILL.md +838 -0
- package/dist/copilot/.agents/skills/jahia-dev-cypress/SKILL.md +445 -0
- package/dist/copilot/.agents/skills/jahia-dev-debug/SKILL.md +176 -0
- package/dist/copilot/.agents/skills/jahia-dev-define-content-type/SKILL.md +536 -0
- package/dist/copilot/.agents/skills/jahia-dev-import-from/SKILL.md +244 -0
- package/dist/copilot/.agents/skills/jahia-dev-java/SKILL.md +105 -0
- package/dist/copilot/.agents/skills/jahia-dev-java/references/backend.md +331 -0
- package/dist/copilot/.agents/skills/jahia-dev-java/references/content-types.md +273 -0
- package/dist/copilot/.agents/skills/jahia-dev-java/references/modules.md +218 -0
- package/dist/copilot/.agents/skills/jahia-dev-java/references/osgi.md +208 -0
- package/dist/copilot/.agents/skills/jahia-dev-java/references/rendering.md +191 -0
- package/dist/copilot/.agents/skills/jahia-dev-java/references/ui-extensions.md +344 -0
- package/dist/copilot/.agents/skills/jahia-dev-jexperience/SKILL.md +269 -0
- package/dist/copilot/.agents/skills/jahia-dev-ops/SKILL.md +50 -0
- package/dist/copilot/.agents/skills/jahia-dev-ops/references/docker.md +151 -0
- package/dist/copilot/.agents/skills/jahia-dev-ops/references/monitoring.md +195 -0
- package/dist/copilot/.agents/skills/jahia-dev-ops/references/provisioning.md +269 -0
- package/dist/copilot/.agents/skills/jahia-dev-osgi-module/SKILL.md +297 -0
- package/dist/copilot/.agents/skills/jahia-dev-properties/SKILL.md +147 -0
- package/dist/copilot/.agents/skills/jahia-dev-properties/references/all-properties.md +231 -0
- package/dist/copilot/.agents/skills/jahia-dev-query-content/SKILL.md +407 -0
- package/dist/copilot/.agents/skills/jahia-dev-review/SKILL.md +228 -0
- package/dist/copilot/.agents/skills/jahia-dev-screenshot/SKILL.md +177 -0
- package/dist/copilot/.agents/skills/jahia-dev-start-local/SKILL.md +129 -0
- package/dist/copilot/.agents/skills/jahia-dev-ui-extension/SKILL.md +559 -0
- package/dist/copilot/AGENTS.md +89 -0
- package/dist/cursor/.agents/skills/jahia/SKILL.md +136 -0
- package/dist/cursor/.agents/skills/jahia-content/SKILL.md +139 -0
- package/dist/cursor/.agents/skills/jahia-content-create-content/SKILL.md +384 -0
- package/dist/cursor/.agents/skills/jahia-content-explore-structure/SKILL.md +164 -0
- package/dist/cursor/.agents/skills/jahia-content-move-content/SKILL.md +236 -0
- package/dist/cursor/.agents/skills/jahia-content-query-content/SKILL.md +144 -0
- package/dist/cursor/.agents/skills/jahia-content-translate-content/SKILL.md +297 -0
- package/dist/cursor/.agents/skills/jahia-dev/SKILL.md +124 -0
- package/dist/cursor/.agents/skills/jahia-dev-accessibility/SKILL.md +271 -0
- package/dist/cursor/.agents/skills/jahia-dev-apis/SKILL.md +52 -0
- package/dist/cursor/.agents/skills/jahia-dev-apis/references/authentication.md +484 -0
- package/dist/cursor/.agents/skills/jahia-dev-apis/references/graphql.md +657 -0
- package/dist/cursor/.agents/skills/jahia-dev-apis/references/jcr-api.md +465 -0
- package/dist/cursor/.agents/skills/jahia-dev-apis/references/security.md +541 -0
- package/dist/cursor/.agents/skills/jahia-dev-build-component/SKILL.md +140 -0
- package/dist/cursor/.agents/skills/jahia-dev-create-page-template/SKILL.md +303 -0
- package/dist/cursor/.agents/skills/jahia-dev-create-template-set/SKILL.md +232 -0
- package/dist/cursor/.agents/skills/jahia-dev-create-view/SKILL.md +838 -0
- package/dist/cursor/.agents/skills/jahia-dev-cypress/SKILL.md +445 -0
- package/dist/cursor/.agents/skills/jahia-dev-debug/SKILL.md +176 -0
- package/dist/cursor/.agents/skills/jahia-dev-define-content-type/SKILL.md +536 -0
- package/dist/cursor/.agents/skills/jahia-dev-import-from/SKILL.md +244 -0
- package/dist/cursor/.agents/skills/jahia-dev-java/SKILL.md +105 -0
- package/dist/cursor/.agents/skills/jahia-dev-java/references/backend.md +331 -0
- package/dist/cursor/.agents/skills/jahia-dev-java/references/content-types.md +273 -0
- package/dist/cursor/.agents/skills/jahia-dev-java/references/modules.md +218 -0
- package/dist/cursor/.agents/skills/jahia-dev-java/references/osgi.md +208 -0
- package/dist/cursor/.agents/skills/jahia-dev-java/references/rendering.md +191 -0
- package/dist/cursor/.agents/skills/jahia-dev-java/references/ui-extensions.md +344 -0
- package/dist/cursor/.agents/skills/jahia-dev-jexperience/SKILL.md +269 -0
- package/dist/cursor/.agents/skills/jahia-dev-ops/SKILL.md +50 -0
- package/dist/cursor/.agents/skills/jahia-dev-ops/references/docker.md +151 -0
- package/dist/cursor/.agents/skills/jahia-dev-ops/references/monitoring.md +195 -0
- package/dist/cursor/.agents/skills/jahia-dev-ops/references/provisioning.md +269 -0
- package/dist/cursor/.agents/skills/jahia-dev-osgi-module/SKILL.md +297 -0
- package/dist/cursor/.agents/skills/jahia-dev-properties/SKILL.md +147 -0
- package/dist/cursor/.agents/skills/jahia-dev-properties/references/all-properties.md +231 -0
- package/dist/cursor/.agents/skills/jahia-dev-query-content/SKILL.md +407 -0
- package/dist/cursor/.agents/skills/jahia-dev-review/SKILL.md +228 -0
- package/dist/cursor/.agents/skills/jahia-dev-screenshot/SKILL.md +177 -0
- package/dist/cursor/.agents/skills/jahia-dev-start-local/SKILL.md +129 -0
- package/dist/cursor/.agents/skills/jahia-dev-ui-extension/SKILL.md +559 -0
- package/dist/cursor/.cursor/rules/jahia.mdc +80 -0
- package/dist/gemini/.agents/skills/jahia/SKILL.md +136 -0
- package/dist/gemini/.agents/skills/jahia-content/SKILL.md +139 -0
- package/dist/gemini/.agents/skills/jahia-content-create-content/SKILL.md +384 -0
- package/dist/gemini/.agents/skills/jahia-content-explore-structure/SKILL.md +164 -0
- package/dist/gemini/.agents/skills/jahia-content-move-content/SKILL.md +236 -0
- package/dist/gemini/.agents/skills/jahia-content-query-content/SKILL.md +144 -0
- package/dist/gemini/.agents/skills/jahia-content-translate-content/SKILL.md +297 -0
- package/dist/gemini/.agents/skills/jahia-dev/SKILL.md +124 -0
- package/dist/gemini/.agents/skills/jahia-dev-accessibility/SKILL.md +271 -0
- package/dist/gemini/.agents/skills/jahia-dev-apis/SKILL.md +52 -0
- package/dist/gemini/.agents/skills/jahia-dev-apis/references/authentication.md +484 -0
- package/dist/gemini/.agents/skills/jahia-dev-apis/references/graphql.md +657 -0
- package/dist/gemini/.agents/skills/jahia-dev-apis/references/jcr-api.md +465 -0
- package/dist/gemini/.agents/skills/jahia-dev-apis/references/security.md +541 -0
- package/dist/gemini/.agents/skills/jahia-dev-build-component/SKILL.md +140 -0
- package/dist/gemini/.agents/skills/jahia-dev-create-page-template/SKILL.md +303 -0
- package/dist/gemini/.agents/skills/jahia-dev-create-template-set/SKILL.md +232 -0
- package/dist/gemini/.agents/skills/jahia-dev-create-view/SKILL.md +838 -0
- package/dist/gemini/.agents/skills/jahia-dev-cypress/SKILL.md +445 -0
- package/dist/gemini/.agents/skills/jahia-dev-debug/SKILL.md +176 -0
- package/dist/gemini/.agents/skills/jahia-dev-define-content-type/SKILL.md +536 -0
- package/dist/gemini/.agents/skills/jahia-dev-import-from/SKILL.md +244 -0
- package/dist/gemini/.agents/skills/jahia-dev-java/SKILL.md +105 -0
- package/dist/gemini/.agents/skills/jahia-dev-java/references/backend.md +331 -0
- package/dist/gemini/.agents/skills/jahia-dev-java/references/content-types.md +273 -0
- package/dist/gemini/.agents/skills/jahia-dev-java/references/modules.md +218 -0
- package/dist/gemini/.agents/skills/jahia-dev-java/references/osgi.md +208 -0
- package/dist/gemini/.agents/skills/jahia-dev-java/references/rendering.md +191 -0
- package/dist/gemini/.agents/skills/jahia-dev-java/references/ui-extensions.md +344 -0
- package/dist/gemini/.agents/skills/jahia-dev-jexperience/SKILL.md +269 -0
- package/dist/gemini/.agents/skills/jahia-dev-ops/SKILL.md +50 -0
- package/dist/gemini/.agents/skills/jahia-dev-ops/references/docker.md +151 -0
- package/dist/gemini/.agents/skills/jahia-dev-ops/references/monitoring.md +195 -0
- package/dist/gemini/.agents/skills/jahia-dev-ops/references/provisioning.md +269 -0
- package/dist/gemini/.agents/skills/jahia-dev-osgi-module/SKILL.md +297 -0
- package/dist/gemini/.agents/skills/jahia-dev-properties/SKILL.md +147 -0
- package/dist/gemini/.agents/skills/jahia-dev-properties/references/all-properties.md +231 -0
- package/dist/gemini/.agents/skills/jahia-dev-query-content/SKILL.md +407 -0
- package/dist/gemini/.agents/skills/jahia-dev-review/SKILL.md +228 -0
- package/dist/gemini/.agents/skills/jahia-dev-screenshot/SKILL.md +177 -0
- package/dist/gemini/.agents/skills/jahia-dev-start-local/SKILL.md +129 -0
- package/dist/gemini/.agents/skills/jahia-dev-ui-extension/SKILL.md +559 -0
- package/dist/gemini/AGENTS.md +89 -0
- package/dist/gemini/GEMINI.md +6 -0
- package/dist/index.js +975 -0
- package/dist/opencode/.agents/skills/jahia/SKILL.md +136 -0
- package/dist/opencode/.agents/skills/jahia-content/SKILL.md +139 -0
- package/dist/opencode/.agents/skills/jahia-content-create-content/SKILL.md +384 -0
- package/dist/opencode/.agents/skills/jahia-content-explore-structure/SKILL.md +164 -0
- package/dist/opencode/.agents/skills/jahia-content-move-content/SKILL.md +236 -0
- package/dist/opencode/.agents/skills/jahia-content-query-content/SKILL.md +144 -0
- package/dist/opencode/.agents/skills/jahia-content-translate-content/SKILL.md +297 -0
- package/dist/opencode/.agents/skills/jahia-dev/SKILL.md +124 -0
- package/dist/opencode/.agents/skills/jahia-dev-accessibility/SKILL.md +271 -0
- package/dist/opencode/.agents/skills/jahia-dev-apis/SKILL.md +52 -0
- package/dist/opencode/.agents/skills/jahia-dev-apis/references/authentication.md +484 -0
- package/dist/opencode/.agents/skills/jahia-dev-apis/references/graphql.md +657 -0
- package/dist/opencode/.agents/skills/jahia-dev-apis/references/jcr-api.md +465 -0
- package/dist/opencode/.agents/skills/jahia-dev-apis/references/security.md +541 -0
- package/dist/opencode/.agents/skills/jahia-dev-build-component/SKILL.md +140 -0
- package/dist/opencode/.agents/skills/jahia-dev-create-page-template/SKILL.md +303 -0
- package/dist/opencode/.agents/skills/jahia-dev-create-template-set/SKILL.md +232 -0
- package/dist/opencode/.agents/skills/jahia-dev-create-view/SKILL.md +838 -0
- package/dist/opencode/.agents/skills/jahia-dev-cypress/SKILL.md +445 -0
- package/dist/opencode/.agents/skills/jahia-dev-debug/SKILL.md +176 -0
- package/dist/opencode/.agents/skills/jahia-dev-define-content-type/SKILL.md +536 -0
- package/dist/opencode/.agents/skills/jahia-dev-import-from/SKILL.md +244 -0
- package/dist/opencode/.agents/skills/jahia-dev-java/SKILL.md +105 -0
- package/dist/opencode/.agents/skills/jahia-dev-java/references/backend.md +331 -0
- package/dist/opencode/.agents/skills/jahia-dev-java/references/content-types.md +273 -0
- package/dist/opencode/.agents/skills/jahia-dev-java/references/modules.md +218 -0
- package/dist/opencode/.agents/skills/jahia-dev-java/references/osgi.md +208 -0
- package/dist/opencode/.agents/skills/jahia-dev-java/references/rendering.md +191 -0
- package/dist/opencode/.agents/skills/jahia-dev-java/references/ui-extensions.md +344 -0
- package/dist/opencode/.agents/skills/jahia-dev-jexperience/SKILL.md +269 -0
- package/dist/opencode/.agents/skills/jahia-dev-ops/SKILL.md +50 -0
- package/dist/opencode/.agents/skills/jahia-dev-ops/references/docker.md +151 -0
- package/dist/opencode/.agents/skills/jahia-dev-ops/references/monitoring.md +195 -0
- package/dist/opencode/.agents/skills/jahia-dev-ops/references/provisioning.md +269 -0
- package/dist/opencode/.agents/skills/jahia-dev-osgi-module/SKILL.md +297 -0
- package/dist/opencode/.agents/skills/jahia-dev-properties/SKILL.md +147 -0
- package/dist/opencode/.agents/skills/jahia-dev-properties/references/all-properties.md +231 -0
- package/dist/opencode/.agents/skills/jahia-dev-query-content/SKILL.md +407 -0
- package/dist/opencode/.agents/skills/jahia-dev-review/SKILL.md +228 -0
- package/dist/opencode/.agents/skills/jahia-dev-screenshot/SKILL.md +177 -0
- package/dist/opencode/.agents/skills/jahia-dev-start-local/SKILL.md +129 -0
- package/dist/opencode/.agents/skills/jahia-dev-ui-extension/SKILL.md +559 -0
- package/dist/opencode/AGENTS.md +89 -0
- package/dist/windsurf/.windsurf/rules/jahia.md +80 -0
- package/dist/windsurf/.windsurf/skills/jahia/SKILL.md +136 -0
- package/dist/windsurf/.windsurf/skills/jahia-content/SKILL.md +139 -0
- package/dist/windsurf/.windsurf/skills/jahia-content-create-content/SKILL.md +384 -0
- package/dist/windsurf/.windsurf/skills/jahia-content-explore-structure/SKILL.md +164 -0
- package/dist/windsurf/.windsurf/skills/jahia-content-move-content/SKILL.md +236 -0
- package/dist/windsurf/.windsurf/skills/jahia-content-query-content/SKILL.md +144 -0
- package/dist/windsurf/.windsurf/skills/jahia-content-translate-content/SKILL.md +297 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev/SKILL.md +124 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-accessibility/SKILL.md +271 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-apis/SKILL.md +52 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-apis/references/authentication.md +484 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-apis/references/graphql.md +657 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-apis/references/jcr-api.md +465 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-apis/references/security.md +541 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-build-component/SKILL.md +140 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-create-page-template/SKILL.md +303 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-create-template-set/SKILL.md +232 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-create-view/SKILL.md +838 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-cypress/SKILL.md +445 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-debug/SKILL.md +176 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-define-content-type/SKILL.md +536 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-import-from/SKILL.md +244 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-java/SKILL.md +105 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-java/references/backend.md +331 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-java/references/content-types.md +273 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-java/references/modules.md +218 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-java/references/osgi.md +208 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-java/references/rendering.md +191 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-java/references/ui-extensions.md +344 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-jexperience/SKILL.md +269 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-ops/SKILL.md +50 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-ops/references/docker.md +151 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-ops/references/monitoring.md +195 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-ops/references/provisioning.md +269 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-osgi-module/SKILL.md +297 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-properties/SKILL.md +147 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-properties/references/all-properties.md +231 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-query-content/SKILL.md +407 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-review/SKILL.md +228 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-screenshot/SKILL.md +177 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-start-local/SKILL.md +129 -0
- package/dist/windsurf/.windsurf/skills/jahia-dev-ui-extension/SKILL.md +559 -0
- package/dist/windsurf/AGENTS.md +89 -0
- package/package.json +28 -0
|
@@ -0,0 +1,838 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: jahia-dev-create-view
|
|
3
|
+
description: Implements a React view for a Jahia content type. Use when asked to create or update the rendering of a component, add a new view, or add styling.
|
|
4
|
+
allowed-tools: Bash, Read, Write, Edit
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
A **view** tells Jahia how to render a content type. Views are React components (TypeScript/TSX) registered with the `jahiaComponent` function. They follow the **Single Directory Component (SDC)** pattern alongside the `definition.cnd`.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## File naming convention
|
|
14
|
+
|
|
15
|
+
| Filename | Meaning |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `default.server.tsx` | Default server-side rendered view |
|
|
18
|
+
| `<name>.server.tsx` | Named view (e.g. `small.server.tsx`) |
|
|
19
|
+
| `<name>.client.tsx` | Client-side rendered (interactive) view |
|
|
20
|
+
|
|
21
|
+
A node type can have **multiple views**. When `name` is omitted in `jahiaComponent`, the view is the default.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Step 1 — Create the view file
|
|
26
|
+
|
|
27
|
+
In the component folder (`src/components/<Category>/<Name>/`), create `default.server.tsx`:
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
import { jahiaComponent, buildNodeUrl, RenderChildren, RenderChild } from "@jahia/javascript-modules-library";
|
|
31
|
+
import type { Props } from "./types.js";
|
|
32
|
+
import classes from "./component.module.css";
|
|
33
|
+
|
|
34
|
+
jahiaComponent(
|
|
35
|
+
{
|
|
36
|
+
componentType: "view", // always "view" for a component (use "template" for page templates)
|
|
37
|
+
nodeType: "namespace:typeName",
|
|
38
|
+
displayName: "Human Readable Name",
|
|
39
|
+
// name: "small", // omit for default view; set for named views
|
|
40
|
+
},
|
|
41
|
+
({ title, subtitle, background }: Props) => (
|
|
42
|
+
<section className={classes.root}>
|
|
43
|
+
<h2>{title}</h2>
|
|
44
|
+
<p>{subtitle}</p>
|
|
45
|
+
</section>
|
|
46
|
+
),
|
|
47
|
+
);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`jahiaComponent` **returns its second argument** (the React component). Export it to reuse the component directly in other views:
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
// small.server.tsx — registered as a named view AND exported for direct reuse
|
|
54
|
+
export const SmallHero = jahiaComponent(
|
|
55
|
+
{ componentType: "view", nodeType: "ns:heroSection", name: "small" },
|
|
56
|
+
({ title, background }: Props) => <header style={{ backgroundImage: `url(${buildNodeUrl(background)})` }}><h1>{title}</h1></header>,
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
// fullPage.server.tsx — reuse the component directly without going through Jahia rendering
|
|
60
|
+
import { SmallHero } from "../Hero/Section/small.server.jsx";
|
|
61
|
+
<SmallHero title={title} background={cover} />
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### When implementing a view from existing HTML
|
|
65
|
+
|
|
66
|
+
When you have a source HTML fragment to translate (e.g. from `/jahia-dev-import-from`), apply only **mechanical transformations**:
|
|
67
|
+
|
|
68
|
+
- `class=` → `className=`
|
|
69
|
+
- Void elements: `<img>`, `<input>`, `<br>` → self-close with ` />`
|
|
70
|
+
- `{placeholder}` text → `{propName}` matching `Props`
|
|
71
|
+
|
|
72
|
+
**Never** remove, rearrange, or simplify elements. Every `data-*`, `aria-*`, `role`, `id`, `<noscript>`, and `<source>` must appear in the TSX output. Carousel and slider wrapper `id`s in particular must be preserved verbatim — JS libraries use them for initialization.
|
|
73
|
+
|
|
74
|
+
**Self-check before finishing:** Count the attributes on 2–3 key elements in the source HTML. If the source `<div>` has 6 attributes and your TSX has 4, you dropped something — go back.
|
|
75
|
+
|
|
76
|
+
**CSS class names:** Rename source HTML class names to CSS Module keys (`hero__title` → `classes.heroTitle`). If the component also imports a vendor CSS file as a static asset (see `jahia-dev-import-from`), those vendor classes stay as plain strings in the JSX — they are not processed by CSS Modules.
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Step 2 — Import Props from types.ts
|
|
82
|
+
|
|
83
|
+
Always import `Props` from `./types.js` (not `./types.ts` — use `.js` extension at import time):
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
import type { Props } from "./types.js";
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
If `types.ts` doesn't exist yet, create it first (see `jahia-dev-define-content-type` skill).
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## CMS rule — never hardcode links or URLs
|
|
94
|
+
|
|
95
|
+
> ⚠️ **This is a CMS. All links must come from contributed content — never from hardcoded strings in code.**
|
|
96
|
+
|
|
97
|
+
> 🚫 **NEVER use an external link (`j:linkType: "external"`) to point to an internal Jahia page.** Use `"internal"` with `j:linknode` instead. An external URL hardcoded to an internal path breaks on environment changes, language switches, workspace toggling (live/preview), and vanity URL rewrites.
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
// ❌ Wrong — hardcoded URL
|
|
101
|
+
<a href="https://www.jahia.com">Jahia</a>
|
|
102
|
+
<a href="/en/documentation">Documentation</a>
|
|
103
|
+
|
|
104
|
+
// ❌ Wrong — external link used for an internal page
|
|
105
|
+
// j:linkType: "external", j:url: "/sites/mySite/documentation.html"
|
|
106
|
+
|
|
107
|
+
// ✅ Correct — internal link to a JCR node
|
|
108
|
+
switch (props["j:linkType"]) {
|
|
109
|
+
case "internal": return <a href={buildNodeUrl(props["j:linknode"])}>{props.label}</a>;
|
|
110
|
+
case "external": return <a href={props["j:url"]}>{props.label}</a>; // only for truly external URLs
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// ✅ Correct — URL resolved from a JCR node at render time
|
|
114
|
+
<a href={buildNodeUrl(currentNode)}>{title}</a>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
This applies everywhere: `href`, `src`, `action`, `data-url`. If a link needs to appear on screen, it must have a corresponding contributed field (`j:linkType`, `weakreference`, or similar). The only exception is links within the CMS UI itself (edit mode chrome).
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Step 3 — Use library helpers as needed
|
|
122
|
+
|
|
123
|
+
### `buildNodeUrl(node)` — convert a JCR node to a URL
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
import { buildNodeUrl } from "@jahia/javascript-modules-library";
|
|
127
|
+
|
|
128
|
+
<img src={buildNodeUrl(coverNode)} alt="Descriptive alt text" />
|
|
129
|
+
<header style={{ backgroundImage: `url(${buildNodeUrl(background)})` }}>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Options** (second argument):
|
|
133
|
+
|
|
134
|
+
| Option | Default | Use |
|
|
135
|
+
|---|---|---|
|
|
136
|
+
| `extension` | `.html` | Change output extension, e.g. `extension: ".pdf"` |
|
|
137
|
+
| `language` | current language | Override language: `language: "fr"` |
|
|
138
|
+
| `mode` | current mode | Force workspace: `"edit"`, `"preview"`, or `"live"` |
|
|
139
|
+
| `parameters` | — | Append query params: `parameters: { page: "2" }` |
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
// Link to the blog page in the current language
|
|
143
|
+
<a href={buildNodeUrl(renderContext.getSite().getNode("blog"))}>Blog</a>
|
|
144
|
+
|
|
145
|
+
// Same link forced to French
|
|
146
|
+
<a href={buildNodeUrl(blogNode, { language: "fr" })}>Blog (FR)</a>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
> ⚠️ **Always guard optional nodes**: `buildNodeUrl(undefined)` throws `"Expected a node in buildNodeUrl, received undefined"`. If the prop is optional in the CND, guard it:
|
|
150
|
+
> ```tsx
|
|
151
|
+
> // ❌ Crashes when background is not set
|
|
152
|
+
> style={{ backgroundImage: `url(${buildNodeUrl(background)})` }}
|
|
153
|
+
>
|
|
154
|
+
> // ✅ Safe
|
|
155
|
+
> style={background ? { backgroundImage: `url(${buildNodeUrl(background)})` } : undefined}
|
|
156
|
+
> ```
|
|
157
|
+
|
|
158
|
+
> ⚠️ **Caching rule**: Never render properties of a **weakreference** node directly in the same view. Doing so will produce stale output because Jahia's cache is based on the referencing node, not the referenced one. Instead, render the referenced node using `<RenderChild>` (or a dedicated sub-view), or call `addCacheDependency` explicitly. Example:
|
|
159
|
+
>
|
|
160
|
+
> ```tsx
|
|
161
|
+
> // ❌ Don't do this — stale on referenced node change
|
|
162
|
+
> <img src={buildNodeUrl(background)} alt={background.getProperty('jcr:title').getString()} />
|
|
163
|
+
>
|
|
164
|
+
> // ✅ Do this — render the referenced node as its own view
|
|
165
|
+
> <RenderChild name="background" />
|
|
166
|
+
> ```
|
|
167
|
+
|
|
168
|
+
### `RenderChildren` — render child nodes with optional pagination and filtering
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
import { RenderChildren } from "@jahia/javascript-modules-library";
|
|
172
|
+
|
|
173
|
+
// All children
|
|
174
|
+
<RenderChildren />
|
|
175
|
+
|
|
176
|
+
// Offset-based pagination
|
|
177
|
+
<RenderChildren pagination={{ count: 10, start: 0 }} />
|
|
178
|
+
|
|
179
|
+
// Page-based pagination (for paginator UI)
|
|
180
|
+
<RenderChildren pagination={{ count: 10, page: 0 }} />
|
|
181
|
+
|
|
182
|
+
// Filter by node type — string (single type) or function
|
|
183
|
+
<RenderChildren filter="ns:cardItem" />
|
|
184
|
+
<RenderChildren filter={(node) => node.isNodeType("ns:highlight")} />
|
|
185
|
+
|
|
186
|
+
// Combined
|
|
187
|
+
<RenderChildren pagination={{ count: 6, page: 0 }} filter="ns:blogPost" />
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### `RenderChild` — render a specific named child node
|
|
191
|
+
|
|
192
|
+
```tsx
|
|
193
|
+
import { RenderChild } from "@jahia/javascript-modules-library";
|
|
194
|
+
|
|
195
|
+
<RenderChild name="hero" /> // default view
|
|
196
|
+
<RenderChild name="hero" view="small" /> // named view
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### `Render` — render any arbitrary JCR node or virtual node
|
|
200
|
+
|
|
201
|
+
```tsx
|
|
202
|
+
import { Render } from "@jahia/javascript-modules-library";
|
|
203
|
+
|
|
204
|
+
// Render a specific node by reference (also solves the weakreference cache issue)
|
|
205
|
+
<Render node={cityNode} view="name" />
|
|
206
|
+
|
|
207
|
+
// Render a virtual node — no JCR storage, no editor interaction needed
|
|
208
|
+
// Use for components that take no parameters and need no per-page configuration
|
|
209
|
+
<Render content={{ nodeType: "namespace:navBar" }} />
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**Virtual nodes** (`content={{ nodeType }}`) render a component inline without creating a JCR node. This is the right pattern for parameterless structural components like a nav bar that is always the same on every page. Unlike `<AbsoluteArea>`, virtual nodes require zero editor interaction.
|
|
213
|
+
|
|
214
|
+
> **Why `<Render node={...} />` solves the cache issue**: When you render a weakreference node via `<Render>`, its fragment is cached separately. If the referenced node changes, its fragment is invalidated and Jahia propagates that invalidation upward to any parent fragment that included it.
|
|
215
|
+
|
|
216
|
+
### `linkTypeInitializer` — rendering links
|
|
217
|
+
|
|
218
|
+
When a CND type uses `choicelist[linkTypeInitializer]`, the `j:linkType` property is a discriminator, NOT a URL. Use a `switch` statement:
|
|
219
|
+
|
|
220
|
+
```tsx
|
|
221
|
+
import { buildNodeUrl, jahiaComponent } from "@jahia/javascript-modules-library";
|
|
222
|
+
import type { Props } from "./types.js";
|
|
223
|
+
|
|
224
|
+
jahiaComponent(
|
|
225
|
+
{ componentType: "view", nodeType: "namespace:callToAction" },
|
|
226
|
+
(props: Props) => {
|
|
227
|
+
switch (props["j:linkType"]) {
|
|
228
|
+
case "internal":
|
|
229
|
+
return <a href={buildNodeUrl(props["j:linknode"])}>{props.label}</a>;
|
|
230
|
+
case "external":
|
|
231
|
+
return <a href={props["j:url"]} title={props["j:linkTitle"]}>{props.label}</a>;
|
|
232
|
+
default:
|
|
233
|
+
return <span>{props.label}</span>;
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
);
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
The `Props` type must be a discriminated union (see `jahia-dev-define-content-type` skill).
|
|
240
|
+
|
|
241
|
+
### Cache properties — controlling fragment caching
|
|
242
|
+
|
|
243
|
+
Add a `properties` key to `jahiaComponent` to tune caching:
|
|
244
|
+
|
|
245
|
+
```tsx
|
|
246
|
+
jahiaComponent(
|
|
247
|
+
{
|
|
248
|
+
componentType: "view",
|
|
249
|
+
nodeType: "namespace:price",
|
|
250
|
+
properties: {
|
|
251
|
+
"cache.expiration": "60", // re-render at most once per minute
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
({ price }: Props) => <span>{price}</span>,
|
|
255
|
+
);
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
```tsx
|
|
259
|
+
jahiaComponent(
|
|
260
|
+
{
|
|
261
|
+
componentType: "view",
|
|
262
|
+
nodeType: "namespace:greeting",
|
|
263
|
+
properties: {
|
|
264
|
+
"cache.perUser": "true", // different cache per logged-in user
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
(_, { renderContext }) => (
|
|
268
|
+
<div>Welcome, {renderContext.getUser().getUsername()}</div>
|
|
269
|
+
),
|
|
270
|
+
);
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
> Cache only applies in **live mode**. Edit and preview modes bypass the cache entirely.
|
|
274
|
+
|
|
275
|
+
### `buildModuleFileUrl` — URL to a static module asset
|
|
276
|
+
|
|
277
|
+
```tsx
|
|
278
|
+
import { buildModuleFileUrl, AddResources } from "@jahia/javascript-modules-library";
|
|
279
|
+
|
|
280
|
+
// Inject a vendor CSS file into the page head
|
|
281
|
+
<AddResources type="css" url={buildModuleFileUrl("css/vendor.min.css")} />
|
|
282
|
+
|
|
283
|
+
// Reference a bundled image
|
|
284
|
+
<img src={buildModuleFileUrl("images/placeholder.svg")} alt="" />
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Never hardcode `/modules/<name>/javascript/apps/...` paths — use `buildModuleFileUrl` so the path resolves correctly across environments.
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
### `getChildNodes` — iterate over child nodes in code
|
|
292
|
+
|
|
293
|
+
```tsx
|
|
294
|
+
import { getChildNodes, buildNodeUrl, jahiaComponent } from "@jahia/javascript-modules-library";
|
|
295
|
+
import type { JCRNodeWrapper } from "org.jahia.services.content";
|
|
296
|
+
|
|
297
|
+
jahiaComponent(
|
|
298
|
+
{ componentType: "view", nodeType: "namespace:navBar" },
|
|
299
|
+
(_, { renderContext, mainNode }) => {
|
|
300
|
+
// Get all child pages of the site root
|
|
301
|
+
const pages = getChildNodes(renderContext.getSite(), -1, 0,
|
|
302
|
+
(node: JCRNodeWrapper) => node.isNodeType("jnt:page")
|
|
303
|
+
);
|
|
304
|
+
return (
|
|
305
|
+
<nav>
|
|
306
|
+
<ul>
|
|
307
|
+
{pages.map(page => (
|
|
308
|
+
<li key={page.getPath()}>
|
|
309
|
+
<a
|
|
310
|
+
href={buildNodeUrl(page)}
|
|
311
|
+
aria-current={page.getPath() === mainNode.getPath() ? "page" : undefined}
|
|
312
|
+
>
|
|
313
|
+
{page.getProperty("jcr:title").getString()}
|
|
314
|
+
</a>
|
|
315
|
+
</li>
|
|
316
|
+
))}
|
|
317
|
+
</ul>
|
|
318
|
+
</nav>
|
|
319
|
+
);
|
|
320
|
+
},
|
|
321
|
+
);
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
`getChildNodes(node, limit, offset, filterFn)` — `limit: -1` means no limit.
|
|
325
|
+
|
|
326
|
+
Use `aria-current="page"` (not a CSS class) to mark the active page — it's the accessible standard and can be styled with `[aria-current="page"] { font-weight: bold }`. Compare against `mainNode.getPath()` since `===` identity comparison doesn't work across GraalJS polyglot contexts.
|
|
327
|
+
|
|
328
|
+
### `useServerContext` — access rendering context
|
|
329
|
+
|
|
330
|
+
The second argument to `jahiaComponent` is the `ServerContext`. You can also call `useServerContext()` explicitly in helper functions outside the component signature.
|
|
331
|
+
|
|
332
|
+
```tsx
|
|
333
|
+
jahiaComponent(
|
|
334
|
+
{ componentType: "view", nodeType: "ns:type" },
|
|
335
|
+
({ title }: Props, { renderContext, currentNode, mainNode, jcrSession, bundleKey }) => {
|
|
336
|
+
const isEdit = renderContext.isEditMode();
|
|
337
|
+
const siteKey = renderContext.getSite().getName();
|
|
338
|
+
return <div data-edit={isEdit}>{title}</div>;
|
|
339
|
+
},
|
|
340
|
+
);
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
| Context field | Type | What it is |
|
|
344
|
+
|---|---|---|
|
|
345
|
+
| `renderContext` | `RenderContext` | Full rendering context (site, workspace, edit mode, user) |
|
|
346
|
+
| `currentNode` | `JCRNodeWrapper` | The component's own JCR node |
|
|
347
|
+
| `mainNode` | `JCRNodeWrapper` | The page's main resource node |
|
|
348
|
+
| `currentResource` | `Resource` | The render resource |
|
|
349
|
+
| `jcrSession` | `JCRSessionWrapper` | Current JCR session — do NOT hold across requests |
|
|
350
|
+
| `bundleKey` | `string` | Module bundle key (e.g. `"my-module"`) |
|
|
351
|
+
|
|
352
|
+
> Use `mainNode` to navigate to the page or site from within a sub-component. Use `jcrSession` for JCR reads that can't go through props (e.g. loading a node by path in a computed listing).
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
### `Java.type()` — low-level Java interop
|
|
357
|
+
|
|
358
|
+
For accessing Java classes directly from JS (use only for well-known, stable APIs):
|
|
359
|
+
|
|
360
|
+
```js
|
|
361
|
+
const LogManager = Java.type("org.apache.logging.log4j.LogManager");
|
|
362
|
+
const logger = LogManager.getLogger("MyJSLogger");
|
|
363
|
+
logger.info("Hello from JS!");
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Only use `Java.type()` with classes from Jahia's documented core. Undocumented classes may change without notice. Prefer `useServerContext()` for officially supported objects.
|
|
367
|
+
|
|
368
|
+
**Mixing JS and Java modules** is fully supported — content types and services from one type can be used by the other. What does NOT work:
|
|
369
|
+
- JSP files inside a JS module
|
|
370
|
+
- JSX views inside a Java module
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
### Render filters
|
|
375
|
+
|
|
376
|
+
Register a render filter from a JS module's init script to transform rendered output:
|
|
377
|
+
|
|
378
|
+
```js
|
|
379
|
+
registry.add("render-filter", "myFilter", renderFilterRef, {
|
|
380
|
+
target: "render:50", // phase + priority (lower = earlier)
|
|
381
|
+
applyOnNodeTypes: "jnt:bigText",
|
|
382
|
+
prepare: (renderContext, resource, chain) => { /* setup before render */ },
|
|
383
|
+
execute: (previousOut, renderContext, resource, chain) => {
|
|
384
|
+
return previousOut.replace("foo", "bar");
|
|
385
|
+
},
|
|
386
|
+
});
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
The `target` string format is `"<phase>:<priority>"`. Filters with priority < 16 run on every request; priority > 16 only on cache miss.
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
### `useGQLQuery` — server-side GraphQL
|
|
394
|
+
|
|
395
|
+
Executes a GraphQL query **synchronously** using the current user's credentials. Returns the `data` portion of the response.
|
|
396
|
+
|
|
397
|
+
```tsx
|
|
398
|
+
import { useGQLQuery, jahiaComponent } from "@jahia/javascript-modules-library";
|
|
399
|
+
import { gql } from "graphql-tag";
|
|
400
|
+
|
|
401
|
+
const QUERY = gql`
|
|
402
|
+
query ListNodes($path: String!) {
|
|
403
|
+
jcr {
|
|
404
|
+
nodeByPath(path: $path) {
|
|
405
|
+
children { nodes { name displayName path } }
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
`;
|
|
410
|
+
|
|
411
|
+
jahiaComponent(
|
|
412
|
+
{ componentType: "view", nodeType: "ns:listing" },
|
|
413
|
+
(_, { renderContext }) => {
|
|
414
|
+
const siteKey = renderContext.getSite().getName();
|
|
415
|
+
const data = useGQLQuery(QUERY, { path: `/sites/${siteKey}/contents` });
|
|
416
|
+
const nodes = data?.jcr?.nodeByPath?.children?.nodes ?? [];
|
|
417
|
+
return <ul>{nodes.map((n: any) => <li key={n.path}>{n.displayName}</li>)}</ul>;
|
|
418
|
+
},
|
|
419
|
+
);
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
Use `useGQLQuery` when you need field-level projection, joins across nodes, or complex filtering. Use `useJCRQuery` for simple node listings where you'll call Java methods on the results.
|
|
423
|
+
|
|
424
|
+
> **Edit mode pattern for interactive components**: Carousels, accordions, tabs, and sliders are hard for editors to work with in their interactive state. In edit mode, render them **flat** (all slides/tabs visible) and optionally show an editor hint:
|
|
425
|
+
>
|
|
426
|
+
> ```tsx
|
|
427
|
+
> ({ slides }: Props, { renderContext }) => {
|
|
428
|
+
> const isEdit = renderContext.isEditMode();
|
|
429
|
+
> return isEdit ? (
|
|
430
|
+
> <div className={classes.editStack}>
|
|
431
|
+
> {/* flat — all children visible for editing */}
|
|
432
|
+
> <RenderChildren />
|
|
433
|
+
> <p className={classes.hint}>🖊 Carousel — add or reorder slides here</p>
|
|
434
|
+
> </div>
|
|
435
|
+
> ) : (
|
|
436
|
+
> <div className={classes.carousel}>
|
|
437
|
+
> <RenderChildren />
|
|
438
|
+
> </div>
|
|
439
|
+
> );
|
|
440
|
+
> }
|
|
441
|
+
> ```
|
|
442
|
+
|
|
443
|
+
### `readOnly` prop for shared/structural nodes
|
|
444
|
+
|
|
445
|
+
Use `readOnly` when rendering a node that editors should not edit in-place (e.g. a shared footer, a system-level navigation area):
|
|
446
|
+
|
|
447
|
+
```tsx
|
|
448
|
+
<RenderChild name="footer" readOnly={true} />
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
For `AbsoluteArea`, use `readOnly="children"` to allow editing only from the owning page:
|
|
452
|
+
|
|
453
|
+
```tsx
|
|
454
|
+
// Fully read-only — editors cannot edit the footer from any page
|
|
455
|
+
<AbsoluteArea name="footer" parent={renderContext.getSite()} readOnly={true} />
|
|
456
|
+
|
|
457
|
+
// Read-only everywhere EXCEPT the designated "footer management" page
|
|
458
|
+
<AbsoluteArea name="footer" parent={renderContext.getSite()} readOnly="children" />
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
`readOnly="children"` is the recommended pattern: the footer is manageable from one page, but other page templates just include it without showing edit handles.
|
|
462
|
+
|
|
463
|
+
---
|
|
464
|
+
|
|
465
|
+
## Step 4 — Add CSS with CSS Modules
|
|
466
|
+
|
|
467
|
+
Create a `component.module.css` file in the same folder:
|
|
468
|
+
|
|
469
|
+
```css
|
|
470
|
+
.root {
|
|
471
|
+
display: flex;
|
|
472
|
+
flex-direction: column;
|
|
473
|
+
gap: 1rem;
|
|
474
|
+
padding: 2rem;
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
Import and use in the view:
|
|
479
|
+
|
|
480
|
+
```tsx
|
|
481
|
+
import classes from "./component.module.css";
|
|
482
|
+
|
|
483
|
+
<section className={classes.root}>
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
Combine multiple classes:
|
|
487
|
+
|
|
488
|
+
```tsx
|
|
489
|
+
<section className={[classes.root, classes.small].join(" ")}>
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
### ⚠️ CSS grid: `auto-fit` vs `auto-fill`
|
|
493
|
+
|
|
494
|
+
When using `repeat(auto-fill, ...)`, CSS creates **phantom empty tracks** for remaining grid columns, leaving gaps when there are fewer items than columns. Use **`auto-fit`** instead — it collapses empty tracks so items stretch to fill the row:
|
|
495
|
+
|
|
496
|
+
```css
|
|
497
|
+
/* ❌ auto-fill — leaves gaps when items don't fill the row */
|
|
498
|
+
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
|
499
|
+
|
|
500
|
+
/* ✅ auto-fit — items stretch to fill the full row */
|
|
501
|
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### ⚠️ Full-card clickability
|
|
505
|
+
|
|
506
|
+
When only the title of a card is a link, make the entire card clickable using the CSS stretched-link technique:
|
|
507
|
+
|
|
508
|
+
```tsx
|
|
509
|
+
// In the card view
|
|
510
|
+
<article className={classes.card}>
|
|
511
|
+
<h3 className={classes.cardTitle}>
|
|
512
|
+
<a href={buildNodeUrl(currentNode)} className={classes.cardLink}>
|
|
513
|
+
{title}
|
|
514
|
+
</a>
|
|
515
|
+
</h3>
|
|
516
|
+
<p>{description}</p>
|
|
517
|
+
</article>
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
```css
|
|
521
|
+
/* In component.module.css */
|
|
522
|
+
.card {
|
|
523
|
+
position: relative; /* ← required for stretch to work */
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
.cardLink::after {
|
|
527
|
+
content: "";
|
|
528
|
+
position: absolute;
|
|
529
|
+
inset: 0; /* stretches to cover the entire card */
|
|
530
|
+
}
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
The `::after` pseudo-element on the link covers the entire `position: relative` card, making every pixel clickable while keeping the link semantically on the title.
|
|
534
|
+
|
|
535
|
+
---
|
|
536
|
+
|
|
537
|
+
## Step 5 — Creating a named (non-default) view
|
|
538
|
+
|
|
539
|
+
To create a second view (e.g. a compact version), create a new file `small.server.tsx` and add `name: "small"` to the `jahiaComponent` call:
|
|
540
|
+
|
|
541
|
+
```tsx
|
|
542
|
+
jahiaComponent(
|
|
543
|
+
{
|
|
544
|
+
componentType: "view",
|
|
545
|
+
nodeType: "namespace:typeName",
|
|
546
|
+
displayName: "Small View",
|
|
547
|
+
name: "small", // ← this registers a named view
|
|
548
|
+
},
|
|
549
|
+
({ title }: Props) => <span className={classes.small}>{title}</span>,
|
|
550
|
+
);
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
Request a named view from a parent component with `<RenderChild name="child" view="small" />`.
|
|
554
|
+
|
|
555
|
+
---
|
|
556
|
+
|
|
557
|
+
## Step 5b — Creating a client-side interactive component (Island Architecture)
|
|
558
|
+
|
|
559
|
+
Jahia uses the **Island Architecture**: server components render static HTML; interactive islands are hydrated in the browser. Use this when you need React state, browser events, or browser-only APIs.
|
|
560
|
+
|
|
561
|
+
### When to use client vs server rendering
|
|
562
|
+
|
|
563
|
+
| Use `.server.tsx` for… | Use `.client.tsx` for… |
|
|
564
|
+
|---|---|
|
|
565
|
+
| Static HTML, CMS content, navigation | Buttons, toggles, counters, forms |
|
|
566
|
+
| Reading JCR/GQL data | `useState`, `useEffect`, browser events |
|
|
567
|
+
| SEO-important content | Animations, browser-only libraries |
|
|
568
|
+
|
|
569
|
+
### Step 1 — Create the client component
|
|
570
|
+
|
|
571
|
+
Create `MyComponent.client.tsx` **in the same folder** as the server view. This is a plain React component — no `jahiaComponent` call needed:
|
|
572
|
+
|
|
573
|
+
```tsx
|
|
574
|
+
// src/components/Counter/Counter.client.tsx
|
|
575
|
+
import { useState } from "react";
|
|
576
|
+
import classes from "./component.module.css";
|
|
577
|
+
|
|
578
|
+
interface Props {
|
|
579
|
+
label: string; // only serializable types allowed as Island props
|
|
580
|
+
initialCount?: number;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
export default function Counter({ label, initialCount = 0 }: Props) {
|
|
584
|
+
const [count, setCount] = useState(initialCount);
|
|
585
|
+
return (
|
|
586
|
+
<div className={classes.counter}>
|
|
587
|
+
<button type="button" onClick={() => setCount(c => c - 1)}>−</button>
|
|
588
|
+
<span>{label}: {count}</span>
|
|
589
|
+
<button type="button" onClick={() => setCount(c => c + 1)}>+</button>
|
|
590
|
+
</div>
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
> ⚠️ **Only the default export** of a `.client.tsx` file can be used as an island component. Named exports are bundled for the browser but cannot be registered as islands.
|
|
596
|
+
|
|
597
|
+
> ⚠️ **Props must be serializable**: only strings, numbers, booleans, plain objects, and arrays. You cannot pass `JCRNodeWrapper`, `renderContext`, or Java objects to a client component.
|
|
598
|
+
|
|
599
|
+
### Step 2 — Wrap it with `<Island>` in the server view
|
|
600
|
+
|
|
601
|
+
```tsx
|
|
602
|
+
// src/components/Counter/default.server.tsx
|
|
603
|
+
import { jahiaComponent, Island } from "@jahia/javascript-modules-library";
|
|
604
|
+
import Counter from "./Counter.client.jsx"; // .jsx at import time
|
|
605
|
+
import type { Props } from "./types.js";
|
|
606
|
+
|
|
607
|
+
jahiaComponent(
|
|
608
|
+
{ componentType: "view", nodeType: "namespace:counter" },
|
|
609
|
+
({ label, initialCount }: Props) => (
|
|
610
|
+
<div>
|
|
611
|
+
<Island component={Counter} props={{ label, initialCount }} />
|
|
612
|
+
</div>
|
|
613
|
+
),
|
|
614
|
+
);
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
The `Island` component handles SSR + hydration automatically. The server view fetches the content from JCR; only serializable values flow into the client island.
|
|
618
|
+
|
|
619
|
+
### Step 3 — Browser-only rendering (skip SSR)
|
|
620
|
+
|
|
621
|
+
If the component cannot run on the server (e.g. uses `window`, `document`, or a browser-only library), use `clientOnly`:
|
|
622
|
+
|
|
623
|
+
```tsx
|
|
624
|
+
<Island component={MapWidget} props={{ lat, lng }} clientOnly>
|
|
625
|
+
<p>Loading map…</p> {/* shown until the component hydrates */}
|
|
626
|
+
</Island>
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
### Step 3b — Passing children to an island (accordion pattern)
|
|
630
|
+
|
|
631
|
+
In default mode (without `clientOnly`), children passed to `<Island>` are rendered on the server and inserted as static children of the island component. Use this for accordion or collapsible containers where the shell is interactive but the content is static:
|
|
632
|
+
|
|
633
|
+
```tsx
|
|
634
|
+
// Accordion.client.tsx
|
|
635
|
+
import type { ReactNode } from "react";
|
|
636
|
+
import { useState } from "react";
|
|
637
|
+
|
|
638
|
+
export default function Accordion({ children }: { children: ReactNode }) {
|
|
639
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
640
|
+
return (
|
|
641
|
+
<div>
|
|
642
|
+
<button type="button" onClick={() => setIsOpen(o => !o)}>
|
|
643
|
+
{isOpen ? "Close" : "Open"}
|
|
644
|
+
</button>
|
|
645
|
+
<div style={{ display: isOpen ? "block" : "none" }}>
|
|
646
|
+
{children}
|
|
647
|
+
</div>
|
|
648
|
+
</div>
|
|
649
|
+
);
|
|
650
|
+
}
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
```tsx
|
|
654
|
+
// default.server.tsx
|
|
655
|
+
<Island component={Accordion}>
|
|
656
|
+
<p>Server-rendered static content</p>
|
|
657
|
+
</Island>
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
> ⚠️ The `{children}` insertion point must always be present in the client component. If you want to hide children, use CSS — a JS condition will cause them to be omitted from the page entirely.
|
|
661
|
+
|
|
662
|
+
> ⚠️ Children are wrapped in a `<jsm-children>` custom element. Avoid using the CSS `>` child combinator to target island children. Also do not target `jsm-island` or `jsm-children` in CSS — they are implementation details and may change.
|
|
663
|
+
|
|
664
|
+
In `clientOnly` mode, children act as a **loading placeholder** shown until the island hydrates (see Step 3 above).
|
|
665
|
+
|
|
666
|
+
### Step 4 — Dynamic import for heavy/browser-only libraries
|
|
667
|
+
|
|
668
|
+
For large libraries, import them dynamically inside `useEffect` to avoid SSR issues and reduce bundle size:
|
|
669
|
+
|
|
670
|
+
```tsx
|
|
671
|
+
// Counter.client.tsx
|
|
672
|
+
import { useEffect, useState } from "react";
|
|
673
|
+
|
|
674
|
+
export default function Confetti() {
|
|
675
|
+
const [fire, setFire] = useState<(() => void) | null>(null);
|
|
676
|
+
|
|
677
|
+
useEffect(() => {
|
|
678
|
+
import("canvas-confetti").then(({ default: confetti }) => {
|
|
679
|
+
setFire(() => () => confetti({ origin: { y: 1 } }));
|
|
680
|
+
});
|
|
681
|
+
}, []);
|
|
682
|
+
|
|
683
|
+
return <button type="button" onClick={() => fire?.()} disabled={!fire}>🎉</button>;
|
|
684
|
+
}
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
### Edit mode caveat
|
|
688
|
+
|
|
689
|
+
Client components are hydrated even in Page Builder edit mode. If the interactive behaviour is disruptive in edit mode (e.g. a slider that auto-advances), guard it:
|
|
690
|
+
|
|
691
|
+
```tsx
|
|
692
|
+
// Pass isEditMode from the server view as a prop
|
|
693
|
+
<Island component={Slider} props={{ slides, isEditMode: renderContext.isEditMode() }} />
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
Then in the client component, skip the interactive behaviour when `isEditMode` is true.
|
|
697
|
+
|
|
698
|
+
---
|
|
699
|
+
|
|
700
|
+
## Step 5c — Add front-end UI labels (locales)
|
|
701
|
+
|
|
702
|
+
Any string that appears in the rendered HTML and is not a JCR property value must come from `settings/locales/`.
|
|
703
|
+
Do not hardcode button text, section headings, alt text templates, error messages, or form labels.
|
|
704
|
+
|
|
705
|
+
**File location:**
|
|
706
|
+
```
|
|
707
|
+
settings/locales/en.json ← required
|
|
708
|
+
settings/locales/fr.json ← required minimum
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
These files are auto-discovered by `@jahia/vite-plugin` — no registration needed.
|
|
712
|
+
|
|
713
|
+
**Usage in views:**
|
|
714
|
+
|
|
715
|
+
```tsx
|
|
716
|
+
import { useTranslation } from "react-i18next";
|
|
717
|
+
|
|
718
|
+
// Works in both .server.tsx and .client.tsx
|
|
719
|
+
const { t } = useTranslation();
|
|
720
|
+
|
|
721
|
+
// Simple
|
|
722
|
+
<button>{t("hero.cta.label")}</button>
|
|
723
|
+
|
|
724
|
+
// With interpolation
|
|
725
|
+
<img alt={t("alt.hero", { title })} />
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
**Add to both `en.json` and `fr.json` for every new string:**
|
|
729
|
+
|
|
730
|
+
```json
|
|
731
|
+
{
|
|
732
|
+
"hero": {
|
|
733
|
+
"cta": {
|
|
734
|
+
"label": "Discover more"
|
|
735
|
+
}
|
|
736
|
+
},
|
|
737
|
+
"alt": {
|
|
738
|
+
"hero": "Hero image for {{title}}"
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
**Best practices:**
|
|
744
|
+
- Use random/opaque keys (e.g. `"r3k2"`) or scoped semantic keys (e.g. `"hero.cta.label"`) — never bare English words as keys (`"read-more"`) which creates ambiguity across contexts and forces renaming.
|
|
745
|
+
- Never concatenate: always use interpolation (`{{author}}`) for dynamic data.
|
|
746
|
+
- For HTML inside translations, use the `<Trans>` component instead of `t()`:
|
|
747
|
+
|
|
748
|
+
```tsx
|
|
749
|
+
import { Trans } from "react-i18next";
|
|
750
|
+
// key value: "Written by <a>{{author}}</a>"
|
|
751
|
+
<Trans i18nKey="article.byline" values={{ author }} components={{ a: <a href={authorUrl} /> }} />
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
**IDE integration:** `npm init @jahia/module@latest` automatically configures the [i18n ally](https://github.com/lokalise/i18n-ally#readme) VS Code extension. When installed it shows translation values inline in the code, lets you edit them without opening JSON files, and provides an `Extract text into i18n messages` command that replaces a hardcoded string with a `t("...")` call. Install the recommended extensions in `.vscode/extensions.json` to get it.
|
|
755
|
+
|
|
756
|
+
> Front-end UI labels (`locales/*.json`) are separate from CND editor labels (`settings/resources/*.properties`). Both are required — locales for rendered UI strings, properties for the Jahia content editor.
|
|
757
|
+
|
|
758
|
+
---
|
|
759
|
+
|
|
760
|
+
## Step 5d — Language switcher
|
|
761
|
+
|
|
762
|
+
Use the following utilities from `@jahia/javascript-modules-library` to build a server-rendered language switcher:
|
|
763
|
+
|
|
764
|
+
```tsx
|
|
765
|
+
import { getSiteLocales, buildNodeUrl, jahiaComponent } from "@jahia/javascript-modules-library";
|
|
766
|
+
|
|
767
|
+
jahiaComponent(
|
|
768
|
+
{ componentType: "view", nodeType: "ns:languageSwitcher" },
|
|
769
|
+
(_, { renderContext, currentNode }) => {
|
|
770
|
+
const locales = getSiteLocales(renderContext.getSite());
|
|
771
|
+
const invalidLanguages: string[] = currentNode.getPropertyAsString("j:invalidLanguages")?.split(" ") ?? [];
|
|
772
|
+
|
|
773
|
+
return (
|
|
774
|
+
<ul>
|
|
775
|
+
{locales
|
|
776
|
+
.filter(locale => !invalidLanguages.includes(locale))
|
|
777
|
+
.filter(locale => currentNode.hasI18N(renderContext.getSite().getLocale(locale)))
|
|
778
|
+
.map(locale => (
|
|
779
|
+
<li key={locale}>
|
|
780
|
+
<a href={buildNodeUrl(currentNode, { language: locale })}>{locale.toUpperCase()}</a>
|
|
781
|
+
</li>
|
|
782
|
+
))}
|
|
783
|
+
</ul>
|
|
784
|
+
);
|
|
785
|
+
},
|
|
786
|
+
);
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
`j:invalidLanguages` is a system property Jahia sets on nodes that haven't been translated to a given language. Filtering it out prevents dead links to untranslated pages. `node.hasI18N(locale)` provides an additional check — it returns false for nodes that have no translated properties at all for the given locale, catching cases `j:invalidLanguages` may not cover.
|
|
790
|
+
|
|
791
|
+
---
|
|
792
|
+
|
|
793
|
+
## Step 6 — Push to Jahia
|
|
794
|
+
|
|
795
|
+
Build and deploy the module to push all changes (existing or new files):
|
|
796
|
+
|
|
797
|
+
```bash
|
|
798
|
+
# Always use this — never use yarn dev from an agent (it's interactive-only)
|
|
799
|
+
yarn build && yarn jahia-deploy
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
---
|
|
803
|
+
|
|
804
|
+
## Validation checklist
|
|
805
|
+
- [ ] `jahiaComponent` registered with correct `nodeType` (matches CND)
|
|
806
|
+
- [ ] `Props` imported from `./types.js`
|
|
807
|
+
- [ ] `buildNodeUrl` used for any image or node URL
|
|
808
|
+
- [ ] Weakreference-backed content rendered via sub-view (`RenderChild`), not inline property access
|
|
809
|
+
- [ ] Interactive UI (carousels, tabs) flattened in edit mode with editor hints
|
|
810
|
+
- [ ] Structural/shared nodes rendered with `readOnly` prop
|
|
811
|
+
- [ ] Semantic HTML used (`<article>`, `<section>`, `<nav>`, `<header>`, `<footer>`)
|
|
812
|
+
- [ ] Images have meaningful `alt` text (not empty `alt=""` unless decorative) — use `t("alt.key", {...})` for translated alt text
|
|
813
|
+
- [ ] No hardcoded UI strings — all button labels, headings, messages use `t("key")` from `settings/locales/`
|
|
814
|
+
- [ ] `settings/locales/en.json` and `fr.json` both updated with any new keys
|
|
815
|
+
- [ ] CSS Module created and imported
|
|
816
|
+
- [ ] **If client-side**: component is in `.client.tsx`, wrapped with `<Island>` in the server view
|
|
817
|
+
- [ ] **If client-side**: all props passed to Island are serializable (no JCR objects)
|
|
818
|
+
- [ ] **If client-side**: browser-only libraries use dynamic `import()` inside `useEffect`
|
|
819
|
+
- [ ] `yarn build && yarn jahia-deploy` run after all changes
|
|
820
|
+
- [ ] Component renders without errors in Page Builder
|
|
821
|
+
|
|
822
|
+
## Troubleshooting
|
|
823
|
+
> https://academy.jahia.com/tutorials-get-started/front-end-developer/making-a-hero-section
|
|
824
|
+
|
|
825
|
+
### JSX vs HTML attribute differences
|
|
826
|
+
|
|
827
|
+
| Feature | HTML | JSX |
|
|
828
|
+
|---|---|---|
|
|
829
|
+
| CSS class | `class="..."` | `className="..."` |
|
|
830
|
+
| Inline style | `style="color:red"` | `style={{ color: 'red' }}` |
|
|
831
|
+
| Event handler | `onclick="fn()"` | `onClick={fn}` |
|
|
832
|
+
| Comments | `<!-- -->` | `{/* */}` |
|
|
833
|
+
| Boolean attributes | `disabled` | `disabled={true}` or just `disabled` |
|
|
834
|
+
|
|
835
|
+
## References
|
|
836
|
+
|
|
837
|
+
- JavaScript modules monorepo: https://github.com/Jahia/javascript-modules
|
|
838
|
+
- Preparing for i18n: https://academy.jahia.com/documentation/jahia-cms/jahia-8-2/developer/javascript-module-development/preparing-for-internationalization-i18n
|