molecule-publish
Public Made by Adomby adom
Publish molecules AND generic boards to the Adom wiki - one publisher, two shapes: OCCT conversion (molecule mode with stats gates, or plain for boards), component packaging, adom-wiki publish, APM re
name: molecule-publish description: Publish a molecule OR a generic KiCad/EAGLE board to the Adom wiki - one publisher, two shapes — runs the OCCT molecule-mode conversion (anchored GLB + footprint + symbol with stats gates), assembles the component package, and publishes via adom-wiki. The EDA-agnostic middle of the pipeline; companion to adom-molecule-import (which does wiki → Hydrogen). Use when the user says "publish this molecule to the wiki", "upload molecule bundle", "convert and publish my molecule", "molecule to the wiki", "publish my board" (plain, non-molecule boards use BOARD MODE - no anchoring gates), or an EDA export skill (kicad-export-molecule, fusion-export-molecule, altium-export-molecule) hands off here after exporting. Every publish also emits the render/ assets (including APM's per-version render archive behind the board version selector) and component dependencies adom-project-manager (APM) reads. user-invocable: true argument-hint: " --step <f.step> --board <f.kicad_pcb|f.brd> --sch [--pin medium|large] [--silk-top png --silk-bottom png] [--org adom]"
molecule-publish — source bundle → wiki molecule
The EDA-agnostic middle of the molecule pipeline. Input is the bare-minimum
bundle any EDA export produces; output is a published, pipeline-ready wiki
component. The Hydrogen half is adom-molecule-import — this skill is its
publish-side companion.
EDA export skill THIS SKILL adom-molecule-import
(kicad/fusion/altium) → convert → package → publish → wiki → Hydrogen
Two shapes: molecule vs board
| Molecule (machine pins + MP markers) | Board (plain KiCad/EAGLE) | |
|---|---|---|
| Convert | --molecule --board (anchor/gold/footprint, ALL stats gates) |
plain step2glb convert (no molecule flags, no anchor gates) |
| Tag | molecule |
board |
| Footprint/symbol JSON | required (wire attach points) | not applicable |
| render/ + deps (APM) | yes | yes |
Decide by the board itself: Adom machine pins + MP1-MP4 markers -> molecule;
otherwise board. Both shapes get <slug>.glb from step2glb (never an
EDA-native GLB), model_3d_path pointing at it, and the APM stages below.
Contract — inputs vs the published set
The user supplies sources; this skill generates and attaches the rest. The published page always carries the full set — GLB + STEP + schematic + board + metadata — and every downstream tool expects all five (import reuses the GLB, wiring reads the metadata). The GLB and footprint/symbol JSON are never user-supplied: they come out of the OCCT conversion below.
Inputs — the bare-minimum bundle
| Required | File | Notes |
|---|---|---|
| yes | STEP (.step) |
exported ON the design machine so all 3D models (machine pins, contacts, MP markers) are baked in |
| yes | Board/layout (.kicad_pcb or .brd) |
what footprint+symbol generation parses |
| yes | Schematic — .kicad_sch (EVERY sheet: root + sub-sheets) or .sch |
source completeness + APM's hierarchical schematic view renders from these |
| board shape | .kicad_pro + any .kicad_sym/.pretty used |
APM render sources |
| generated | GLB | OCCT conversion output — never user-supplied, always published |
| generated | Metadata | OCCT footprint/symbol JSONs + the authored package.json |
| optional | Silk PNGs (top/bottom) | white artwork on transparent |
| optional | Extras | .f3d/.usdz/gerbers/BOM/CPL — carry what the EDA produced |
Rule: never accept an EDA-native GLB. KiCad, Fusion, and service-kicad can all emit GLBs — those bypass anchoring, gold materials, meter normalization, optimization, and footprint emit. The ONLY GLB in a molecule package comes from the OCCT conversion below.
Stage 1 — Convert (OCCT molecule mode)
step2glb convert <name>.step --board <name>.kicad_pcb --pin medium \
-o <slug>.glb # --board implies --molecule; add --silk-top/--silk-bottom PNGs
Requires step2glb >= 0.11.0 (adom-wiki pkg install adom/adom-step2glb).
(No adom-wiki on the container? Bootstrap it first:
curl -fsSL https://wiki.adom.inc/download/adom/adom-wiki-cli/1.0.2/adom-wiki-cli-v1.0.2 -o ~/.local/bin/adom-wiki && chmod +x ~/.local/bin/adom-wiki — then keep using adom-wiki, not legacy tools.)
It posts multipart to /convert?molecule=true&pin=..., polls the job,
downloads the GLB and <slug>_footprint.json + <slug>_symbol.json
beside it, prints the full stats block, and emits gate hints on failures.
Fallback (older CLI): curl -X POST ".../convert?molecule=true&pin=..." -H "X-Client: <agent>" -H "X-Job-Name: <name>" -F "step=@..." -F "board=@...".
Board shape: use a plain convert instead — step2glb convert <name>.step -o <slug>.glb — and SKIP the molecule stats gates below (they do not apply;
if the output warns molecule_markers_detected, it IS a molecule — switch).
pin = machine-pin size on the board (medium | large). Poll
GET /jobs/{id} until complete, then gate on the stats — never publish a
degraded conversion:
| Field | Must be | If not |
|---|---|---|
anchored |
true |
MP markers missing/undetected — fix the board, re-export |
footprint_applied |
true |
board parse failed — read warnings[] |
contact_z |
≈2.8–8.4 mm | wrong pin param or missing contact models |
warnings[] |
empty | each entry is a stop-sign, not a footnote |
Artifacts: GET /jobs/{id}/result → <name>.glb,
/jobs/{id}/footprint → <name>_footprint.json,
/jobs/{id}/symbol → <name>_symbol.json.
Stage 2 — Package
<slug>/
package.json # see REQUIRED fields below
<slug>.glb # OCCT artifact — MUST be named exactly <slug>.glb (see below)
<name>.kicad_pcb|.brd # board source
<name>.kicad_sch|.sch # schematic source
<name>_footprint.json # OCCT artifact — per-pad wire-attach Z
<name>_symbol.json # OCCT artifact
README.md
[extras: silk PNGs, .f3d, .usdz, gerbers, bom, cpl]
package.json REQUIRED fields (publish 400s or silently under-registers
without them):
{
"slug": "<slug>", "version": "1.0.0", "type": "component",
"description": "<≥20 chars>", "tags": ["molecule", "..."],
"component": { "mpn": "<name>", "manufacturer": "", "category": "other" },
"dependencies": {},
"hero": { "headline": "...", "subhead": "...", "screenshot": "screenshots/hero.png" }
}
- The
componentblock is what creates the page's component_metadata row — without itmetadata.model_3d_pathis never set and imports fail with "no published GLB" even though the file is there. - The
heroblock +screenshots/hero.pngare hard-required at publish.
Do NOT include a page.json — the server generates it, and a hand-made one
can blank the page brief or override org/visibility on reindex.
Name the GLB exactly <slug>.glb. At publish the wiki auto-converts the
STEP to a PLAIN <slug>.glb (no anchoring, no gold) and points
model_3d_path at it — if your anchored OCCT GLB has any other name, the
plain one shadows it and every import silently gets an unanchored model.
(This is exactly what broke the COSMIIC boards.) Matching the name ensures
your anchored GLB is the one model_3d_path resolves to.
Stage 2.5 — Component dependencies (BEFORE publish — one version per cycle)
APM lists a board/molecule's components from package.json.dependencies
(one-hop expand). Map the design's BOM parts to wiki component slugs and
MERGE them into the Stage 2 package.json — before Stage 3's publish, so
each publish cycle produces exactly ONE registry version (a deps-only
follow-up publish creates an extra version whose renders are identical:
harmless under APM's dedup, but noise in the version selector).
- Mapping helper:
skills/publish-board/kicad_board_bundle.pyon theadom/adom-project-managerpage (adom-wiki repo clone adom/adom-project-manager). Mind its Value-fallback caveat: value-named symbols likeR_4.3K_0402are NOT component slugs — resolve the real MPN. - Write owner-qualified refs (
adom/<slug>) intodependencies. MERGE, never overwrite — preservecomponent,hero,tags,model_3d_path. - Verify each referenced component page exists; flag missing ones.
- The dependency graph is a REGISTRY concept — it rides Stage 3's
pkg publish, not the repo push. - Known behavior to keep in mind: deps are real registry deps, so
pkg install <board>will pull the component pages too.
Stage 3 — Publish + verify
adom-wiki pkg publish [--org adom]
adom-wiki repo push <owner>/<slug> --files <every file above> -m "<name> molecule"
adom-wiki page visibility <owner>/<slug> --preset open # or private
Verify before declaring done:
adom-wiki api /api/v1/pages/<slug>→metadata.model_3d_pathis set- the GLB at
model_3d_pathis byte-identical to YOUR gated conversion output — this is the anchoring proof. (Do NOT inspect the GLB for amolecule_anchornode: the optimizer flattens it away by design — the anchoring survives as baked geometry, not as a node. A gate on that node false-fails every properly converted molecule.)
Your conversion's stats block (curl -fsSL "https://wiki.adom.inc/blob/component/<slug>/<slug>.glb" -o /tmp/check.glb sha256sum /tmp/check.glb <slug>.glb # MUST match — if not, the page is # serving a different GLB (e.g. the wiki's plain auto-conversion): re-push # your OCCT GLB as <slug>.glb and re-verify.molecule_anchored: true, no warnings) plus this checksum equals a verified anchored GLB on the page. - the page's Files tab shows the full bundle (registry and git layers are separate — publish alone does not populate Files)
- the registry tarball is the source of record per version: Stage 2's
layout means every publish carries the full board source, and
adom-wiki pkg install <owner>/<slug>@<version>delivers any past version's files (APM's version selector relies on this for "give me the source of an older version" — render/ is previews only, never source).
Stage 3.5 — APM render assets + version archive (AFTER publish, every time)
APM shows PCB + hierarchical schematics + the board version selector
from a pre-rendered render/ folder; without it, boards trip APM's red
"missing render folder" bar and fall back to slow live rendering.
adom-wiki pkg install adom/adom-project-manager # once per container (needs >= 0.4.1)
adom-project-manager --render-board <slug> # push-only: writes ONLY render/
Ordering is load-bearing: run this AFTER Stage 3's pkg publish + repo
push. --render-board stamps the archive with the version it reads from
the PUBLISHED package.json on the page — run it before the publish and it
stamps the previous version.
--render-board (APM >= 0.4.0) fully owns the version archive — never
write render/<version>/ or edit render/manifest.json yourself
(double-writing fights its content dedup). On each run it:
- renders + pushes the top-level
render/*= current version (includingrender/board.glbwhenever a GLB exists); - content-hashes the rendered assets and, ONLY if they differ from the last
archived version, writes
render/<version>/...and prepends aversions[]entry tomanifest.json(v2:{v:2, current, versions[]}, newest-first). A deps/metadata-only republish adds NO entry.
Verify after the run:
render/manifest.jsonis on the page, parses, andcurrent== the version you just published;- a content-changing publish added a
versions[]entry +render/<version>/files; a metadata-only republish did NOT (dedup working as intended).
Re-run on every content update so it never goes stale. KiCad sources render
today; EAGLE/Fusion (.brd/.sch) pages report "nothing rendered" and skip
gracefully — APM shows a static version label for them (Fusion rendering is
landing in APM; nothing changes on this side when it does).
Stage 4 — Handoff
Import to Hydrogen is adom-molecule-import's job (ships with
adom/adom-molecule): authenticated clone + adom-molecule create --glb ... --no-optimize. Do not re-implement it here.
Attach-points caveat: adom-molecule import <slug> (the one-shot verb)
currently carries ONLY the GLB — no footprint/symbol reach Hydrogen, so the
molecule has no wire attach points. Until that's fixed, register with the
board included so Hydrogen generates and attaches the footprint at create:
adom-molecule create --owner <o> --name <n> --glb <slug>.glb --pcb <board> --no-optimize (use --brd for EAGLE/Fusion boards).
Page polish rules (field-tested — molecule-pipeline #190)
Hard-won from ~10 real imports; each one cost a debugging detour:
- Heroes on board/component pages are static images —
page hero --image, never--screenshot/billboard (billboard composes an app-style browser frame around the render: "images within images"). - Browse-card thumbnails bake at publish time — a repo-only hero push does NOT refresh the card. Republish with a version bump, then verify the served card PNG actually changed (sha256 the blob).
- Keep board pages PDF-free. Any PDF in the repo becomes an unwanted auto-scanned "Datasheet" section with no manifest opt-out — ship docs on a dedicated docs page or as release assets instead.
- Draco-compress big scene GLBs only. Multi-MB workcell/scene models:
gltf-transform optimize --compress draco(35 MB → ~1.3 MB, <3 s load). Chip/molecule-sized GLBs: do NOT draco — it comes out ~40% BIGGER than quantized and the wiki readme sandbox can't decode it (adom-step2glb #3). Your published molecule GLB is already optimized by OCCT — leave it alone. - Plain components (no MP markers) skip axis normalization — molecule
mode anchors Z-up, but a plain
step2glb convertpreserves the source STEP's axes; check orientation per board and bake a ±90° X root rotation only when the source needs it. - Wiki page animations are baked glTF animations in the viewer GLB — GIFs only work inside README sections.
Related
adom-molecule-import— the wiki → Hydrogen companionkicad-export-molecule/fusion-export-molecule/altium-export-molecule— the EDA → bundle front-ends that hand off hereadom-step2glb— the conversion CLI/service this skill drivesmolecule-pipeline— the top-level router across the whole chain
---
name: molecule-publish
description: Publish a molecule OR a generic KiCad/EAGLE board to the Adom wiki - one publisher, two shapes — runs the OCCT molecule-mode conversion (anchored GLB + footprint + symbol with stats gates), assembles the component package, and publishes via adom-wiki. The EDA-agnostic middle of the pipeline; companion to adom-molecule-import (which does wiki → Hydrogen). Use when the user says "publish this molecule to the wiki", "upload molecule bundle", "convert and publish my molecule", "molecule to the wiki", "publish my board" (plain, non-molecule boards use BOARD MODE - no anchoring gates), or an EDA export skill (kicad-export-molecule, fusion-export-molecule, altium-export-molecule) hands off here after exporting. Every publish also emits the render/ assets (including APM's per-version render archive behind the board version selector) and component dependencies adom-project-manager (APM) reads.
user-invocable: true
argument-hint: "<name> --step <f.step> --board <f.kicad_pcb|f.brd> --sch <schematic> [--pin medium|large] [--silk-top png --silk-bottom png] [--org adom]"
---
# molecule-publish — source bundle → wiki molecule
The EDA-agnostic middle of the molecule pipeline. Input is the **bare-minimum
bundle** any EDA export produces; output is a published, pipeline-ready wiki
component. The Hydrogen half is `adom-molecule-import` — this skill is its
publish-side companion.
```
EDA export skill THIS SKILL adom-molecule-import
(kicad/fusion/altium) → convert → package → publish → wiki → Hydrogen
```
## Two shapes: molecule vs board
| | **Molecule** (machine pins + MP markers) | **Board** (plain KiCad/EAGLE) |
|---|---|---|
| Convert | `--molecule --board` (anchor/gold/footprint, ALL stats gates) | plain `step2glb convert` (no molecule flags, no anchor gates) |
| Tag | `molecule` | `board` |
| Footprint/symbol JSON | required (wire attach points) | not applicable |
| render/ + deps (APM) | yes | yes |
Decide by the board itself: Adom machine pins + MP1-MP4 markers -> molecule;
otherwise board. Both shapes get `<slug>.glb` from step2glb (never an
EDA-native GLB), `model_3d_path` pointing at it, and the APM stages below.
## Contract — inputs vs the published set
**The user supplies sources; this skill generates and attaches the rest.**
The published page always carries the full set — **GLB + STEP + schematic +
board + metadata** — and every downstream tool expects all five (import
reuses the GLB, wiring reads the metadata). The GLB and footprint/symbol
JSON are never user-supplied: they come out of the OCCT conversion below.
### Inputs — the bare-minimum bundle
| Required | File | Notes |
|---|---|---|
| yes | STEP (`.step`) | exported ON the design machine so all 3D models (machine pins, contacts, MP markers) are baked in |
| yes | Board/layout (`.kicad_pcb` or `.brd`) | what footprint+symbol generation parses |
| yes | Schematic — `.kicad_sch` (EVERY sheet: root + sub-sheets) or `.sch` | source completeness + APM's hierarchical schematic view renders from these |
| board shape | `.kicad_pro` + any `.kicad_sym`/`.pretty` used | APM render sources |
| generated | GLB | OCCT conversion output — never user-supplied, always published |
| generated | Metadata | OCCT footprint/symbol JSONs + the authored `package.json` |
| optional | Silk PNGs (top/bottom) | white artwork on transparent |
| optional | Extras | `.f3d`/`.usdz`/gerbers/BOM/CPL — carry what the EDA produced |
**Rule: never accept an EDA-native GLB.** KiCad, Fusion, and service-kicad can
all emit GLBs — those bypass anchoring, gold materials, meter normalization,
optimization, and footprint emit. The ONLY GLB in a molecule package comes
from the OCCT conversion below.
## Stage 1 — Convert (OCCT molecule mode)
```bash
step2glb convert <name>.step --board <name>.kicad_pcb --pin medium \
-o <slug>.glb # --board implies --molecule; add --silk-top/--silk-bottom PNGs
```
Requires `step2glb` >= 0.11.0 (`adom-wiki pkg install adom/adom-step2glb`).
(No `adom-wiki` on the container? Bootstrap it first:
`curl -fsSL https://wiki.adom.inc/download/adom/adom-wiki-cli/1.0.2/adom-wiki-cli-v1.0.2 -o ~/.local/bin/adom-wiki && chmod +x ~/.local/bin/adom-wiki` — then keep using `adom-wiki`, not legacy tools.)
It posts multipart to `/convert?molecule=true&pin=...`, polls the job,
downloads the GLB **and** `<slug>_footprint.json` + `<slug>_symbol.json`
beside it, prints the full stats block, and emits gate hints on failures.
Fallback (older CLI): `curl -X POST ".../convert?molecule=true&pin=..."
-H "X-Client: <agent>" -H "X-Job-Name: <name>" -F "step=@..." -F "board=@..."`.
**Board shape:** use a plain convert instead — `step2glb convert <name>.step
-o <slug>.glb` — and SKIP the molecule stats gates below (they do not apply;
if the output warns `molecule_markers_detected`, it IS a molecule — switch).
`pin` = machine-pin size on the board (`medium` | `large`). Poll
`GET /jobs/{id}` until complete, then **gate on the stats — never publish a
degraded conversion**:
| Field | Must be | If not |
|---|---|---|
| `anchored` | `true` | MP markers missing/undetected — fix the board, re-export |
| `footprint_applied` | `true` | board parse failed — read `warnings[]` |
| `contact_z` | ≈2.8–8.4 mm | wrong `pin` param or missing contact models |
| `warnings[]` | empty | each entry is a stop-sign, not a footnote |
Artifacts: `GET /jobs/{id}/result` → `<name>.glb`,
`/jobs/{id}/footprint` → `<name>_footprint.json`,
`/jobs/{id}/symbol` → `<name>_symbol.json`.
## Stage 2 — Package
```
<slug>/
package.json # see REQUIRED fields below
<slug>.glb # OCCT artifact — MUST be named exactly <slug>.glb (see below)
<name>.kicad_pcb|.brd # board source
<name>.kicad_sch|.sch # schematic source
<name>_footprint.json # OCCT artifact — per-pad wire-attach Z
<name>_symbol.json # OCCT artifact
README.md
[extras: silk PNGs, .f3d, .usdz, gerbers, bom, cpl]
```
`package.json` REQUIRED fields (publish 400s or silently under-registers
without them):
```json
{
"slug": "<slug>", "version": "1.0.0", "type": "component",
"description": "<≥20 chars>", "tags": ["molecule", "..."],
"component": { "mpn": "<name>", "manufacturer": "", "category": "other" },
"dependencies": {},
"hero": { "headline": "...", "subhead": "...", "screenshot": "screenshots/hero.png" }
}
```
- The **`component` block is what creates the page's component_metadata row —
without it `metadata.model_3d_path` is never set and imports fail** with
"no published GLB" even though the file is there.
- The **`hero` block + `screenshots/hero.png` are hard-required** at publish.
Do NOT include a `page.json` — the server generates it, and a hand-made one
can blank the page brief or override org/visibility on reindex.
**Name the GLB exactly `<slug>.glb`.** At publish the wiki auto-converts the
STEP to a PLAIN `<slug>.glb` (no anchoring, no gold) and points
`model_3d_path` at it — if your anchored OCCT GLB has any other name, the
plain one shadows it and every import silently gets an unanchored model.
(This is exactly what broke the COSMIIC boards.) Matching the name ensures
your anchored GLB is the one `model_3d_path` resolves to.
## Stage 2.5 — Component dependencies (BEFORE publish — one version per cycle)
APM lists a board/molecule's components from `package.json.dependencies`
(one-hop expand). Map the design's BOM parts to wiki component slugs and
MERGE them into the Stage 2 `package.json` — before Stage 3's publish, so
each publish cycle produces exactly ONE registry version (a deps-only
follow-up publish creates an extra version whose renders are identical:
harmless under APM's dedup, but noise in the version selector).
- Mapping helper: `skills/publish-board/kicad_board_bundle.py` on the
`adom/adom-project-manager` page (`adom-wiki repo clone adom/adom-project-manager`).
Mind its Value-fallback caveat: value-named symbols like `R_4.3K_0402` are
NOT component slugs — resolve the real MPN.
- Write owner-qualified refs (`adom/<slug>`) into `dependencies`. **MERGE,
never overwrite** — preserve `component`, `hero`, `tags`, `model_3d_path`.
- Verify each referenced component page exists; flag missing ones.
- The dependency graph is a REGISTRY concept — it rides Stage 3's
`pkg publish`, not the repo push.
- Known behavior to keep in mind: deps are real registry deps, so
`pkg install <board>` will pull the component pages too.
## Stage 3 — Publish + verify
```bash
adom-wiki pkg publish [--org adom]
adom-wiki repo push <owner>/<slug> --files <every file above> -m "<name> molecule"
adom-wiki page visibility <owner>/<slug> --preset open # or private
```
Verify before declaring done:
- `adom-wiki api /api/v1/pages/<slug>` → `metadata.model_3d_path` is set
- **the GLB at `model_3d_path` is byte-identical to YOUR gated conversion
output** — this is the anchoring proof. (Do NOT inspect the GLB for a
`molecule_anchor` node: the optimizer flattens it away by design — the
anchoring survives as baked geometry, not as a node. A gate on that node
false-fails every properly converted molecule.)
```bash
curl -fsSL "https://wiki.adom.inc/blob/component/<slug>/<slug>.glb" -o /tmp/check.glb
sha256sum /tmp/check.glb <slug>.glb # MUST match — if not, the page is
# serving a different GLB (e.g. the wiki's plain auto-conversion): re-push
# your OCCT GLB as <slug>.glb and re-verify.
```
Your conversion's stats block (`molecule_anchored: true`, no warnings) plus
this checksum equals a verified anchored GLB on the page.
- the page's Files tab shows the full bundle (registry and git layers are
separate — publish alone does not populate Files)
- the registry tarball is the **source of record per version**: Stage 2's
layout means every publish carries the full board source, and
`adom-wiki pkg install <owner>/<slug>@<version>` delivers any past
version's files (APM's version selector relies on this for "give me the
source of an older version" — render/ is previews only, never source).
## Stage 3.5 — APM render assets + version archive (AFTER publish, every time)
APM shows PCB + hierarchical schematics + the board **version selector**
from a pre-rendered `render/` folder; without it, boards trip APM's red
"missing render folder" bar and fall back to slow live rendering.
```bash
adom-wiki pkg install adom/adom-project-manager # once per container (needs >= 0.4.1)
adom-project-manager --render-board <slug> # push-only: writes ONLY render/
```
**Ordering is load-bearing: run this AFTER Stage 3's `pkg publish` + repo
push.** `--render-board` stamps the archive with the version it reads from
the PUBLISHED `package.json` on the page — run it before the publish and it
stamps the previous version.
`--render-board` (APM >= 0.4.0) **fully owns the version archive** — never
write `render/<version>/` or edit `render/manifest.json` yourself
(double-writing fights its content dedup). On each run it:
- renders + pushes the top-level `render/*` = current version (including
`render/board.glb` whenever a GLB exists);
- content-hashes the rendered assets and, ONLY if they differ from the last
archived version, writes `render/<version>/...` and prepends a
`versions[]` entry to `manifest.json` (v2: `{v:2, current, versions[]}`,
newest-first). A deps/metadata-only republish adds NO entry.
Verify after the run:
- `render/manifest.json` is on the page, parses, and `current` == the
version you just published;
- a content-changing publish added a `versions[]` entry + `render/<version>/`
files; a metadata-only republish did NOT (dedup working as intended).
Re-run on every content update so it never goes stale. KiCad sources render
today; EAGLE/Fusion (`.brd`/`.sch`) pages report "nothing rendered" and skip
gracefully — APM shows a static version label for them (Fusion rendering is
landing in APM; nothing changes on this side when it does).
## Stage 4 — Handoff
Import to Hydrogen is `adom-molecule-import`'s job (ships with
`adom/adom-molecule`): authenticated clone + `adom-molecule create --glb ...
--no-optimize`. Do not re-implement it here.
**Attach-points caveat:** `adom-molecule import <slug>` (the one-shot verb)
currently carries ONLY the GLB — no footprint/symbol reach Hydrogen, so the
molecule has no wire attach points. Until that's fixed, register with the
board included so Hydrogen generates and attaches the footprint at create:
`adom-molecule create --owner <o> --name <n> --glb <slug>.glb --pcb <board>
--no-optimize` (use `--brd` for EAGLE/Fusion boards).
## Page polish rules (field-tested — molecule-pipeline #190)
Hard-won from ~10 real imports; each one cost a debugging detour:
- **Heroes on board/component pages are static images** — `page hero --image`,
never `--screenshot`/billboard (billboard composes an app-style browser
frame around the render: "images within images").
- **Browse-card thumbnails bake at publish time** — a repo-only hero push
does NOT refresh the card. Republish with a version bump, then verify the
served card PNG actually changed (sha256 the blob).
- **Keep board pages PDF-free.** Any PDF in the repo becomes an unwanted
auto-scanned "Datasheet" section with no manifest opt-out — ship docs on a
dedicated docs page or as release assets instead.
- **Draco-compress big scene GLBs only.** Multi-MB workcell/scene models:
`gltf-transform optimize --compress draco` (35 MB → ~1.3 MB, <3 s load).
Chip/molecule-sized GLBs: do NOT draco — it comes out ~40% BIGGER than
quantized and the wiki readme sandbox can't decode it (adom-step2glb #3).
Your published molecule GLB is already optimized by OCCT — leave it alone.
- **Plain components (no MP markers) skip axis normalization** — molecule
mode anchors Z-up, but a plain `step2glb convert` preserves the source
STEP's axes; check orientation per board and bake a ±90° X root rotation
only when the source needs it.
- **Wiki page animations are baked glTF animations** in the viewer GLB —
GIFs only work inside README sections.
## Related
- `adom-molecule-import` — the wiki → Hydrogen companion
- `kicad-export-molecule` / `fusion-export-molecule` / `altium-export-molecule` — the EDA → bundle front-ends that hand off here
- `adom-step2glb` — the conversion CLI/service this skill drives
- `molecule-pipeline` — the top-level router across the whole chain