Skip to content

Project Structure

Version: CalVer, YYYY.MM.N (2026.09.7 at the time of writing)
Framework: React 19, built with Vite and tested with Vitest


Directory layout

The repository is ttl-editor. Test files are colocated with their source (foo.js โ†’ foo.test.js) and are left out of the tree below; see Testing.

ttl-editor/
โ”œโ”€โ”€ index.html                      # Vite entry page (at the root, not in public/)
โ”œโ”€โ”€ vite.config.mjs                 # Build and Vitest configuration; output to dist/
โ”œโ”€โ”€ eslint.config.mjs               # ESLint flat config
โ”œโ”€โ”€ playwright.config.js            # End-to-end journeys
โ”œโ”€โ”€ tailwind.config.js
โ”œโ”€โ”€ postcss.config.js
โ”œโ”€โ”€ package.json
โ”œโ”€โ”€ package-lock.json
โ”œโ”€โ”€ renovate.json                   # Dependency update policy
โ”œโ”€โ”€ SECURITY-PIPELINE.md            # Pins, required checks, accepted risks
โ”œโ”€โ”€ .nvmrc                          # Exact Node version (24.20.0); CI reads it
โ”œโ”€โ”€ .npmrc                          # min-release-age=14 โ€” npm's 14-day cooldown
โ”œโ”€โ”€ .env.development                # Local: backend :3001, Operaton :8081
โ”œโ”€โ”€ .env.production                 # Loaded by every `vite build`
โ”œโ”€โ”€ .env.acceptance                 # Loaded by nothing unless --mode acceptance
โ”œโ”€โ”€ .env.example
โ”œโ”€โ”€ .husky/
โ”‚   โ”œโ”€โ”€ pre-commit                  # npx lint-staged
โ”‚   โ””โ”€โ”€ pre-push                    # deps:check, lint, check-format
โ”‚
โ”œโ”€โ”€ public/                         # Copied verbatim into dist/
โ”‚   โ”œโ”€โ”€ favicon.svg, favicon.ico, favicon-96x96.png, apple-touch-icon.png
โ”‚   โ”œโ”€โ”€ manifest.json, web-app-manifest-192x192.png, web-app-manifest-512x512.png
โ”‚   โ”œโ”€โ”€ robots.txt
โ”‚   โ”œโ”€โ”€ CognitatieAnnotationExport.xml
โ”‚   โ””โ”€โ”€ examples/
โ”‚       โ””โ”€โ”€ organizations/svb/      # RONL_BerekenLeeftijden_CPRMV.dmn
โ”‚
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ App.jsx                     # Main orchestrator: layout, navigation, import
โ”‚   โ”œโ”€โ”€ App.css
โ”‚   โ”œโ”€โ”€ index.jsx                   # React entry point
โ”‚   โ”œโ”€โ”€ index.css                   # Global styles, Tailwind imports
โ”‚   โ”œโ”€โ”€ parseTTL.enhanced.js        # TTL parser with DMN preservation
โ”‚   โ”œโ”€โ”€ setupTests.js               # Vitest setup
โ”‚   โ”œโ”€โ”€ logo.svg
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ components/
โ”‚   โ”‚   โ”œโ”€โ”€ PreviewPanel.jsx        # Live TTL preview side panel
โ”‚   โ”‚   โ”œโ”€โ”€ PublishDialog.jsx       # TriplyDB publish dialog + pre-publish SHACL panel
โ”‚   โ”‚   โ””โ”€โ”€ tabs/
โ”‚   โ”‚       โ”œโ”€โ”€ index.js            # Barrel export โ€” the four lazy tabs deliberately excluded
โ”‚   โ”‚       โ”œโ”€โ”€ ServiceTab.jsx
โ”‚   โ”‚       โ”œโ”€โ”€ CostSection.jsx     # Embedded in ServiceTab
โ”‚   โ”‚       โ”œโ”€โ”€ OutputSection.jsx   # Embedded in ServiceTab
โ”‚   โ”‚       โ”œโ”€โ”€ OrganizationTab.jsx
โ”‚   โ”‚       โ”œโ”€โ”€ LegalTab.jsx
โ”‚   โ”‚       โ”œโ”€โ”€ RulesTab.jsx        # RPP: Rules
โ”‚   โ”‚       โ”œโ”€โ”€ ParametersTab.jsx   # RPP: Parameters
โ”‚   โ”‚       โ”œโ”€โ”€ CPRMVTab.jsx        # RPP: Policy (lazy-loaded)
โ”‚   โ”‚       โ”œโ”€โ”€ DMNTab.jsx          # DMN upload, deploy, test (lazy-loaded)
โ”‚   โ”‚       โ”œโ”€โ”€ ConceptsTab.jsx     # NL-SBB concept definitions
โ”‚   โ”‚       โ”œโ”€โ”€ VendorTab.jsx       # Vendor integration, hosts the iKnow UI (lazy-loaded)
โ”‚   โ”‚       โ”œโ”€โ”€ IKnowMappingTab.jsx # iKnow mapping config (rendered inside VendorTab)
โ”‚   โ”‚       โ””โ”€โ”€ ChangelogTab.jsx    # Version history and build provenance (lazy-loaded)
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ hooks/
โ”‚   โ”‚   โ”œโ”€โ”€ useEditorState.js       # Centralised state management
โ”‚   โ”‚   โ”œโ”€โ”€ useArrayHandlers.js     # DRY CRUD for array-based fields
โ”‚   โ”‚   โ””โ”€โ”€ useDsoImport.js         # DSO โ†’ DMN deep-link import
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ utils/
โ”‚   โ”‚   โ”œโ”€โ”€ index.js                # Barrel export
โ”‚   โ”‚   โ”œโ”€โ”€ constants.js            # Shared constants, TTL_NAMESPACES, dropdown options
โ”‚   โ”‚   โ”œโ”€โ”€ ttlGenerator.js         # TTL generation class
โ”‚   โ”‚   โ”œโ”€โ”€ ttlHelpers.js           # TTL string/IRI helpers (escapeTTLString, sanitizeIri, โ€ฆ)
โ”‚   โ”‚   โ”œโ”€โ”€ importHandler.js        # Import logic
โ”‚   โ”‚   โ”œโ”€โ”€ cprmvImport.js          # CPRMV 0.4.1 Rules API โ†’ flat model
โ”‚   โ”‚   โ”œโ”€โ”€ shaclHelper.js          # Pre-publish SHACL validation
โ”‚   โ”‚   โ”œโ”€โ”€ dmnHelpers.js           # DMN-specific utilities
โ”‚   โ”‚   โ”œโ”€โ”€ validators.js           # Form validation
โ”‚   โ”‚   โ”œโ”€โ”€ triplydbHelper.js       # TriplyDB API integration, buildGraphIRI
โ”‚   โ”‚   โ”œโ”€โ”€ ronlHelper.js           # RONL vocabulary SPARQL queries
โ”‚   โ”‚   โ”œโ”€โ”€ iknowParser.js          # iKnow XML parser
โ”‚   โ”‚   โ”œโ”€โ”€ problem.js              # Reads the backend's RFC 9457 error detail
โ”‚   โ”‚   โ””โ”€โ”€ buildInfo.js            # Build SHA and run number, injected at build time
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ data/
โ”‚   โ”‚   โ”œโ”€โ”€ changelog.json          # Powers ChangelogTab
โ”‚   โ”‚   โ”œโ”€โ”€ roadmap.json            # Planned features for ChangelogTab
โ”‚   โ”‚   โ””โ”€โ”€ cprmv-example.json      # Conformant 0.4.1 example for CPRMV "Load Example"
โ”‚   โ”‚
โ”‚   โ””โ”€โ”€ config/
โ”‚       โ”œโ”€โ”€ vocabularies.config.js  # RDF vocabulary mappings for parser
โ”‚       โ””โ”€โ”€ iknow-mappings/         # iKnow default field mapping templates
โ”‚
โ”œโ”€โ”€ e2e/                            # Playwright journeys and their global setup
โ”œโ”€โ”€ e2e-fixtures/                   # Journey fixtures, with a provenance manifest
โ”œโ”€โ”€ examples/                       # Reference TTL/DMN exports; round-trip test fixtures
โ”‚   โ””โ”€โ”€ organizations/              # Per-organisation examples and test cases
โ”‚
โ”œโ”€โ”€ scripts/
โ”‚   โ”œโ”€โ”€ check-deps.sh               # npm run deps:check โ€” install vs lockfile; warns on npm < 11.10
โ”‚   โ”œโ”€โ”€ write-deps-marker.mjs       # postinstall โ€” snapshots the lockfile deps:check compares with
โ”‚   โ”œโ”€โ”€ check-supply-chain.mjs      # npm run check-supply-chain โ€” pin truth and register agreement
โ”‚   โ”œโ”€โ”€ audit-tree.mjs              # Daily dependency audit, grouped by advisory
โ”‚   โ”œโ”€โ”€ write-sbom.mjs              # npm run sbom โ€” CycloneDX SBOM into docs/sbom/
โ”‚   โ”œโ”€โ”€ check-mirror.sh             # npm run check-mirror โ€” GitLab mirror vs GitHub (never pushes)
โ”‚   โ””โ”€โ”€ check-previews.sh           # npm run check-previews โ€” orphaned preview environments (never deletes)
โ”‚
โ”œโ”€โ”€ docs/
โ”‚   โ””โ”€โ”€ sbom/                       # <name>-<version>.cdx.json, one per release
โ”‚
โ””โ”€โ”€ .github/
    โ”œโ”€โ”€ zizmor.yml                  # zizmor configuration
    โ””โ”€โ”€ workflows/
        โ”œโ”€โ”€ azure-static-web-apps-orange-beach-0574c2a03.yml  # Deploy ACC
        โ”œโ”€โ”€ azure-static-web-apps-white-sky-02b674303.yml     # Deploy PROD
        โ”œโ”€โ”€ close-preview-environments.yml
        โ”œโ”€โ”€ dependency-audit.yml
        โ”œโ”€โ”€ sbom.yml
        โ”œโ”€โ”€ semgrep.yml
        โ””โ”€โ”€ zizmor.yml                                        # Supply-chain audit

