# SnapEDA / SnapMagic (chip-fetcher playbook)

Verified end-to-end 2026-05-03 on nRF52840-CKAA-R7 — KiCad + Altium + Fusion in one session. Read this when the manufacturer doesn't host CAD directly (Nordic, niche connectors, passives, smaller-vendor MCUs).

**SnapEDA is a TIER 2 fallback — only use it AFTER confirming the manufacturer doesn't host CAD on their own site.** When falling back, post a `no mfr-direct CAD — falling back to SnapEDA` heartbeat so the user sees on the dashboard that we're leaving manufacturer-direct (per [`dashboard-flow.md`](dashboard-flow.md)). All format-cycling stages (kicad → altium → fusion) get their own heartbeats: `setting preferred format altium`, `clicking download symbol+footprint`, `dismissing heads-up`, `pulling altium IntLib`, etc.

## What it is

**SnapEDA is `snapeda.com` (host) but rebranded to "SnapMagic Search" in the UI.** Free CAD downloads (symbol + footprint + STEP + 3D + Altium/KiCad/Eagle/OrCAD/PADS/TARGET/Allegro) for millions of parts. **Account required for downloads.** Most embedded engineers already have one — ASK first per the credentials playbook.

**Where SnapEDA shines:** parts that aren't in CSE/UL — Nordic (no UL deep-link), niche connectors, passives, smaller-vendor MCUs, anything where the manufacturer doesn't publish CAD directly.

## Login flow (verified working)

```bash
# 1. Navigate to login page
adom-desktop browser_navigate '{"sessionId":"chip-fetcher","url":"https://www.snapeda.com/account/login/"}'
sleep 5

# 2. Fill credentials + form.submit() (NOT button click — the "Log In" looks like an <a> but
#    button-click doesn't fire the real handler; only form.submit() works)
adom-desktop browser_eval '{"sessionId":"chip-fetcher","expr":"(()=>{const u=document.querySelector(\"input[name=username]\"); const p=document.querySelector(\"input[type=password]\"); const proto=Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype,\"value\"); proto.set.call(u,\"<email>\"); proto.set.call(p,\"<password>\"); [\"input\",\"change\",\"blur\"].forEach(t=>{u.dispatchEvent(new Event(t,{bubbles:true})); p.dispatchEvent(new Event(t,{bubbles:true}));}); u.closest(\"form\").submit(); return \"submitted\";})()"}'

# 3. Wait for redirect away from /account/login/ — typically lands on /home/
```

**Critical: SnapEDA's "Log in" button does NOT submit the form via click.** Use `form.submit()` directly. Verified painful pattern when button-click wasted ~30 seconds before figuring this out.

## Search + part-page flow

URL pattern: `https://www.snapeda.com/parts/<MPN>/<Manufacturer>/view-part/`. The Manufacturer slug is URL-encoded (`Nordic%20Semiconductors` for Nordic parts).

To search: `https://www.snapeda.com/search/?q=<MPN>` returns a list of matching variants.

## Download flow — KEY INSIGHT: format is gated by user account preference

The part page has three tabs: **"Symbol and Footprint"**, **"3D Model"**, **"Alternates"**. The "Symbol and Footprint" tab has TWO orange buttons side by side: full bundle (`Download Symbol and Footprint`) and footprint-only (`Download Footprint`).

**3D Model (STEP)** — direct, no format picker:
```bash
adom-desktop browser_eval '{"sessionId":"chip-fetcher","expr":"document.getElementById(\"download_step_model\").click()"}'
# Lands as <MPN>--3DModel-STEP-<id>.STEP. Always raw STEP regardless of preferred-format.
```

**Symbol + Footprint** is gated by a **per-account "Preferred ECAD format"** at `https://www.snapeda.com/account/email/`. Two settings drive the orange-button behavior:

1. **Preferred ECAD format** (radio `preferred_2d_format`): one of `altium_native`, `kicad_modv6`, `kicad_modv4`, `kicad_modv3`, `eagle`, `fusion_360`, `orcad_v17`, `orcad_v16`, `pads`, `diptrace`, `designspark`, `cr_8000`, `circuit_studio`, `ecadstar`, `easypc`, `express_pcb_plus`.
2. **Direct download toggle** (ON = skip the format-picker modal and go straight to the preferred format)

When toggle is OFF (the default), clicking the orange "Download Symbol and Footprint" opens a `Choose Download Format` modal showing ALL formats, with the preferred at the top. When toggle is ON, the modal is skipped — except for KiCad which still asks "V3 / V4 / V6 & later" version variant.

## Switching format programmatically

Clicking the radio auto-saves via AJAX (no submit button needed). Verified by header text updating to "Direct download - Preferred format: Altium":

```bash
# Set Altium as preferred (auto-saves on click)
adom-desktop browser_navigate '{"sessionId":"chip-fetcher","url":"https://www.snapeda.com/account/email/"}'
sleep 4
adom-desktop browser_eval '{"sessionId":"chip-fetcher","expr":"document.querySelector(\"input[name=preferred_2d_format][value=altium_native]\").click()"}'
# Then go back to part page — orange button now serves Altium.
```

**Always restore the preferred format to whatever the user had originally** (typically `kicad_modv6`) at the end of the session — don't leave the account changed.

## The "Heads Up" warning

For parts with multiple symbol sections, a small modal interrupts the download with *"This part contains multiple symbol sections. View the sections to see all pinouts."* Click the orange "Ok, download this part" button to proceed:

