adom-project-manager
Public Made by Adomby adom
Adom Project Manager — browse your wiki boards/projects (Personal / Organization / Public), view symbol + footprint + 3D and the per-EDA footprint layer stackup, explore the board and schematic in INT
name: publish-board description: Publish or update a KiCad project to the Adom wiki so it renders in the Adom Project Manager — 3D board, hierarchical schematic, PCB — backed by a component library. Triggers include "upload my kicad project to the wiki", "publish my board", "push my kicad project so I can view it in the project manager", "update my board on the wiki". user-invocable: true
Publish a KiCad board to the wiki
Turn a local KiCad project into a wiki board page that renders in the Adom Project Manager (rotatable 3D board with real components, hierarchical schematic, KiCad-colored PCB), backed by a component library.
Data model: board → library → components
- Board page —
type: component,category: board, tags["board", …](ormolecule). Ships the render files:.kicad_pro,.kicad_pcb, EVERY.kicad_sch(root + sub-sheets), and a<Board>.3dshapes/of custom 3D models. Its single dependency is the library. - Library page —
type: component, tag["library"], title"<Board Name> Library", slug<board-slug>-library.dependencies= every component on the board. Ships the board's.kicad_sym+.pretty. - Component pages — the existing per-component pages, keyed by MPN: slug =
the normalized MPN, title leads with the MPN. Never publish or depend on a
component keyed by its value/properties (e.g. slug
cap-2u2-0402-6v3, title "2.2uF 0402") — value names collide (many parts are "2.2uF 0402"), don't resolve MPN→slug, and break dedup + the dependency graph. If a board references a value-named component page, re-slug it to the MPN (or point the dep at the real MPN page) rather than depending on the value-named one.
The Manager reads the board's one dependency (the library), then lists the
library's dependencies (the components). board_deps expands any dependency that
itself has dependencies, so this resolves automatically.
Workflow
1. Pull the project (from the user's machine via adom-desktop)
Ask for / find the .kicad_pro. Pull the project folder (or at least):
.kicad_pro, .kicad_pcb, every .kicad_sch, .kicad_sym, .pretty/.
Use adom-desktop shell_execute (find the files) + pull_file.
2. Analyze it
Run the helper on the pulled folder:
python3 skills/publish-board/kicad_board_bundle.py <project-dir>
It reports the render files, board_name, the 3D model refs
(models_std vs models_custom), and the components (ref, value, mpn, slug).
3. Bundle the custom 3D models + normalize the refs
models_std (${KICAD*_3DMODEL_DIR}/…) resolve on the render service — leave
them. For each models_custom ref, pull the .step/.wrl from the user's
machine into <Board>.3dshapes/<basename>. Then normalize the PCB's model refs
to project-relative paths so the published source is portable:
python3 skills/publish-board/kicad_board_bundle.py <project-dir> --normalize
This rewrites every custom (model "…") ref to <Board>.3dshapes/<basename>
(forward slashes; KiCad resolves them next to the .kicad_pcb, and the Manager's
GLB render bundles them by basename), leaving ${KICAD*_3DMODEL_DIR} refs and
every offset/scale/rotate untouched.
NEVER publish a .kicad_pcb with machine-specific ABSOLUTE model paths
(/home/<user>/…, C:\Users\<user>\…). They resolve nowhere on the render
service or on anyone else's machine (and not even on the author's, if they wrote
them for a different OS). Run --normalize and confirm grep -E '\(model "(/|[A-Za-z]:\\\\)' <pcb> is empty before pushing.
4. Map components → wiki slugs (MPN → slug)
Slug = MPN lowercased, non-alphanumeric → -. The helper falls back to the
schematic Value when no MPN property exists — verify the slugs actually match
real wiki component pages (GET /api/v1/pages/<slug>), because value-named
symbols (R_4.3K_0402) are NOT wiki component slugs. Resolve the real MPN per
part (BOM, the symbol's MPN/LCSC field, or ask the user). Warn + list any that
aren't on the wiki — they won't appear in the component list until published.
5. Ensure each component renders in the Manager — REQUIRED (adom-lbr JSON)
The Manager renders a component's symbol + footprint + per-EDA layer stackup from
the canonical adom-lbr JSON on its page (<MPN>.adom-lbr.json). It falls back
to a lossy on-the-fly KiCad import ONLY if that file is absent — and renders
nothing for a component page that has only a footprint, only a symbol, or
non-KiCad sources. So every component on the board must carry a
<MPN>.adom-lbr.json on its wiki page; generate + push it wherever it's missing:
# fetch the component's KiCad files from its page, then convert:
adom-lbr import-kicad --sym <MPN>.kicad_sym --fp <MPN>.kicad_mod --mpn <MPN> # → <MPN>.adom-lbr.json
adom-wiki repo push <owner>/<slug> --files <MPN>.adom-lbr.json -m "add adom-lbr JSON for the Project Manager"
adom-lbr is the adom/adom-lbr EDA translator; the adom-lbr JSON is its canonical
hub (it can also import from Altium .SchLib/.PcbLib/.IntLib). Verify in the
Manager that the component's source reads "adom-lbr json", not "kicad (generated)".
Interim step: this conversion is moving into adom/molecule-publish (see its
issue #7) so the pipeline delivers the JSON automatically; do it here until then.
6. Library page — create or update, and VERIFY completeness
- Slug
<board-slug>-library, title"<Board Name> Library",type: component, tags["library"],dependencies= the owner-qualified component slugs. - On every update, ensure every component on the board is present in the library's dependencies; add any missing ones.
- Ship
.kicad_sym+.pretty. - Publish needs a hero (generate a simple 1200×630 billboard) + a 3D file for the
component type (reuse any component
.step):adom-wiki pkg publish [--org <org>] --skip-lint, thenrepo pushthepackage.json+.kicad_sym+.pretty.
7. Board page — create or update
type: component,category: board, tags["board", …],dependencies={ "<owner>/<board-slug>-library": "^0.1.0" }.- Needs a hero + a 3D file (reuse a component model or a board render).
pkg publish(this updates the wiki dependency GRAPH —repo pushalone does NOT), thenrepo push:.kicad_pro,.kicad_pcb, all.kicad_sch, the<Board>.3dshapes/. Set visibility open.
8. Regenerate the stored render assets — REQUIRED on every publish/update
After the board files are published, regenerate the pre-rendered assets so the Manager loads the board instantly (no live render) and the wiki 3D preview is fresh:
adom-project-manager --render-board <board-slug>
This renders the 3D GLB + PCB SVG + per-sheet schematic SVGs and pushes them to the
page's render/ folder (with a manifest.json). The Manager serves render/
directly when present and only falls back to live rendering when it's absent.
Stale render/ = the board shows its OLD 3D/PCB/schematic after an edit, so
never skip this after changing .kicad_pcb/.kicad_sch/models.
9. Verify
Open the Manager; confirm the board appears (Personal/Organization by owner) and its 3D + schematic + PCB render, and the component list matches the board.
Gotchas (learned the hard way)
- repo push ref: the component namespace is a single shared namespace. Use the
bare slug for
repo push <slug>;pkg publishneeds--org <org>if the slug is owned by an org (a409 already exists … owned by <org>tells you which). - Dependency graph vs file: the Manager reads the
package.jsonFILE (sorepo pushis enough for it), but the wiki's dependency-graph UI comes frompkg publish— re-publish (bump the version) to update the graph. - Hierarchical schematics: upload the
.kicad_pro+ EVERY.kicad_sch. The Manager renders the whole project so the root's sheet-symbol boxes resolve; a single sheet alone renders wrong. - 3D models: bundle every non-
${KICAD*_3DMODEL_DIR}(model …)into<Board>.3dshapes/and normalize the refs to<Board>.3dshapes/<basename>(step 3). Machine-specific absolute paths are the #1 cause of "board renders as a bare PCB / the render service errors" — and they break even on the author's own box if written for a different OS. The Manager bundles by basename so relative, Unix-absolute, and Windows-absolute all render, but only relative paths are portable source, so always normalize before publishing. - Every page needs a hero; components additionally need a 3D file — even the library. Generate/reuse one to pass the (hard-enforced) publish lint.
---
name: publish-board
description: Publish or update a KiCad project to the Adom wiki so it renders in the Adom Project Manager — 3D board, hierarchical schematic, PCB — backed by a component library. Triggers include "upload my kicad project to the wiki", "publish my board", "push my kicad project so I can view it in the project manager", "update my board on the wiki".
user-invocable: true
---
# Publish a KiCad board to the wiki
Turn a local KiCad project into a wiki board page that renders in the **Adom
Project Manager** (rotatable 3D board with real components, hierarchical
schematic, KiCad-colored PCB), backed by a component **library**.
## Data model: board → library → components
- **Board page** — `type: component`, `category: board`, tags `["board", …]` (or
`molecule`). Ships the render files: `.kicad_pro`, `.kicad_pcb`, EVERY
`.kicad_sch` (root + sub-sheets), and a `<Board>.3dshapes/` of custom 3D
models. Its single dependency is the library.
- **Library page** — `type: component`, tag `["library"]`, title
`"<Board Name> Library"`, slug `<board-slug>-library`. `dependencies` = every
component on the board. Ships the board's `.kicad_sym` + `.pretty`.
- **Component pages** — the existing per-component pages, **keyed by MPN**: slug =
the normalized MPN, title leads with the MPN. **Never publish or depend on a
component keyed by its value/properties** (e.g. slug `cap-2u2-0402-6v3`, title
"2.2uF 0402") — value names collide (many parts are "2.2uF 0402"), don't resolve
MPN→slug, and break dedup + the dependency graph. If a board references a
value-named component page, re-slug it to the MPN (or point the dep at the real
MPN page) rather than depending on the value-named one.
The Manager reads the board's one dependency (the library), then lists the
library's dependencies (the components). `board_deps` expands any dependency that
itself has dependencies, so this resolves automatically.
## Workflow
### 1. Pull the project (from the user's machine via `adom-desktop`)
Ask for / find the `.kicad_pro`. Pull the project folder (or at least):
`.kicad_pro`, `.kicad_pcb`, **every** `.kicad_sch`, `.kicad_sym`, `.pretty/`.
Use `adom-desktop shell_execute` (find the files) + `pull_file`.
### 2. Analyze it
Run the helper on the pulled folder:
```
python3 skills/publish-board/kicad_board_bundle.py <project-dir>
```
It reports the render files, `board_name`, the 3D model refs
(`models_std` vs `models_custom`), and the `components` (ref, value, mpn, slug).
### 3. Bundle the custom 3D models + normalize the refs
`models_std` (`${KICAD*_3DMODEL_DIR}/…`) resolve on the render service — leave
them. For each `models_custom` ref, pull the `.step`/`.wrl` from the user's
machine into `<Board>.3dshapes/<basename>`. Then **normalize the PCB's model refs
to project-relative paths** so the published source is portable:
```
python3 skills/publish-board/kicad_board_bundle.py <project-dir> --normalize
```
This rewrites every custom `(model "…")` ref to `<Board>.3dshapes/<basename>`
(forward slashes; KiCad resolves them next to the `.kicad_pcb`, and the Manager's
GLB render bundles them by basename), leaving `${KICAD*_3DMODEL_DIR}` refs and
every `offset`/`scale`/`rotate` untouched.
**NEVER publish a `.kicad_pcb` with machine-specific ABSOLUTE model paths**
(`/home/<user>/…`, `C:\Users\<user>\…`). They resolve nowhere on the render
service or on anyone else's machine (and not even on the author's, if they wrote
them for a different OS). Run `--normalize` and confirm `grep -E '\(model "(/|[A-Za-z]:\\\\)' <pcb>` is empty before pushing.
### 4. Map components → wiki slugs (MPN → slug)
Slug = MPN lowercased, non-alphanumeric → `-`. **The helper falls back to the
schematic `Value` when no MPN property exists** — verify the slugs actually match
real wiki component pages (`GET /api/v1/pages/<slug>`), because value-named
symbols (`R_4.3K_0402`) are NOT wiki component slugs. Resolve the real MPN per
part (BOM, the symbol's MPN/LCSC field, or ask the user). Warn + list any that
aren't on the wiki — they won't appear in the component list until published.
### 5. Ensure each component renders in the Manager — REQUIRED (adom-lbr JSON)
The Manager renders a component's symbol + footprint + per-EDA layer stackup from
the canonical **adom-lbr JSON** on its page (`<MPN>.adom-lbr.json`). It falls back
to a lossy on-the-fly KiCad import ONLY if that file is absent — and renders
**nothing** for a component page that has only a footprint, only a symbol, or
non-KiCad sources. So every component on the board must carry a
`<MPN>.adom-lbr.json` on its wiki page; generate + push it wherever it's missing:
```bash
# fetch the component's KiCad files from its page, then convert:
adom-lbr import-kicad --sym <MPN>.kicad_sym --fp <MPN>.kicad_mod --mpn <MPN> # → <MPN>.adom-lbr.json
adom-wiki repo push <owner>/<slug> --files <MPN>.adom-lbr.json -m "add adom-lbr JSON for the Project Manager"
```
`adom-lbr` is the `adom/adom-lbr` EDA translator; the adom-lbr JSON is its canonical
hub (it can also import from Altium `.SchLib`/`.PcbLib`/`.IntLib`). Verify in the
Manager that the component's source reads **"adom-lbr json"**, not "kicad (generated)".
**Interim step:** this conversion is moving into `adom/molecule-publish` (see its
issue #7) so the pipeline delivers the JSON automatically; do it here until then.
### 6. Library page — create or update, and VERIFY completeness
- Slug `<board-slug>-library`, title `"<Board Name> Library"`, `type: component`,
tags `["library"]`, `dependencies` = the owner-qualified component slugs.
- **On every update, ensure every component on the board is present in the
library's dependencies; add any missing ones.**
- Ship `.kicad_sym` + `.pretty`.
- Publish needs a hero (generate a simple 1200×630 billboard) + a 3D file for the
component type (reuse any component `.step`): `adom-wiki pkg publish [--org <org>] --skip-lint`,
then `repo push` the `package.json` + `.kicad_sym` + `.pretty`.
### 7. Board page — create or update
- `type: component`, `category: board`, tags `["board", …]`,
`dependencies` = `{ "<owner>/<board-slug>-library": "^0.1.0" }`.
- Needs a hero + a 3D file (reuse a component model or a board render).
- `pkg publish` (this updates the wiki dependency GRAPH — `repo push` alone does
NOT), then `repo push`: `.kicad_pro`, `.kicad_pcb`, all `.kicad_sch`, the
`<Board>.3dshapes/`. Set visibility open.
### 8. Regenerate the stored render assets — REQUIRED on every publish/update
After the board files are published, regenerate the pre-rendered assets so the
Manager loads the board instantly (no live render) and the wiki 3D preview is fresh:
```
adom-project-manager --render-board <board-slug>
```
This renders the 3D GLB + PCB SVG + per-sheet schematic SVGs and pushes them to the
page's `render/` folder (with a `manifest.json`). The Manager serves `render/`
directly when present and only falls back to live rendering when it's absent.
**Stale `render/` = the board shows its OLD 3D/PCB/schematic after an edit**, so
never skip this after changing `.kicad_pcb`/`.kicad_sch`/models.
### 9. Verify
Open the Manager; confirm the board appears (Personal/Organization by owner) and
its 3D + schematic + PCB render, and the component list matches the board.
## Gotchas (learned the hard way)
- **repo push ref**: the component namespace is a single shared namespace. Use the
**bare slug** for `repo push <slug>`; `pkg publish` needs `--org <org>` if the
slug is owned by an org (a `409 already exists … owned by <org>` tells you which).
- **Dependency graph vs file**: the Manager reads the `package.json` FILE (so
`repo push` is enough for it), but the wiki's dependency-graph UI comes from
`pkg publish` — re-publish (bump the version) to update the graph.
- **Hierarchical schematics**: upload the `.kicad_pro` + EVERY `.kicad_sch`. The
Manager renders the whole project so the root's sheet-symbol boxes resolve; a
single sheet alone renders wrong.
- **3D models**: bundle every non-`${KICAD*_3DMODEL_DIR}` `(model …)` into
`<Board>.3dshapes/` and **normalize** the refs to `<Board>.3dshapes/<basename>`
(step 3). Machine-specific absolute paths are the #1 cause of "board renders as
a bare PCB / the render service errors" — and they break even on the author's
own box if written for a different OS. The Manager bundles by basename so
relative, Unix-absolute, and Windows-absolute all *render*, but only relative
paths are portable *source*, so always normalize before publishing.
- **Every page needs a hero**; components additionally need a 3D file — even the
library. Generate/reuse one to pass the (hard-enforced) publish lint.