fix(json): emit canonical camelCase JSON wire keys#196
Conversation
Flips snake_case JSON output keys to camelCase across the three remaining templates that still emit snake form, completing the canonical wire-tag contract for the academy JSON view files. Hard prerequisite for the meshery-cloud v1beta3 academy migration: - learning-path.json.html line 23 emits 'org_id', which populates AcademyCurricula.OrgId. v1beta2 had json:'org_id', v1beta3 (released in schemas v1.2.12) has json:'orgId' and no UnmarshalJSON fallback. Without this change, cloud reading curriculum on v1beta3 would silently write nil-OrgId rows and break org-scoped curriculum lookups. Adjacent canonical-casing alignment (same theme PR, consistent wire form): - learning-path.json.html: total_courses/total_tests/total_modules/ total_pages -> totalCourses/totalTests/totalModules/totalPages; prerequisite_knowledge/related_resources/additional_attributes -> prerequisiteKnowledge/relatedResources/additionalAttributes. - common-curricula-properties.html: reading_time/prerequisite_knowledge/ related_resources -> readingTime/prerequisiteKnowledge/relatedResources. - lab/single.json.json: starter_catalog_link/starter_embed_link/ answer_catalog_link/answer_embed_link -> starterCatalogLink/ starterEmbedLink/answerCatalogLink/answerEmbedLink. The Hugo source-side reads (.Params.<snake_case>) are left unchanged: they match the existing frontmatter keys in the content repos (layer5-academy, exoscale-academy, meshery-academy, academy-example), so no content-repo change is required. The transformation is purely on the JSON output side. Theme partials test/single.html (quiz) was already camelCase; this PR brings the remaining three to parity. Post-merge, every JSON wire key the theme emits is canonical camelCase (verified: grep for snake-cased JSON keys across layouts/ returns empty). Signed-off-by: Alex Quinn <227241865+alexquincy@users.noreply.github.com>
|
🚀 Preview deployment: https://layer5io.github.io/academy-theme/pr-preview/pr-196/ |
There was a problem hiding this comment.
Pull request overview
This PR standardizes the JSON “wire” keys emitted by the academy theme’s JSON templates by converting remaining snake_case output keys to canonical camelCase, aligning with the v1beta3 academy schema expectations used by meshery-cloud’s LoadCurricula.
Changes:
- Updated
learning-path.json.htmlto emitorgIdand camelCase aggregate/metadata keys (e.g.,totalCourses,prerequisiteKnowledge). - Updated
common-curricula-properties.htmlto emit camelCase keys (e.g.,readingTime,relatedResources). - Updated the lab JSON output (
single.json.json) to emit camelCase link keys (e.g.,starterCatalogLink,answerEmbedLink).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| layouts/partials/learning-path.json.html | Converts learning-path JSON output keys (including orgId) from snake_case to camelCase. |
| layouts/partials/common-curricula-properties.html | Converts shared curricula JSON property keys (e.g., reading time and resource fields) to camelCase. |
| layouts/lab/single.json.json | Converts lab JSON output link field keys to camelCase. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Code Review
This pull request updates several Hugo template files, including layouts/lab/single.json.json, layouts/partials/common-curricula-properties.html, and layouts/partials/learning-path.json.html, to convert JSON output keys from snake_case to camelCase. Specifically, keys such as starter_catalog_link, reading_time, org_id, and various total_ count fields have been renamed to their camelCase equivalents. I have no feedback to provide.
Summary
Flips the remaining snake_case JSON output keys to camelCase across three theme templates, completing the canonical wire-tag contract for the academy JSON view files that meshery-cloud reads at runtime via
LoadCurricula.The hard prerequisite
layouts/partials/learning-path.json.htmlline 23 emits"org_id", which populatesAcademyCurricula.OrgIdin the cloud-side decode. The academy schema flipped this wire tag between v1beta2 (json:"org_id") and v1beta3 (json:"orgId"), and v1beta3 has noUnmarshalJSONfallback (confirmed againstmodels/v1beta3/academy/zz_generated.helpers.go). Without this change, the planned meshery-cloud v1beta3 migration (layer5io/meshery-cloud#5379) would have everyLoadCurriculasilently write nil-OrgIdrows and break org-scoped curriculum lookups.Adjacent canonical-casing alignment (same PR)
Folded in per the maintainer-mindset rule (pay down adjacent debt while in the area). Every JSON output key the theme emits is now canonical camelCase:
layouts/partials/learning-path.json.htmlorg_id,total_courses,total_tests,total_modules,total_pages,prerequisite_knowledge,related_resources,additional_attributeslayouts/partials/common-curricula-properties.htmlreading_time,prerequisite_knowledge,related_resourceslayouts/lab/single.json.jsonstarter_catalog_link,starter_embed_link,answer_catalog_link,answer_embed_linkThe quiz template (
layouts/partials/test/single.html) was already camelCase; this PR brings the remaining three to parity. The build (layer5io/academy-build) must be re-run after merge to publish refreshedindex.jsonartifacts before any cloud v1beta3 deploy.What does NOT change
.Params.<snake_case>) are left untouched. They match existing frontmatter keys in the content repos (layer5io/layer5-academy,layer5io/exoscale-academy,meshery-extensions/meshery-academy,layer5io/academy-example). The transformation is purely on the JSON output side, so no content repo requires any change for this migration.Test plan
This is a pure string-literal change to JSON-emitting Hugo templates. Hugo template parsing is unaffected by string content. Verification:
grep -rnE '"[a-z]+_[a-z_]+":' layouts/ --include='*.html' --include='*.json'returns empty post-edit (zero residual snake_case JSON output keys across the theme). Confirmed locally.public/learning-paths/index.jsonfororgId(camelCase) and absence oforg_id. Local Hugo build was attempted but the docsy transitive module resolution conflicted with the local-replacements env var setup; the change is mechanical enough that a CI-driven build verification is the appropriate gate.LoadCurriculawrites non-nilOrgIdrows.Related
models/v1beta3/academy/) — the canonical-casing schema, released since v1.2.12.layer5io/academy-build— needs a re-run after this PR merges, before any v1beta3 cloud deploy.