```bash
adom-desktop browser_eval '{"sessionId":"chip-fetcher","expr":"(()=>{const b=Array.from(document.querySelectorAll(\"a, button\")).find(e=>e.offsetParent!==null && /ok.*download this part/i.test((e.textContent||\"\").trim())); if(b){b.click(); return \"clicked\";} return \"no heads-up modal\";})()"}'
```

This is benign — just a "did you know there are multiple sections" notification. Always click OK.

## Full proven 3-format sequence

```bash
PART_URL="https://www.snapeda.com/parts/<MPN>/<Manufacturer>/view-part/"

fetch_format() {
  local FORMAT="$1"  # altium_native | kicad_modv6 | fusion_360 | eagle | etc.
  # 1. Set preference (auto-saves)
  adom-desktop browser_navigate '{"sessionId":"chip-fetcher","url":"https://www.snapeda.com/account/email/"}' >/dev/null
  sleep 4
  adom-desktop browser_eval "{\"sessionId\":\"chip-fetcher\",\"expr\":\"document.querySelector('input[name=preferred_2d_format][value=$FORMAT]').click()\"}" >/dev/null
  sleep 1
  # 2. Back to part page
  adom-desktop browser_navigate "{\"sessionId\":\"chip-fetcher\",\"url\":\"$PART_URL\"}" >/dev/null
  sleep 5
  # 3. Click orange Download (use coords from canvas-main-btn rect, typically near (548, 704))
  adom-desktop browser_eval '{"sessionId":"chip-fetcher","expr":"(()=>{const b=Array.from(document.querySelectorAll(\"a.canvas-main-btn, a.modal-trigger\")).find(e=>e.offsetParent!==null && /download symbol and footprint/i.test((e.textContent||\"\").trim())); if(!b)return\"no btn\"; const r=b.getBoundingClientRect(); return JSON.stringify({x:Math.round(r.x+r.width/2),y:Math.round(r.y+r.height/2)});})()"}'
  # ...trusted-click those coords...
  # 4. Modal opens: click the format button by visible text
  # 5. KiCad-only: pick V6 & Later. All formats: dismiss "Heads Up" → click "Ok, download this part"
  # 6. Watch Downloads for new file
}

fetch_format kicad_modv6   # → <MPN>.zip   (contains .kicad_sym + .kicad_mod)
fetch_format altium_native # → <MPN>.IntLib (raw IntLib, NOT zipped)
fetch_format fusion_360    # → <MPN>.lbr   (Eagle .lbr — Fusion eats Eagle natively)
```

## Verified filenames in user Downloads

No MPN-Format suffix, just `<MPN>` + native extension:

| Format radio | Filename in Downloads | What's inside |
|--------------|----------------------|---------------|
| `kicad_modv6` (after V6 & Later picker) | `<MPN>.zip` | `<MPN>.kicad_sym` + `<MPN>.kicad_mod` |
| `kicad_modv4`, `kicad_modv3` | `<MPN>.zip` | older-format KiCad files |
| `altium_native` | `<MPN>.IntLib` | binary Altium Integrated Library, not zipped |
| `fusion_360` | `<MPN>.lbr` | Eagle .lbr (Fusion 360 imports Eagle) |
| `eagle` | `<MPN>.lbr` | identical content to Fusion in many cases |
| `orcad_v17` / `orcad_v16` | `<MPN>.zip` | OrCAD/Allegro library |

**Repeat-download collisions:** if the user already has `<MPN>.lbr` from a prior Fusion fetch, a fresh Eagle fetch lands as `<MPN> (1).lbr`. Watch Downloads diff, not absolute filename.

## Importing into chip-fetcher library

```bash
# KiCad zip → auto-extracts to .kicad_sym + .kicad_mod
chip-fetcher pull "C:\\Users\\<user>\\Downloads\\<MPN>.zip" --mpn <MPN>

# Altium IntLib + Fusion .lbr — pull stages them in incoming/ but doesn't auto-import.
# Manually copy into library/ with explicit names so the viewer can find them:
chip-fetcher pull "C:\\Users\\<user>\\Downloads\\<MPN>.IntLib" --mpn <MPN>
cp incoming/<MPN>.IntLib library/<MPN>/<MPN>.IntLib

chip-fetcher pull "C:\\Users\\<user>\\Downloads\\<MPN>.lbr" --mpn <MPN>
cp "incoming/<MPN>.lbr" library/<MPN>/<MPN>-fusion.lbr  # disambiguate from Eagle if both fetched
```

**(TODO for chip-fetcher importer: handle `.IntLib` and `.lbr` natively — current importer only knows about KiCad zips and STEP files, leaves Altium/Fusion in incoming/.)**

## InstaBuild AI-generated parts

Some parts on SnapMagic are AI-generated rather than vetted by the SnapMagic editorial team. Banner reads *"You've created this part using our AI Model Generator. This part is only visible to you."* The download flow is identical, but the symbol/footprint quality should be inspected before committing to the design. The InstaBuild edit URL is `https://instabuild.snapmagic.com/?unipart_id=<id>&token=<token>` (linked from the banner).

## Account profile cache

If `user_profile.md` (personal memory) has a `Site logins` section listing SnapEDA's email, pre-fill it; otherwise ASK. Never store passwords — pre-fill email + ask user to type password once. Pup persists session via cookies after login (`chip-fetcher` profile name).

**Login URL:** `https://www.snapeda.com/account/login/`

Direct user reaction when this flow landed the STEP for nRF52840-CKAA: *"all adom users will be thrilled!"*
