# adom-symbol

Standalone Rust CLI + live app for **KiCad schematic symbols**. Generates
`.kicad_sym` files natively in Rust, renders them as gorgeous dark-themed SVGs
through the shared **service-kicad** container, and serves an AI-drivable live
viewer with a full layout studio. No Node, no gallia, no local KiCad install.

![The adom-symbol live viewer — an ADC symbol with its 3D-chip outline lasered into the body, beside the docked Layout studio](docs/screenshot-viewer.png)

## What it does

- **Generate** `.kicad_sym` natively in Rust — rectangle-body ICs with grouped,
  side-sorted pins (Category A) and discrete passives derived from a KiCad
  baseline symbol (Category B).
- **Render** the symbol to a cropped, dark-themed SVG via service-kicad
  (`POST /kicad/sch/export/svg`) — the same render path the chip-fetcher
  dashboard uses, so the thumbnail and the app match exactly. The default render
  **inlines** the part's 3D-chip **vector outline** (with the part number lasered
  on) into the body centre as real `<polyline>`s — crisp in every renderer
  (browser, librsvg thumbnailer, anything), not a rasterisable `<image>`.
- **Browse + lay out** a whole chip-fetcher library in the **live viewer**: a
  left chip-library rail (with project filters), a docked **Layout studio** for
  the source / pin arrangement / designator placement / 3D-chip style, drag-to-
  place labels, one-step **Undo**, and **Send to** KiCad / Fusion 360 / Altium /
  OrCAD.
- **Emit an outline contract** — alongside `<mpn>-symbol.svg`, `render` writes
  `<mpn>-symbol-outline.mm.svg` + `<mpn>-symbol-outline.json` so **adom-lbr** can
  draw the exact same chip outline onto the EAGLE/Fusion 360 symbol with **zero
  guessing**. See [3D-chip outline contract](#3d-chip-outline-contract-for-adom-lbr).
- **Serve** a live, AI-drivable app: the frontend stays connected to the Rust
  server (`GET /state` poller + `POST /eval` channel), so the AI can push a new
  symbol, hot-patch the UI, or read the console in real time.

## The live viewer

`adom-symbol serve` opens an interactive, AI-drivable viewer over the whole
chip-fetcher library. The **Layout studio is always open** on the right — it's
where you shape the symbol — and a collapsible chip-library rail sits on the
left.

**Browse the library.** Every chip in the library root, with chip-fetcher's
project filters; ↑/↓ to step through, and each chip auto-saves the look you give
it (per-symbol; your last-used choices fill in untouched chips).

![The chip-library rail (74 chips) on the left, a symbol with its shaded 3D chip in the body, and the docked Layout studio on the right](screenshots/app-chip-rail.png)

**Shape it in the Layout studio.** Pick the **source** (auto-grouped from ds2sf,
or any manufacturer / Altium / Fusion / KiCad library variant), the pin
**layout** (left-right or all-sides) and grouping, the **3D-chip** overlay style
(off / shaded iso / thin / bold / blue / teal / dark) and size, where the chip
name shows (lasered on the chip, in the symbol, both, or hidden), and then
**Send to** a desktop EDA tool.

![The shaded photoreal "iso" 3D chip composited into the symbol body](screenshots/app-3d-iso.png)

**Place the labels — auto or by hand.** The Reference (`U?`/`Y?`) and chip-name
designators don't have to overlap the body or pins. **Auto-place** centres both
clear of everything; flip on **Manual** and each label gets a drag-outline you
grab and drop exactly where you want — it re-renders live and auto-saves to that
chip. Any change (layout, 3D look, size, auto-place, a label drag) steps back
with **↶ Undo** or Ctrl/⌘+Z.

![Manual label mode on a crystal — the Reference (Y?) and chip name (Crystal_GND24) each wrapped in a drag-outline you position by hand](screenshots/app-label-placement.png)

## Install

```
adompkg install adom-symbol
```

## Quick start

```bash
# Create a symbol from structured pin JSON (stdin or --file)
adom-symbol create --file rp2040.json --out RP2040

# Preview an existing .kicad_sym as a themed viewer
adom-symbol preview --file RP2040/RP2040.kicad_sym

# Render a .kicad_sym to a themed thumbnail SVG (+ outline contract for adom-lbr)
adom-symbol render --file RP2040/RP2040.kicad_sym --out RP2040-symbol.svg

# Run the live app (AI-drivable: /state, /load, /eval, /console)
adom-symbol serve --port 8781 --file RP2040/RP2040.kicad_sym
```

Open the served app through the Adom proxy URL
(`https://<slug>.adom.cloud/proxy/8781/`), never `localhost:8781` — the webview
renders outside the container.

## CLI reference

| Command | Description |
|---|---|
| `create --file <json> [--out <dir>]` | Generate `.kicad_sym` + SVG + viewer HTML from pin JSON |
| `preview --file <kicad_sym> [--out <dir>]` | Render an existing symbol to a themed viewer |
| `render --file <kicad_sym> --out <svg> [--iso <png>] [--chip-size large\|medium\|small]` | Render to a themed thumbnail SVG; auto-composites the 3D-chip outline + emits the outline contract |
| `embed --file <kicad_sym> [--out <html>]` | Export a self-contained interactive HTML viewer (pan/zoom + pin info) |
| `serve [--port 8781] [--file <kicad_sym>]` | Run the live AI-drivable viewer + layout studio |

## 3D-chip outline contract (for adom-lbr)

The default `render` composites the part's **3D-chip vector outline** (white
`heavy` style, with the part number lasered on the top face) into the symbol
body — sized to **0.62×** the body's smaller side, fitted from the source
`320×320` outline canvas and centred on the body rectangle.