What each workflow does is on Deployment.


Key modules

src/hooks/useEditorState.js

Centralises all editor state into a single custom hook, providing:

  • State slices for every tab (service, organization, legalResource, ronlAnalysis, ronlMethod, temporalRules, parameters, cprmvRules, concepts, cost, output, dmnData, vendorService, iknowMappingConfig, triplyDBConfig)
  • Shared RONL vocabulary concepts (analysis/method/vendor), fetched once on mount and shared across the Legal and Vendor tabs
  • A clearAllData() action that resets the entire editor

This replaces dozens of individual useState calls that were previously spread across the main component.

src/hooks/useArrayHandlers.js

Provides DRY CRUD handlers for any array-based state (rules, parameters, CPRMV rules):

{
  handleAdd,        // Append new item with auto-incremented ID
  handleUpdate,     // Update item by ID with partial patch
  handleRemove,     // Remove item by ID
  handleUpdateField,// Update a single field (convenience wrapper)
  handleClear,      // Clear the entire array
  handleReplace     // Replace the entire array
}

IDs use Math.max(...ids) + 1 โ€” stable under rapid additions, unlike Date.now().

src/utils/ttlGenerator.js

Class-based TTL generation. Each tab section has a corresponding generate method. Called by App.jsx on export and by PreviewPanel on every state change.

src/parseTTL.enhanced.js

Full TTL parser. Handles vocabulary detection, multi-line values, namespace resolution, date parsing, array extraction (keywords), and DMN block capture and preservation. Returns a data structure matching the editor state shape for direct use in useEditorState.

src/config/vocabularies.config.js

Configuration-driven vocabulary management. Defines namespace-to-prefix mappings, RDF type-to-editor-section mappings, and property aliases, plus the detectEntityType() helper. See Vocabulary Configuration for how to extend it.


RPP tab mapping

Layer Tab Badge label Colour
Rules RulesTab RPP Layer: Rules Blue
Policy CPRMVTab RPP Layer: Policy Purple
Parameters ParametersTab RPP Layer: Parameters Green

State flow

Import:

TTL file โ†’ importHandler.js โ†’ parseTTL.enhanced.js โ†’ useEditorState.set*() โ†’ tabs re-render

Export / Live preview:

useEditorState โ†’ ttlGenerator.js generate() โ†’ combine sections โ†’ PreviewPanel / download