---
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`.
