Adom Footprint
Public Made by Adomby adom
KiCad footprint creator with layer HUD viewer and delivery to KiCad/Fusion 360
name: adom-footprint description: "Use when the user asks to create a KiCad footprint, make a .kicad_mod, design a PCB footprint, build a footprint for a part, preview a footprint in FpView, lint a footprint, send a footprint to KiCad or Fusion 360, or view pad positions and solder blob layout. Also trigger for footprint-related questions like pad size, courtyard rules, or silk overlap."
adom-footprint
Creates, previews, lints, validates, and delivers KiCad PCB footprints (.kicad_mod) with an interactive FpView HTML5 viewer. Supports delivery to KiCad, Fusion 360, and Altium.
Architecture
adom-footprint (Rust binary)
+-- adom-footprint serve -> starts Node.js HTTP server on :8782
+-- adom-footprint create -> creates footprints from pad JSON
+-- adom-footprint lint -> lint via design-rule checks
+-- adom-footprint health -> version check
Node.js server (footprint-creator/)
+-- POST /fp/create -> create footprint from pad JSON
+-- POST /fp/preview -> refresh FpView viewer
+-- POST /fp/lint -> design-rule lint
+-- POST /fp/validate -> artifact completeness check
+-- POST /fp/deliver -> send to KiCad/Fusion 360/Altium
+-- GET /fp/list -> list available footprints
+-- GET /viewer/:name -> FpView interactive viewer
+-- GET /health -> service health
Quick start
# Start the server
adom-footprint serve &
# Create a footprint from JSON
echo '{"footprintName":"QFN-20","pads":[...],"body":{...}}' | adom-footprint create
# Preview in FpView
adom-footprint preview --name QFN-20
# -> http://localhost:8782/viewer/QFN-20
# Lint a footprint
adom-footprint lint --name QFN-20
adom-footprint lint --path /path/to/custom.kicad_mod
# Send to KiCad
adom-footprint deliver --name QFN-20 --target kicad
Commands
| Command | Description |
|---|---|
serve [-p port] |
Start HTTP server (default :8782) |
create [--file json] |
Create footprint from pad JSON (stdin or file) |
preview --name NAME |
Generate/refresh FpView viewer |
lint --name NAME or --path FILE |
Design-rule lint |
validate --name NAME |
Check artifact completeness |
deliver --name NAME --target kicad/fusion360/altium |
Send to desktop EDA |
health |
Check service health |
install |
Install Claude Code skill + completions |
completions bash/zsh/fish |
Generate shell completions |
FpView viewer
The interactive HTML5 footprint viewer includes:
- Dark Adom theme with zoom/pan
- Pad hover highlighting (teal #00b8b1)
- Rich tooltips: pad number, name, size, shape, layer
- Toggle layers: Grid, Solder blobs, Labels
- Solder blob visualization (300um dots at 0.25mm pitch for InstaPCB jetting)
- Sticky click-to-pin tooltips
- Cursor coordinates (mm)
Lint checks
The linter validates against KiCad and InstaPCB design rules:
- Courtyard present and 0.25mm minimum clearance
- Fabrication outline on F.Fab layer
- Pin 1 marker on silkscreen
- No silk-pad overlap
- Pad numbering sequential
- Pad size minimums for solder-jet compatibility
Dependencies
| Dependency | Required? | Why |
|---|---|---|
| Node.js 18+ | Yes | Runs the HTTP server and FpView generator |
| service-kicad | Optional | SVG export for FpView rendering, footprint library search |
| adom-lbr | Optional | Converts footprint to .lbr for Fusion 360 delivery |
| adom-desktop | Optional | One-click delivery to desktop KiCad/Fusion 360/Altium |
| adom-symbol | Recommended | Symbol + footprint created together for complete component |
Footprint storage
Footprints are stored at:
/home/adom/project/project-content/schematics/footprints/<NAME>/
<NAME>.kicad_mod <- the footprint
<NAME>-metadata.json <- pad count, description, tags, timestamps
<NAME>-fpview.html <- interactive FpView viewer (cached)
<NAME>.svg <- rendered SVG (from service-kicad)
Create JSON format
{
"footprintName": "QFN-20",
"description": "QFN-20 4x4mm 0.5mm pitch",
"tags": "QFN QFN-20",
"pads": [
{"number": "1", "x": -1.75, "y": -1.0, "dx": 0.8, "dy": 0.25, "shape": "roundrect"},
{"number": "2", "x": -1.75, "y": -0.5, "dx": 0.8, "dy": 0.25, "shape": "roundrect"},
...
{"number": "21", "x": 0, "y": 0, "dx": 2.6, "dy": 2.6, "shape": "roundrect"}
],
"body": {"x1": -2.0, "y1": -2.0, "x2": 2.0, "y2": 2.0},
"courtyard": {"x1": -2.25, "y1": -2.25, "x2": 2.25, "y2": 2.25}
}
.kicad_mod format notes
- Coordinate system: Y-positive is DOWN (opposite of schematic symbols)
- Pad types: smd, thru_hole, np_thru_hole
- Pad shapes: rect, circle, oval, roundrect
- Key layers: F.Cu, F.Paste, F.Mask, F.SilkS, F.Fab, F.CrtYd
- Courtyard: 0.25mm clearance minimum around body
- Filename must match internal footprint name
RefDes / Value text placement
Placement is ONE universal geometry, computed once in fp_gen::text_placement
(the single source of truth used both to emit the .kicad_mod fp_text and the
textPlacement metadata). Exporters handle per-tool syntax (Y-flip, layer
numbers, anchor) — do NOT add a per-tool kicad/fusion/altium/orcad switch.
The rule (create applies it automatically; keep it if hand-placing):
- Center horizontally (
x = 0). - RefDes (
REF**) just beyond the top extent; Value just beyond the bottom extent — ~1 mm clearance off the full pads ∪ courtyard ∪ body bbox (not just the body). KiCad Y is down, so "above" = negative Y. - Size ~1 mm (KiCad default), scaled down for tiny parts so the label is never
larger than the part. reference on
F.SilkS, value onF.Fab. - Keep it user-visible and editable (the user can nudge it in the app).
Why it matters: adom-lbr carries your .kicad_mod text placement through
verbatim into the Fusion .lbr (and KiCad/Altium/OrCAD) — it no longer invents
its own. Where you put RefDes/Value here is exactly what the user sees in every
tool. Text only ~3 mm from center (the old default) lands ON the pads of larger
parts (e.g. an LQFP-64's pads reach ±5.9 mm) and shows "smeared across the
footprint" in Fusion. adom-lbr's name-value-overlap lint warns (and its export
reprimands) if the text ever sits back on pad copper.
Two carry-through limits in adom-lbr's .lbr path today (so keep parts that
must read well in Fusion at ~1 mm and horizontal):
- text size is hardcoded to 1.27 mm in the
.lbr— your size only reaches KiCad/Altium/OrCAD. - text rotation is dropped — keep
rotation = 0(horizontal).
(adom-lbr will be updated to honor size + rotation.)
textPlacement metadata
Beyond the .kicad_mod fp_text (the primary contract), adom-footprint also emits
an explicit textPlacement block so exporters validate against your intent
instead of re-deriving from pads. Inject it into a ds2sf
<mpn>-footprint.extracted.json (or a create JSON) with:
adom-footprint placement --file <mpn>-footprint.extracted.json --write
"textPlacement": {
"units": "mm",
"yAxis": "down",
"originRelative": "footprint-center",
"reference": { "x": 0, "y": -6.95, "size": 1.0, "rotation": 0, "anchor": "center", "layer": "F.SilkS" },
"value": { "x": 0, "y": 6.95, "size": 1.0, "rotation": 0, "anchor": "center", "layer": "F.Fab" },
"courtyard": { "top": -5.95, "bottom": 5.95, "left": -5.95, "right": 5.95 }
}
courtyard is the keep-out the text must clear. Invariant (Y-down):
reference.y <= courtyard.top AND value.y >= courtyard.bottom.
---
name: adom-footprint
description: "Use when the user asks to create a KiCad footprint, make a .kicad_mod, design a PCB footprint, build a footprint for a part, preview a footprint in FpView, lint a footprint, send a footprint to KiCad or Fusion 360, or view pad positions and solder blob layout. Also trigger for footprint-related questions like pad size, courtyard rules, or silk overlap."
---
# adom-footprint
Creates, previews, lints, validates, and delivers KiCad PCB footprints (.kicad_mod) with an interactive FpView HTML5 viewer. Supports delivery to KiCad, Fusion 360, and Altium.
## Architecture
```
adom-footprint (Rust binary)
+-- adom-footprint serve -> starts Node.js HTTP server on :8782
+-- adom-footprint create -> creates footprints from pad JSON
+-- adom-footprint lint -> lint via design-rule checks
+-- adom-footprint health -> version check
Node.js server (footprint-creator/)
+-- POST /fp/create -> create footprint from pad JSON
+-- POST /fp/preview -> refresh FpView viewer
+-- POST /fp/lint -> design-rule lint
+-- POST /fp/validate -> artifact completeness check
+-- POST /fp/deliver -> send to KiCad/Fusion 360/Altium
+-- GET /fp/list -> list available footprints
+-- GET /viewer/:name -> FpView interactive viewer
+-- GET /health -> service health
```
## Quick start
```bash
# Start the server
adom-footprint serve &
# Create a footprint from JSON
echo '{"footprintName":"QFN-20","pads":[...],"body":{...}}' | adom-footprint create
# Preview in FpView
adom-footprint preview --name QFN-20
# -> http://localhost:8782/viewer/QFN-20
# Lint a footprint
adom-footprint lint --name QFN-20
adom-footprint lint --path /path/to/custom.kicad_mod
# Send to KiCad
adom-footprint deliver --name QFN-20 --target kicad
```
## Commands
| Command | Description |
|---|---|
| `serve [-p port]` | Start HTTP server (default :8782) |
| `create [--file json]` | Create footprint from pad JSON (stdin or file) |
| `preview --name NAME` | Generate/refresh FpView viewer |
| `lint --name NAME` or `--path FILE` | Design-rule lint |
| `validate --name NAME` | Check artifact completeness |
| `deliver --name NAME --target kicad/fusion360/altium` | Send to desktop EDA |
| `health` | Check service health |
| `install` | Install Claude Code skill + completions |
| `completions bash/zsh/fish` | Generate shell completions |
## FpView viewer
The interactive HTML5 footprint viewer includes:
- Dark Adom theme with zoom/pan
- Pad hover highlighting (teal #00b8b1)
- Rich tooltips: pad number, name, size, shape, layer
- Toggle layers: Grid, Solder blobs, Labels
- Solder blob visualization (300um dots at 0.25mm pitch for InstaPCB jetting)
- Sticky click-to-pin tooltips
- Cursor coordinates (mm)
## Lint checks
The linter validates against KiCad and InstaPCB design rules:
- Courtyard present and 0.25mm minimum clearance
- Fabrication outline on F.Fab layer
- Pin 1 marker on silkscreen
- No silk-pad overlap
- Pad numbering sequential
- Pad size minimums for solder-jet compatibility
## Dependencies
| Dependency | Required? | Why |
|---|---|---|
| Node.js 18+ | Yes | Runs the HTTP server and FpView generator |
| service-kicad | Optional | SVG export for FpView rendering, footprint library search |
| adom-lbr | Optional | Converts footprint to .lbr for Fusion 360 delivery |
| adom-desktop | Optional | One-click delivery to desktop KiCad/Fusion 360/Altium |
| adom-symbol | Recommended | Symbol + footprint created together for complete component |
## Footprint storage
Footprints are stored at:
```
/home/adom/project/project-content/schematics/footprints/<NAME>/
<NAME>.kicad_mod <- the footprint
<NAME>-metadata.json <- pad count, description, tags, timestamps
<NAME>-fpview.html <- interactive FpView viewer (cached)
<NAME>.svg <- rendered SVG (from service-kicad)
```
## Create JSON format
```json
{
"footprintName": "QFN-20",
"description": "QFN-20 4x4mm 0.5mm pitch",
"tags": "QFN QFN-20",
"pads": [
{"number": "1", "x": -1.75, "y": -1.0, "dx": 0.8, "dy": 0.25, "shape": "roundrect"},
{"number": "2", "x": -1.75, "y": -0.5, "dx": 0.8, "dy": 0.25, "shape": "roundrect"},
...
{"number": "21", "x": 0, "y": 0, "dx": 2.6, "dy": 2.6, "shape": "roundrect"}
],
"body": {"x1": -2.0, "y1": -2.0, "x2": 2.0, "y2": 2.0},
"courtyard": {"x1": -2.25, "y1": -2.25, "x2": 2.25, "y2": 2.25}
}
```
## .kicad_mod format notes
- Coordinate system: Y-positive is DOWN (opposite of schematic symbols)
- Pad types: smd, thru_hole, np_thru_hole
- Pad shapes: rect, circle, oval, roundrect
- Key layers: F.Cu, F.Paste, F.Mask, F.SilkS, F.Fab, F.CrtYd
- Courtyard: 0.25mm clearance minimum around body
- Filename must match internal footprint name
## RefDes / Value text placement
Placement is ONE universal geometry, computed once in `fp_gen::text_placement`
(the single source of truth used both to emit the `.kicad_mod` fp_text and the
`textPlacement` metadata). Exporters handle per-tool syntax (Y-flip, layer
numbers, anchor) — do NOT add a per-tool kicad/fusion/altium/orcad switch.
**The rule** (`create` applies it automatically; keep it if hand-placing):
- Center horizontally (`x = 0`).
- RefDes (`REF**`) just **beyond the top extent**; Value just **beyond the bottom
extent** — ~1 mm clearance off the **full** pads ∪ courtyard ∪ body bbox (not
just the body). KiCad Y is down, so "above" = negative Y.
- Size ~1 mm (KiCad default), scaled down for tiny parts so the label is never
larger than the part. reference on `F.SilkS`, value on `F.Fab`.
- Keep it user-visible and editable (the user can nudge it in the app).
**Why it matters:** **adom-lbr carries your `.kicad_mod` text placement through
verbatim** into the Fusion `.lbr` (and KiCad/Altium/OrCAD) — it no longer invents
its own. Where you put RefDes/Value here is exactly what the user sees in every
tool. Text only ~3 mm from center (the old default) lands ON the pads of larger
parts (e.g. an LQFP-64's pads reach ±5.9 mm) and shows "smeared across the
footprint" in Fusion. adom-lbr's `name-value-overlap` lint warns (and its export
reprimands) if the text ever sits back on pad copper.
**Two carry-through limits in adom-lbr's `.lbr` path today** (so keep parts that
must read well in Fusion at ~1 mm and horizontal):
- text **size** is hardcoded to 1.27 mm in the `.lbr` — your size only reaches
KiCad/Altium/OrCAD.
- text **rotation** is dropped — keep `rotation = 0` (horizontal).
(adom-lbr will be updated to honor size + rotation.)
### `textPlacement` metadata
Beyond the `.kicad_mod` fp_text (the primary contract), adom-footprint also emits
an explicit `textPlacement` block so exporters **validate against your intent**
instead of re-deriving from pads. Inject it into a ds2sf
`<mpn>-footprint.extracted.json` (or a create JSON) with:
```bash
adom-footprint placement --file <mpn>-footprint.extracted.json --write
```
```json
"textPlacement": {
"units": "mm",
"yAxis": "down",
"originRelative": "footprint-center",
"reference": { "x": 0, "y": -6.95, "size": 1.0, "rotation": 0, "anchor": "center", "layer": "F.SilkS" },
"value": { "x": 0, "y": 6.95, "size": 1.0, "rotation": 0, "anchor": "center", "layer": "F.Fab" },
"courtyard": { "top": -5.95, "bottom": 5.95, "left": -5.95, "right": 5.95 }
}
```
`courtyard` is the keep-out the text must clear. **Invariant (Y-down):**
`reference.y <= courtyard.top` AND `value.y >= courtyard.bottom`.