![A symbol rendered with its 3D chip outline inlined into the body as crisp vector, the part number lasered on the top face](screenshots/app-outline-in-body.png)

Because that exact placement was previously re-guessed downstream (adom-lbr fit
the outline to ~0.38× of a different reference frame, so it drifted ~30% small),
`render` now **exposes the placement** so it can be transcribed 1:1. Next to
`<mpn>-symbol.svg` it writes:

| File | What it is |
|---|---|
| `<mpn>-symbol-outline.mm.svg` | The outline strokes **only**, as decimated (lite) `<polyline>`s, in the **same units / origin / viewBox** as `<mpn>-symbol.svg` (mm, Y-down). A drop-in overlay; each stroke keeps the source style's real colour/width/dash (and the neon glow `<defs>`, blur scaled to mm). |
| `<mpn>-symbol-outline.json` | A self-describing sidecar: the canonical `default_variant`, the source viewBox, segment count, and the exact transform in **both** frames — EAGLE/KiCad **Y-up** (what adom-lbr maps to) and the symbol-svg **Y-down** overlay frame. |

`adom-lbr generate --symbol-art <mpn>-symbol-outline.mm.svg` detects the contract
(via the sibling `.json`), derives the svg→EAGLE offset/flip from the two frame
centres, and emits the outline as layer-94 `<wire>`s — no re-fitting, no
re-decimation, so the art lands exactly where adom-symbol drew it.

> The **canonical embedded variant is `heavy`** (white `#e6edf3`, single visible
> layer) — clean as schematic wires. The multi-layer styles (`blueprint`/`xray`
> add hidden dashed edges, `neon` is a 2-layer glow) are deliberately avoided for
> embedding.

### Outline placement (the math `render` exposes)

For a source outline point `(px, py)` in the `320×320` canvas:

```
scale      = min(body_w, body_h) · 0.62 / 320          # mm per source unit
eagle_x    = center_x + (px − 160) · scale             # KiCad/EAGLE Y-up
eagle_y    = center_y − (py − 160) · scale             # (note the Y flip)
```

`center_x/center_y` (and the Y-down `symbol.svg`-frame equivalents) are written
verbatim into the sidecar, so a consumer never has to reconstruct them.

### The contract, proven

The emitted `.mm.svg` (recoloured magenta) placed over the live `-symbol.svg` —
dead-centre in the body, framed by the real pins, tracing the chip body, side
pads and lasered name. Zero drift.

![Magenta outline contract centered in the symbol body, framed by the pins](screenshots/outline-alignment.png)

Real EAGLE `.lbr` output: **left** transcribed 1:1 from the contract (exact 0.62
fit, centred); **right** the legacy guess — too small *and* off-centre, because
it fit the source's ink bbox instead of the canvas.

![Side-by-side EAGLE symbols: the contract fit centred vs the smaller, off-centre legacy guess](screenshots/outline-lbr-contract-vs-legacy.png)

![The outline-contract JSON with placement in both coordinate frames](screenshots/outline-contract-json.png)

## Architecture

Pure Rust. Symbol generation (`src/sym_gen.rs`, `src/discrete_gen.rs`) is a
byte-for-byte port of the original generator, **verified against golden files**
in `tests/`. The only network dependency is **service-kicad** for SVG rendering
— a lightweight proxy to the shared KiCad-10 container, so nothing installs
KiCad locally. The live app server (`src/server.rs`) follows the Adom
app-creator contract: `GET /state`, `POST /load`, `POST /eval` +
`GET /eval/pending` + `POST /eval/:id/result`, `GET/POST /console`,
`POST /shutdown`, `GET /favicon.svg`, and best-effort HD port registration.
Per-symbol layout (including dragged label positions) persists to each chip's
`info.json` and bakes into its `.kicad_sym` on save.

## Build from source

The full source ships on the wiki app page — anyone in the community can build
it locally:

```bash
# Fetch the source bundle from the wiki
adompkg source adom-symbol            # downloads + unpacks the repo

cargo build --release                 # standalone — only needs Rust + cargo
cargo test --release                  # runs the golden-file parity tests
cp target/release/adom-symbol ~/.local/bin/
```

The only runtime dependency is network access to a service-kicad endpoint
(`KICAD_SERVICE_API`, defaults to the shared container).

## Wiki

https://wiki.adom.inc/adom/adom-symbol

## Contributing & forking — open source under the Adom org

**adom-symbol** is **open source** under the **adom** org on the [Adom Wiki](https://wiki.adom.inc/adom/adom-symbol). The full source lives in this page's repo (public) — open the **Files** tab, or `adompkg source adom-symbol`. Third-party developers are welcome to modify it and contribute back.

**Modify it**
- Get the source from the Files tab (or `adompkg source adom-symbol`), make your changes, run `cargo test --release` (keep the golden tests green), and rebuild.

**Contribute back to Adom — two paths**
1. **Pull request (preferred).** The wiki runs a PR-per-page flow: propose your change on this page and the maintainer reviews + merges it — no fork needed.
2. **Fork + breadcrumb.** Prefer your own fork or add-on? Publish it as your own wiki page, then drop a **breadcrumb on _this_ page** pointing at your fork so it's discoverable:
   - Read existing trails: `GET https://wiki.adom.inc/api/v1/pages/adom-symbol/breadcrumbs`
   - Attach a breadcrumb from your fork's page targeting this anchor (a short label + your slug).

   The breadcrumb leaves a **linked path back here**, so **Adom's AI can auto-discover your fork** and surface it to users — the trail is followable both ways. Your fork stays yours; the original stays discoverable.

## License

**MIT** — © 2026 Adom Industries Inc. Open source; see [LICENSE](LICENSE). Modify, fork, and redistribute freely.
