Appearance
CivilKit extensions (.ckext modules)
CivilKit can be extended by sandboxed modules that add new design checks, load generators, importers and report sections. A module is distributed as a .ckext file - a zip bundle containing a manifest, source, and cited tests - which installs directly in the browser with no server or build step.
The current modules run as MicroPython inside the host's sandboxed runtime. They declare a form, read from the host's trusted capability bridge, and return structured results plus calc-sheet working. Future modules will also compile from Nim or Rust to WebAssembly using the same bundle shape.
What a .ckext bundle contains
my-check.ckext
├── manifest.json # identity, capabilities, contribution points
├── main.py # MicroPython source (current modules)
└── tests/
└── worked-examples.json # cited expected results for the trust badgeWASM modules replace main.py with main.wasm. main.js is reserved for first-party, trusted extensions only - untrusted/community modules must be Python or WASM so they cannot touch the DOM or network directly.
manifest.json
json
{
"id": "com.example.member-shear-check",
"name": "Member shear check",
"version": "1.0.0",
"description": "AS 4100 Clause 5.11 member shear capacity check.",
"author": { "name": "Example Engineering", "url": "https://example.com" },
"license": "MIT",
"homepage": "https://example.com/ckext/member-shear-check",
"keywords": ["AS 4100", "shear", "steel"],
"civilkitApi": "^1.0",
"contributes": [
{
"point": "design-check",
"id": "member-shear-check",
"label": "Member shear check"
}
],
"capabilities": ["getModel", "getSectionProps"],
"tests": "tests/worked-examples.json"
}Required fields
| Field | Purpose |
|---|---|
id | Reverse-DNS identifier, e.g. com.example.my-check |
name | Display name in menus and the store |
version | Semver, e.g. 1.0.0 |
civilkitApi | Host compatibility range, e.g. ^1.0 |
contributes | Array of contribution points (currently design-check) |
Display and trust fields
| Field | Purpose |
|---|---|
description | Short subtitle shown on the store card |
author | Name or { name, email, url } object |
license | SPDX id such as MIT, Apache-2.0, UNLICENSED |
homepage | Link to docs or the module's project page |
keywords | Tags for store search |
capabilities | Host callbacks the module may call (least-privilege) |
tests | Path to worked-example tests that drive the trust badge |
author, homepage, repository and license are self-declared. They are shown to the user so a human can judge provenance, but they confer no trust. Trust comes only from the test gate (the Verified badge, below).
A simple Python module
Every MicroPython design-check module exposes two functions:
python
import json, math, civilkit
def build_ui(inputs, result, calcLines):
return {
"type": "panel",
"title": "Member shear check",
"children": [
{
"type": "field",
"id": "member_id",
"label": "Member",
"inputType": "enum",
"options": [{"value": "m1", "label": "m1"}],
"default": inputs.get("member_id", "m1")
},
{
"type": "field",
"id": "v_star",
"label": "Design shear V* (N)",
"inputType": "number",
"default": inputs.get("v_star", 100000)
},
{"type": "button", "id": "run", "label": "Run check", "action": "run-check"}
]
}
def check(inputs):
model = json.loads(civilkit.getModel())
member_id = inputs.get("member_id", "")
props = json.loads(civilkit.getSectionProps("250UB25.7"))
fy = props.get("fy_MPa", 300)
d = props.get("d_mm", 248)
tw = props.get("tw_mm", 5)
aw = d * tw
phi = 0.9
phi_vv = phi * 0.6 * fy * aw / 1000.0
v_star = float(inputs.get("v_star", 0)) / 1000.0
util = v_star / phi_vv if phi_vv > 0 else 999
status = "OK" if util <= 1.0 else "OVER"
return {
"result": [
{"label": "phiVv", "value": round(phi_vv, 2), "unit": "kN"},
{"label": "Utilisation", "value": round(util, 3)},
{"label": "Status", "value": status, "status": "ok" if status == "OK" else "fail"}
],
"calcLines": [
{
"standard": "AS 4100",
"year": "1998",
"clause": "5.11",
"label": "Member shear capacity",
"eq": "phiVv = phi * 0.6 * fy * Aw = %.2f kN" % round(phi_vv, 2),
"tex": r"\phi V_v = \phi \cdot 0.6 \cdot f_y \cdot A_w"
}
]
}The host renders the UI tree returned by build_ui, calls check when the user clicks the run button, and renders the result list and calcLines working.
Capability bridge
The module calls the host through a least-privilege bridge. Declare only the capabilities you need:
| Capability | Returns |
|---|---|
civilkit.getModel() | The current model as a JSON string |
civilkit.getSelection() | The currently selected object, if any |
civilkit.getSectionProps(name) | Section geometry and analysis properties |
civilkit.memberCapacity(input) | AS 4100 member capacities from the engine |
civilkit.log(msg) | Sandbox-safe logging to the host console |
The module cannot call anything it did not declare, and it never touches the DOM directly.
Worked-example tests
A Verified module ships one or more cited worked examples. The host runs them on install and badges the module only if every example passes.
json
[
{
"id": "m1-100kN",
"input": {
"member_id": "m1",
"v_star": 100000,
"phi": 0.9
},
"expected": {
"result": [
{"label": "phiVv", "value": 200.88, "unit": "kN"},
{"label": "Utilisation", "value": 0.498},
{"label": "Status", "value": "OK"}
]
},
"source": "AS 4100-1998 Cl 5.11 hand calc: 0.9 * 0.6 * 300 MPa * 248 mm * 5 mm / 1000 = 200.88 kN."
}
]The installer compares the module's output against expected.result and labels the module:
- Verified - all bundled tests pass against cited worked examples.
- Community - installed, but tests are absent or not independently reviewed.
Installing and using a module
In the current experiments/py-module/demo.html host:
- Open the Modules tab.
- Drop a
.ckextfile onto the drop zone, or click Install on a module in the store. - The host validates the manifest, runs the worked-example tests, and badges it.
- The module appears under the Custom menu. Click it to open the check.
Modules are persisted in the browser's IndexedDB; they survive a page refresh. Use Uninstall to remove one.
Bundling your own module
- Create a directory with
manifest.json,main.py, andtests/worked-examples.json. - Add the module to
experiments/py-module/store/index.jsonif you want it in the local store. - Zip the contents from inside the directory:
bash
cd my-module
zip -r ../my-module.ckext manifest.json main.py tests- Load the demo, install the
.ckext, and run the check.
What's next for extensions
The current demo proves design-check Python modules. The same .ckext bundle shape will later support:
- importers - custom file formats returning a model patch
- load generators - wind, seismic, moving-load trains
- report sections - stamped calc-report contributions
- viewport overlays - host-drawn diagrams from module draw commands
- WASM modules - Nim/Rust/AssemblyScript compute cores
For the full contract, see docs/architecture/extension-system-spec.md in the repository.