OpenCDD is open source and contributor-friendly. Most contributions do not require any understanding of the IEC 61360 data model — docs improvements, blog posts, and UI fixes are all welcome.
Quick contribution map
| You want to… | Where to look | How to ship |
|---|---|---|
| Fix a typo in docs | src/content/docs/*.mdx |
Edit, PR. |
| Write a new docs page | src/content/docs/ |
Add .mdx, PR. |
| Write a blog post | src/content/blog/ |
Add .mdx, PR. |
| Report a bug or request a feature | Issues | Open an issue. |
| Fix a UI bug | src/components/, src/pages/, src/layouts/ |
Edit, run npm run dev, PR. |
| Add a Vue island | src/components/islands/ |
Same as above. |
| Improve data quality | opencdd-ruby |
Issue + PR there. |
| Scrape missing entities | cdd-data (private) |
Talk to maintainers. |
| Translate docs | (not yet supported) | Open an issue to discuss. |
Repository layout
opencdd.github.io/
├── astro.config.mjs Astro + Vue + MDX + Tailwind config
├── src/
│ ├── components/
│ │ ├── layout/ Header, Footer
│ │ ├── islands/ Vue components (client-side hydrated)
│ │ └── ui/ Astro components (server-rendered)
│ ├── content/
│ │ ├── data/ JSON snapshots (committed; built by cdd-data)
│ │ ├── docs/ MDX documentation (this section)
│ │ └── blog/ MDX blog posts
│ ├── content.config.ts Content collection schemas
│ ├── layouts/ BaseLayout, DictionaryLayout, EntityDetailShell,
│ │ DocsLayout, BlogLayout
│ ├── lib/ Build-time data layer (bundle, registry, loader)
│ ├── pages/ File-based routes
│ │ ├── index.astro Homepage
│ │ ├── docs/ Docs index + [slug]
│ │ ├── blog/ Blog index + [slug]
│ │ ├── search.astro
│ │ └── d/[dict]/ Dictionary pages
│ │ ├── index.astro Overview tabs
│ │ ├── about.astro Metadata
│ │ ├── c/[code].astro Class detail
│ │ ├── p/[code].astro Property detail
│ │ ├── t/[code].astro Value term detail
│ │ ├── u/[code].astro Unit detail
│ │ ├── v/[code].astro Value list detail
│ │ └── r/[code].astro Relation detail
│ └── styles/global.css Tailwind 4 theme + prose styles
├── scripts/
│ ├── fetch-data.ts Copies JSON from ../cdd-data or fetches Release
│ └── gen-tree.ts Pre-builds the class tree JSON
└── tests/ Vitest specs
Development environment
Prerequisites:
- Node.js 22+ (we use
tsxfor TypeScript scripting). - npm 10+.
Setup:
git clone https://github.com/opencdd/opencdd.github.io
cd opencdd.github.io
npm install
npm run fetch-data # populates src/content/data/ from ../cdd-data
# (or set CDD_DATA_RELEASE=latest to fetch Release)
npm run dev # http://localhost:4321
If npm run fetch-data fails because ../cdd-data does not exist
locally, set CDD_DATA_RELEASE=latest to fetch the latest published
release from GitHub.
Common workflows
Add a docs page
-
Pick a slug — short, kebab-case (e.g.
value-formats). -
Create
src/content/docs/{slug}.mdxwith the frontmatter:
section: “Project”
title: Page title description: One-line summary for the docs index and meta tags. published: 2026-07-12 order: 24 # controls nav order; see “Docs ordering” below
3. Write your content as MDX. Astro components and Vue islands can be
imported, but for pure prose you usually do not need them.
4. Add a link to your page from `src/content/docs/index.mdx`.
5. Run `npm run dev` and verify the page renders at
`/docs/{slug}/`.
6. Commit and open a PR.
### Add a blog post
1. Create `src/content/blog/{slug}.mdx` with frontmatter:
```yaml
---
title: Post title
description: One-line summary for the blog index.
published: 2026-07-12
author: Your Name
tags: ["announcement", "deep-dive"]
---
- Write the body. The blog is open to community posts — project news, CDD explainers, integration case studies, data analyses.
- Run
npm run devand verify at/blog/{slug}/. - Commit and open a PR.
The blog has no comments by design. Readers who want to respond should open a GitHub Discussion or write a reply post.
Fix a UI bug
- Reproduce locally with
npm run dev. - Find the relevant component in
src/components/or page insrc/pages/. - Edit, refresh, verify.
- If you add a Vue island, write a Vitest spec in
tests/. - Run
npm run check(Astro typecheck) andnpm testbefore committing.
Update dictionary metadata
Dictionary bibliographic metadata (title, publication ID, abstract,
technical committee, webstore URL) lives in src/lib/dictMetadata.ts.
The data itself (entity counts, languages) comes from index.json,
which is built by rake browser:build_all in cdd-data.
To update metadata for an existing dictionary:
- Find the entry in
src/lib/dictMetadata.ts. - Update the field(s).
- Cite the IEC webstore or other authoritative source in your PR description.
- Run
npm run checkandnpm run devto verify.
Add a new dictionary
Adding a new published dictionary is a multi-repo change:
- Scrape the dictionary into
cdd-data(private). The scraper lives incdd-data/harvest/. - Run
rake browser:build[{slug}]incdd-datato build the JSON. - Run
npm run fetch-datahere to copy the JSON intosrc/content/data/. - Add a metadata entry in
src/lib/dictMetadata.ts. - Verify counts and one entity detail page render correctly.
If you are not a maintainer with access to cdd-data, open an issue
describing the dictionary and a maintainer will handle steps 1–2.
Docs ordering
The order field in frontmatter controls the order of pages in the
docs sidebar. Conventions:
| Range | Section |
|---|---|
-1 |
Docs index (special; only index.mdx). |
1–9 |
New user — introductory pages. |
10–19 |
UI walkthrough. |
20–29 |
Developer — data access. |
30–39 |
Theory — ontology, model. |
40–49 |
Contributor. |
Pick a number that fits the section. Within a section, ordering is
fine-grained by integer value (so 21 comes before 22).
Writing style
- Lead with the value. A reader should know within the first paragraph whether the page is for them.
- Show, then tell. Code examples, screenshots, and concrete entity codes beat abstract description.
- Cite the spec. When you reference IEC 61360 (or related), include the section number and a link to the IEC webstore. See CDD ontology vs UML and RDF for the pattern.
- Do not reproduce IEC text verbatim. The IEC publications are © IEC, Geneva. Paraphrase + cite. Short quoted sentences with explicit attribution are fine.
- Use the spec’s terminology when one exists (
Item_class,class_type,is_case_of). Don’t invent synonyms. - Be terse. Most docs pages should fit on one screen at the section level; expand details with sub-sections.
Code style
- TypeScript: strict mode,
import typefor type-only imports. - Astro components: one concept per file.
- Vue islands: Composition API,
<script setup>, no React. - Tailwind 4: use the existing tokens (
ink-*,sand-*,accent-*), do not hard-code hex colours. - No
anytypes unless interfacing with untyped external data; even then, preferunknown+ cast at the boundary.
Run npm run check and npm test before committing. Run
npm run format if you want auto-formatting.
Commit and PR conventions
- Commit message — imperative mood, no AI attribution trailers
(no
Co-authored-by:for AI tools, no “Generated with …” footers). Match the style of recent commits:EntityDetailShell — shared layout for entity detail pages. - Branch name — short kebab-case, e.g.
docs/getting-startedorfix/toc-empty-box. - PR description — 1–3 bullet points for what and why. Add a Test Plan section with concrete verification steps.
- Small PRs are easier to review than large ones. If you are touching more than ~300 lines, consider splitting.
Tests
Tests run on Vitest 4. Component tests for Vue islands use
@testing-library/vue and jsdom. Each test file has a
// @vitest-environment jsdom directive because Vitest’s per-file
environment config is more reliable than per-glob config under esbuild.
To run:
npm test # one-shot
npm run test:watch # interactive
npm run test:coverage # with coverage
Coverage is currently around 66 % of lines; target 75 %. When you add a Vue island or non-trivial utility, add a test.
Reporting issues
Open an issue on GitHub for:
- Bugs — anything that renders wrong, breaks, or behaves unexpectedly.
- Data gaps — entities that should be present but are not.
- Feature requests — new docs, new UI features, new dictionaries.
- Security issues — see
SECURITY.md(if absent, email the maintainers directly rather than filing a public issue).
For data issues (wrong definition, broken cross-reference), the fix
usually belongs in opencdd-ruby or cdd-data, not this repo.
Licence
By contributing, you agree that your contributions are licensed under the project’s licence (see the repository for the canonical statement). Do not submit IEC publication text — it is © IEC, Geneva, and we cannot host it.
Read more
- What is OpenCDD? — the ecosystem overview.
- What is IEC CDD? — the conceptual primer.
- The
opencdd-rubyrepo for the Ruby model. - The
opencdd-tsrepo for the TypeScript port.