Download

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 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:

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.