← Commit history
README.md+20−14
@@ -1,11 +1,17 @@ # JLCPCB Parts Library -**Know it's in the JLCPCB library — Basic or Extended — before you commit a board to fab.**+**Know it's in the JLCPCB library, Basic or Extended, before you commit a board to fab.**  `adom-jlcpcb` is the single-vendor JLCPCB / LCSC tool for the Adom ecosystem: one Rust binary with-three faces — a JSON **CLI**, a first-class **Hydrogen webview app**, and the shared **backend+three faces, a JSON **CLI**, a first-class **Hydrogen webview app**, and the shared **backend service** that powers `service-jlcpcb` and feeds [`adom-parts-search`](/adom/adom-parts-search). +## Identity and access++**You never need a JLCPCB API key.** Any vendor credential is company-owned and lives only inside Adom's service container. The CLI reaches Adom's hosted JLCPCB backend automatically, with nothing to configure, and never calls the vendor directly.++What a search needs is your **Adom identity**, so it is attributed to a real Adom user: in an Adom container it is read automatically from `/var/run/adom/api-key`; elsewhere set `ADOM_API_KEY` to your Adom session token. An error reading *"this needs your ADOM identity, not a vendor API key"* means exactly that.+ ## Install  ```bash@@ -27,7 +33,7 @@ adom-jlcpcb part "C7950"  ## Screenshots -### Basic vs Extended — the question that costs money+### Basic vs Extended, the question that costs money On a JLCPCB assembly run, **Basic** parts are pre-loaded on the line (no fee); **Extended** parts add a per-part feeder charge. Every card shows the tier, LCSC code, stock and price, so you design around what's actually cheap to place.@@ -35,13 +41,13 @@ around what's actually cheap to place. ![adom-jlcpcb results for an 0402 10k resistor and an LM358 op-amp, flagged as Basic parts with LCSC codes and assembly pricing](/blob/app/adom-jlcpcb/screenshots/results-passives.png)  ### Catch the Extended part before fab does-Search your MCU or regulator and see at a glance whether your first pick is Basic — and what the+Search your MCU or regulator and see at a glance whether your first pick is Basic, and what the Basic alternative is. Here a popular STM32 is Basic while a drop-in GD32 is Extended.  ![adom-jlcpcb results comparing an STM32F103C8T6 Basic part with a GD32 Extended alternative and a Basic MLCC, with LCSC stock and pricing](/blob/app/adom-jlcpcb/screenshots/results-mcu.png)  ### Scriptable from the first keystroke-`search`/`part`/`health` return JSON — pipe to `jq`, a BOM, or a board-cost estimator.+`search`/`part`/`health` return JSON, pipe to `jq`, a BOM, or a board-cost estimator.  ![Terminal showing adom-jlcpcb search piped to jq for the first component including its Basic library tier, then a health check](/blob/app/adom-jlcpcb/screenshots/cli.png) @@ -53,10 +59,10 @@ Basic alternative is. Here a popular STM32 is Basic while a drop-in GD32 is Exte  ## Features -- **Three faces** — CLI verbs, a Hydrogen webview app, and the shared backend service.-- **Library tier on every card** — Basic vs Extended, so you avoid surprise feeder-setup fees.-- **LCSC codes + assembly pricing** — what JLCPCB will actually charge to place the part.-- **Assembly-first** — in [`adom-parts-search`](/adom/adom-parts-search) it's the library column, not a buy-now vendor.+- **Three faces**: CLI verbs, a Hydrogen webview app, and the shared backend service.+- **Library tier on every card**: Basic vs Extended, so you avoid surprise feeder-setup fees.+- **LCSC codes + assembly pricing**: what JLCPCB will actually charge to place the part.+- **Assembly-first**: in [`adom-parts-search`](/adom/adom-parts-search) it's the library column, not a buy-now vendor.  ## Talk to the AI @@ -69,7 +75,7 @@ Basic alternative is. Here a popular STM32 is Basic while a drop-in GD32 is Exte  | Skill | Purpose | |---|---|-| `adom-jlcpcb` | When/how Claude drives the search — Basic/Extended, LCSC codes, reading the cards |+| `adom-jlcpcb` | When/how Claude drives the search, Basic/Extended, LCSC codes, reading the cards | | `adom-jlcpcb-build` | Release workflow (build, publish to the wiki) |  ## CLI reference@@ -82,15 +88,15 @@ Basic alternative is. Here a popular STM32 is Basic while a drop-in GD32 is Exte | `adom-jlcpcb health` | Check the backend + LCSC reachability | | `adom-jlcpcb serve` | Run the shared backend proxy (port 8779) | -## Open source — make it yours, then give it back+## Open source, make it yours, then give it back  This app is **open source under the MIT license**. Fork it, improve it, then send it back: `adom-wiki pkg publish` your own version, or open a pull request against this page so the change lands for everyone. -> **One caveat — the search backend is an Adom service.** Lookups run against Adom's hosted JLCPCB /+> **One caveat, the search backend is an Adom service.** Lookups run against Adom's hosted JLCPCB / > LCSC backend (`service-jlcpcb`), which uses Adom's API credentials and counts against Adom's quota-> — an Adom service, **subject to change**. Everything client-side is yours to fork and republish.+>, an Adom service, **subject to change**. Everything client-side is yours to fork and republish.  ## License -MIT © Adom — do what you want with the code, just pass it on.+MIT © Adom, do what you want with the code, just pass it on.
SKILL.md+34−18
@@ -7,9 +7,25 @@ description: Search JLCPCB Electronics for components, pricing, stock, and part  Search JLCPCB's catalog of millions of electronic components from thousands of manufacturers. Real-time pricing, stock, lead times, and product links. +## Identity and access (read this first)++**You never need a JLCPCB API key, and you must never ask a user for one.** JLCPCB search runs against Adom's own parts snapshot, so there is no vendor credential at all. The CLI reaches Adom's hosted JLCPCB backend automatically; there is nothing to configure.++What every search DOES need is an **Adom identity**, because Adom attributes each search to a real Adom user so shared vendor quota can be accounted for. It is automatic:++- In an Adom container the CLI reads `/var/run/adom/api-key` (your Adom session token) by itself. Nothing to set up.+- Anywhere else, set `ADOM_API_KEY` to the user's Adom session token.+- The backend validates that token against Adom's identity service, so the identity is proven, not self-reported.++Backend resolution, in order: `--api` / `$JLCPCB_API` if set, then a local `adom-jlcpcb serve` on `127.0.0.1`, then **Adom's hosted backend at `https://jlcpcb-wela51osctvp.adom.cloud`**. It never falls back to calling JLCPCB directly.++If a search fails with **"this needs your ADOM identity, not a vendor API key"**, the machine presented no valid Adom token. The fix is signing in to Adom or setting `ADOM_API_KEY`. It is never a vendor key. If it fails with **"could not verify your identity right now"**, that is an Adom-side outage, not the user's credential: retry shortly.++`GET /health` and `GET /usage` on the backend stay open without a credential so monitoring keeps working. `GET /usage?day=YYYY-MM-DD` returns that day's searches by user (`searches_by_owner`), separate from monitoring traffic.+ ## What you have -A single CLI — `adom-jlcpcb` — with three faces:+A single CLI, `adom-jlcpcb`: with three faces:  1. **One-shot search from the shell**, for when the AI just needs the data:    ```bash@@ -43,7 +59,7 @@ Search by keyword, MPN, or JLCPCB PN. |---|---|---| | `--limit N` | 10 | Max results (1–50) | | `--in-stock-only` | false | Only parts currently in stock |-| `--api URL` / `$JLCPCB_API` | auto | Backend URL. If unset, the CLI tries `http://127.0.0.1:8774`, and if that's also down it falls back to calling JLCPCB directly (requires `JLCPCB_API_KEY_UNUSED_placeholder`) |+| `--api URL` / `$JLCPCB_API` | auto | Backend URL. If unset, the CLI tries a local backend on `http://127.0.0.1:8774`, then Adom's hosted backend. It never calls the vendor directly and never needs a vendor key |  Examples: ```bash@@ -112,7 +128,7 @@ Run the backend HTTP proxy. This is what the `service-jlcpcb` container runs. Requires `JLCPCB_API_KEY_UNUSED_placeholder`. Endpoints:  ```-GET  /health                                  — health + live API ping+GET  /health, health + live API ping GET  /search?keyword=...&limit=10&inStockOnly=false GET  /part?partNumber=... POST /              {"action":"search"|"part"|"health", ...}@@ -124,7 +140,7 @@ GET  /              (text/html landing page) Check reachability.  ```bash-adom-jlcpcb health                 # checks backend (or falls back to JLCPCB direct)+adom-jlcpcb health                 # checks backend (local, then Adom's hosted backend) adom-jlcpcb health --api http://127.0.0.1:8774 ``` @@ -132,21 +148,21 @@ adom-jlcpcb health --api http://127.0.0.1:8774  Each component in `.components[]` has: -- `mouser_pn`    — JLCPCB part number, use this for BOM-- `mpn`          — manufacturer part number, use this for schematic/footprint-- `manufacturer` — manufacturer name+- `mouser_pn`: JLCPCB part number, use this for BOM+- `mpn`: manufacturer part number, use this for schematic/footprint+- `manufacturer`: manufacturer name - `description`, `category`-- `stock`        — integer count in JLCPCB's warehouse (live, 10-min cache on backend)-- `stock_text`   — raw JLCPCB text ("In Stock", "Non-Stocked", etc.)-- `popularity`   — `low` / `medium` / `high` heuristic from stock-- `lead_time`    — factory lead time if ordering more-- `unit_price`   — price at qty 1-- `price_tiers`  — array of `{qty, price}` for quantity price breaks-- `min_order`, `mult` — minimum order + order multiple-- `rohs`         — compliance flag-- `lifecycle`    — New Product / Active / NRND / Obsolete+- `stock`: integer count in JLCPCB's warehouse (live, 10-min cache on backend)+- `stock_text`: raw JLCPCB text ("In Stock", "Non-Stocked", etc.)+- `popularity`: `low` / `medium` / `high` heuristic from stock+- `lead_time`: factory lead time if ordering more+- `unit_price`: price at qty 1+- `price_tiers`: array of `{qty, price}` for quantity price breaks+- `min_order`, `mult`: minimum order + order multiple+- `rohs`: compliance flag+- `lifecycle`: New Product / Active / NRND / Obsolete - `datasheet_url`, `product_url`, `image_url`-- `attributes`   — array of `{name, value}` from the product-attribute table+- `attributes`: array of `{name, value}` from the product-attribute table  ## Typical workflows @@ -188,7 +204,7 @@ adom-jlcpcb search "LM317" adom-jlcpcb app        # UI reads $JLCPCB_API automatically ``` -Gallia users don't need to set `JLCPCB_API` explicitly — `adom-jlcpcb` is a Tier A app (see `adom-app-model`), so it's installed by every `adom-wiki pkg install` run from the wiki binary. The CLI autodetects a local `adom-jlcpcb serve` on 127.0.0.1:8774 and falls back to calling JLCPCB directly if `JLCPCB_API_KEY_UNUSED_placeholder` is set locally.+Nobody needs to set `JLCPCB_API`. Install with `adom-wiki pkg install adom/adom-jlcpcb` (it also arrives with `adom/core`), and the CLI finds a backend by itself: a local `serve` on 127.0.0.1 if one is running, otherwise Adom's hosted backend. It never calls the vendor directly.  ### Local-only (quick testing) 
bin/adom-jlcpcb
⋯ 1 unchanged line ⋯
package.json+2−4
@@ -1,6 +1,6 @@ {   "slug": "adom-jlcpcb",-  "version": "1.0.6",+  "version": "1.0.7",   "type": "app",   "description": "Check the JLCPCB / LCSC parts library before you fab \u2014 Basic vs Extended tier, LCSC stock and assembly pricing, so you avoid surprise feeder-setup fees. CLI, a Hydrogen app, and a shared backend.",   "dependencies": {},@@ -27,11 +27,9 @@     "install.sh",     "uninstall.sh",     "package.json",-    "page.json",     "README.md",     "SKILL.md",-    "BUILD-SKILL.md",-    "screenshots/**"+    "BUILD-SKILL.md"   ],   "hero": {     "path": "screenshots/hero.png"
page.json+2−4
@@ -4,7 +4,7 @@   "slug": "adom-jlcpcb",   "title": "JLCPCB Parts Library",   "brief": "Check the JLCPCB / LCSC parts library before you fab — Basic vs Extended tier, LCSC stock and assembly pricing, so you avoid surprise feeder-setup fees. CLI, a Hydrogen app, and a shared backend.",-  "version": "1.0.6",+  "version": "1.0.7",   "install": {     "binary_name": "adom-jlcpcb",     "install_dir": "",@@ -77,11 +77,9 @@     "install.sh",     "uninstall.sh",     "package.json",-    "page.json",     "README.md",     "SKILL.md",-    "BUILD-SKILL.md",-    "screenshots/**"+    "BUILD-SKILL.md"   ],   "org": "adom" }\ No newline at end of file
skills/adom-jlcpcb-build/SKILL.md+7−7
@@ -10,7 +10,7 @@ A release syncs five places to the same version X.Y.Z:  ## Steps -1. **Bump** — decide X.Y.Z (semver). Then:+1. **Bump**: decide X.Y.Z (semver). Then:    ```bash    echo "X.Y.Z" > VERSION    sed -i 's/^version = .*/version = "X.Y.Z"/' Cargo.toml@@ -39,7 +39,7 @@ A release syncs five places to the same version X.Y.Z:    ```    Runs: git commit + tag `vX.Y.Z`, `git push origin main --tags`, `gh release create`, `adom-wiki asset upload` (replaces the prior `docker_binary`), `adom-wiki page update`, and a final curl of the wiki binary to check `--version` returns X.Y.Z. -6. **Service container picks it up automatically** — `service/watchdog.sh` runs every 2 min, `git fetch`es origin/main, and rebuilds + restarts when HEAD moves. Verify within ~5 min:+6. **Service container picks it up automatically**: `service/watchdog.sh` runs every 2 min, `git fetch`es origin/main, and rebuilds + restarts when HEAD moves. Verify within ~5 min:    ```bash    curl -s https://jlcpcb-<slug>.adom.cloud/health | jq '.version'   # → "X.Y.Z"    ```@@ -58,18 +58,18 @@ A release syncs five places to the same version X.Y.Z: - [ ] User has seen a working screenshot of the webview - [ ] No console errors via `GET /console` - [ ] `adom-wiki pkg install` Tier A block still works (pulls + installs the new version)-- [ ] **Brand audit — in-app icons are monochrome white.** Run:+- [ ] **Brand audit, in-app icons are monochrome white.** Run:       ```       grep -nE 'fill="#00b8b0"|stroke="#00b8b0"|color: var\(--accent\)' src/app/*.html src/app/*.svg 2>/dev/null       ```       Expected result: empty, OR only the text-color rules (`.jlcpcb-pn`,       `<a>`, focus-rings) on non-SVG elements. Any match on an `<svg>` or-      a `.logo` / `.icon` class CSS rule is a bug — the brand skill+      a `.logo` / `.icon` class CSS rule is a bug, the brand skill       requires monochrome white for in-app icons. See       `app-creator` §1b and §Checklist.  ## Notes -- **Never skip the ralph loop** — a green `cargo build` is not proof the UI works. Fonts, search, card rendering must be seen working.-- **Wiki upload is idempotent** — `adom-wiki asset upload --asset-type docker_binary` replaces the prior binary for this app automatically.-- **Version discipline is load-bearing** — `refresh-wiki-catalog.mjs` uses semver comparison to surface stale installs; inconsistent versions silently break that.+- **Never skip the ralph loop**: a green `cargo build` is not proof the UI works. Fonts, search, card rendering must be seen working.+- **Wiki upload is idempotent**: `adom-wiki asset upload --asset-type docker_binary` replaces the prior binary for this app automatically.+- **Version discipline is load-bearing**: `refresh-wiki-catalog.mjs` uses semver comparison to surface stale installs; inconsistent versions silently break that.
skills/adom-jlcpcb/SKILL.md+34−18
@@ -7,9 +7,25 @@ description: Search JLCPCB Electronics for components, pricing, stock, and part  Search JLCPCB's catalog of millions of electronic components from thousands of manufacturers. Real-time pricing, stock, lead times, and product links. +## Identity and access (read this first)++**You never need a JLCPCB API key, and you must never ask a user for one.** JLCPCB search runs against Adom's own parts snapshot, so there is no vendor credential at all. The CLI reaches Adom's hosted JLCPCB backend automatically; there is nothing to configure.++What every search DOES need is an **Adom identity**, because Adom attributes each search to a real Adom user so shared vendor quota can be accounted for. It is automatic:++- In an Adom container the CLI reads `/var/run/adom/api-key` (your Adom session token) by itself. Nothing to set up.+- Anywhere else, set `ADOM_API_KEY` to the user's Adom session token.+- The backend validates that token against Adom's identity service, so the identity is proven, not self-reported.++Backend resolution, in order: `--api` / `$JLCPCB_API` if set, then a local `adom-jlcpcb serve` on `127.0.0.1`, then **Adom's hosted backend at `https://jlcpcb-wela51osctvp.adom.cloud`**. It never falls back to calling JLCPCB directly.++If a search fails with **"this needs your ADOM identity, not a vendor API key"**, the machine presented no valid Adom token. The fix is signing in to Adom or setting `ADOM_API_KEY`. It is never a vendor key. If it fails with **"could not verify your identity right now"**, that is an Adom-side outage, not the user's credential: retry shortly.++`GET /health` and `GET /usage` on the backend stay open without a credential so monitoring keeps working. `GET /usage?day=YYYY-MM-DD` returns that day's searches by user (`searches_by_owner`), separate from monitoring traffic.+ ## What you have -A single CLI — `adom-jlcpcb` — with three faces:+A single CLI, `adom-jlcpcb`: with three faces:  1. **One-shot search from the shell**, for when the AI just needs the data:    ```bash@@ -43,7 +59,7 @@ Search by keyword, MPN, or JLCPCB PN. |---|---|---| | `--limit N` | 10 | Max results (1–50) | | `--in-stock-only` | false | Only parts currently in stock |-| `--api URL` / `$JLCPCB_API` | auto | Backend URL. If unset, the CLI tries `http://127.0.0.1:8774`, and if that's also down it falls back to calling JLCPCB directly (requires `JLCPCB_API_KEY_UNUSED_placeholder`) |+| `--api URL` / `$JLCPCB_API` | auto | Backend URL. If unset, the CLI tries a local backend on `http://127.0.0.1:8774`, then Adom's hosted backend. It never calls the vendor directly and never needs a vendor key |  Examples: ```bash@@ -112,7 +128,7 @@ Run the backend HTTP proxy. This is what the `service-jlcpcb` container runs. Requires `JLCPCB_API_KEY_UNUSED_placeholder`. Endpoints:  ```-GET  /health                                  — health + live API ping+GET  /health, health + live API ping GET  /search?keyword=...&limit=10&inStockOnly=false GET  /part?partNumber=... POST /              {"action":"search"|"part"|"health", ...}@@ -124,7 +140,7 @@ GET  /              (text/html landing page) Check reachability.  ```bash-adom-jlcpcb health                 # checks backend (or falls back to JLCPCB direct)+adom-jlcpcb health                 # checks backend (local, then Adom's hosted backend) adom-jlcpcb health --api http://127.0.0.1:8774 ``` @@ -132,21 +148,21 @@ adom-jlcpcb health --api http://127.0.0.1:8774  Each component in `.components[]` has: -- `mouser_pn`    — JLCPCB part number, use this for BOM-- `mpn`          — manufacturer part number, use this for schematic/footprint-- `manufacturer` — manufacturer name+- `mouser_pn`: JLCPCB part number, use this for BOM+- `mpn`: manufacturer part number, use this for schematic/footprint+- `manufacturer`: manufacturer name - `description`, `category`-- `stock`        — integer count in JLCPCB's warehouse (live, 10-min cache on backend)-- `stock_text`   — raw JLCPCB text ("In Stock", "Non-Stocked", etc.)-- `popularity`   — `low` / `medium` / `high` heuristic from stock-- `lead_time`    — factory lead time if ordering more-- `unit_price`   — price at qty 1-- `price_tiers`  — array of `{qty, price}` for quantity price breaks-- `min_order`, `mult` — minimum order + order multiple-- `rohs`         — compliance flag-- `lifecycle`    — New Product / Active / NRND / Obsolete+- `stock`: integer count in JLCPCB's warehouse (live, 10-min cache on backend)+- `stock_text`: raw JLCPCB text ("In Stock", "Non-Stocked", etc.)+- `popularity`: `low` / `medium` / `high` heuristic from stock+- `lead_time`: factory lead time if ordering more+- `unit_price`: price at qty 1+- `price_tiers`: array of `{qty, price}` for quantity price breaks+- `min_order`, `mult`: minimum order + order multiple+- `rohs`: compliance flag+- `lifecycle`: New Product / Active / NRND / Obsolete - `datasheet_url`, `product_url`, `image_url`-- `attributes`   — array of `{name, value}` from the product-attribute table+- `attributes`: array of `{name, value}` from the product-attribute table  ## Typical workflows @@ -188,7 +204,7 @@ adom-jlcpcb search "LM317" adom-jlcpcb app        # UI reads $JLCPCB_API automatically ``` -Gallia users don't need to set `JLCPCB_API` explicitly — `adom-jlcpcb` is a Tier A app (see `adom-app-model`), so it's installed by every `adom-wiki pkg install` run from the wiki binary. The CLI autodetects a local `adom-jlcpcb serve` on 127.0.0.1:8774 and falls back to calling JLCPCB directly if `JLCPCB_API_KEY_UNUSED_placeholder` is set locally.+Nobody needs to set `JLCPCB_API`. Install with `adom-wiki pkg install adom/adom-jlcpcb` (it also arrives with `adom/core`), and the CLI finds a backend by itself: a local `serve` on 127.0.0.1 if one is running, otherwise Adom's hosted backend. It never calls the vendor directly.  ### Local-only (quick testing)