{
  "schema_version": 1,
  "type": "skill",
  "slug": "gerber-viewer",
  "title": "Gerber Viewer",
  "brief": "View Gerber PCB fabrication files in the Adom Viewer.",
  "version": "1.0.0",
  "tags": [],
  "license": "MIT",
  "source_path": "SKILL.md",
  "readme": "# Gerber Viewer\n\nDisplay Gerber PCB fabrication files in the Adom Viewer with an interactive layer-by-layer viewer. Supports all standard Gerber (RS-274X) and Excellon drill file formats. Renders SVGs server-side using `@tracespace/core` — no CDN dependencies at runtime.\n\n## What the user asked to view\n\n$ARGUMENTS\n\n## MCP Tool\n\nUse `av_gerber_display` to display Gerber files:\n\n```\nmcp__adom-viewer__av_gerber_display({\n  directory: \"/path/to/gerber-output/\",\n  title: \"My PCB Board\"\n})\n```\n\nOr specify individual files:\n\n```\nmcp__adom-viewer__av_gerber_display({\n  files: [\"/path/to/board-F_Cu.gtl\", \"/path/to/board-B_Cu.gbl\", \"/path/to/board.drl\"],\n  title: \"Selected Layers\"\n})\n```\n\n### Parameters\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `directory` | string | one of dir/files | Path to folder containing Gerber/drill files |\n| `files` | string[] | one of dir/files | Array of specific file paths |\n| `title` | string | no | Tab title in the viewer |\n| `group` | string | no | Tab group name for grouping related tabs |\n| `instance` | string | no | Target AV instance ID |\n\n## Full Workflow: From KiCad PCB to Gerber Viewer\n\nThe most common workflow is exporting Gerbers from a `.kicad_pcb` file and displaying them:\n\n### Step 1: Export Gerbers via KiCad CLI Service\n\n```javascript\nimport { pcbExportGerbers } from '/home/adom/gallia/viewer/kicad-api-client.js';\n\nconst result = await pcbExportGerbers(\n  '/path/to/board.kicad_pcb',\n  '/tmp/gerbers.zip',\n  {\n    layers: 'F.Cu,B.Cu,F.SilkS,B.SilkS,F.Mask,B.Mask,Edge.Cuts', // optional filter\n    drillFormat: 'excellon',\n  }\n);\n// result: { outputPath, fileCount, files[] }\n```\n\n### Step 2: Extract the ZIP\n\n```javascript\nimport { execSync } from 'child_process';\nexecSync(`python3 -c \"import zipfile; zipfile.ZipFile('${zipPath}').extractall('${outputDir}')\"`);\n```\n\nOr use Node:\n\n```bash\ncd /path/to/output && python3 -c \"import zipfile; zipfile.ZipFile('/tmp/gerbers.zip').extractall('.')\"\n```\n\n### Step 3: Display in Gerber Viewer\n\n```\nmcp__adom-viewer__av_gerber_display({\n  directory: \"/path/to/output/\",\n  title: \"Board Name\"\n})\n```\n\n### One-Shot Script (recommended)\n\n```javascript\n// node --input-type=module\nimport { pcbExportGerbers } from '/home/adom/gallia/viewer/kicad-api-client.js';\nimport { collectGerberFiles, renderGerberLayers, generateGerberViewerHtml } from '/home/adom/gallia/viewer/gerber-viewer.js';\nimport { writeFile } from 'fs/promises';\nimport { execSync } from 'child_process';\n\n// Export Gerbers from KiCad\nconst zipPath = '/tmp/gerbers.zip';\nconst gerberDir = '/tmp/gerbers-out';\nawait pcbExportGerbers('/path/to/board.kicad_pcb', zipPath);\nexecSync(`mkdir -p ${gerberDir} && python3 -c \"import zipfile; zipfile.ZipFile('${zipPath}').extractall('${gerberDir}')\"`);\n\n// Render and generate HTML\nconst paths = await collectGerberFiles(gerberDir);\nconst layers = await renderGerberLayers(paths);\nconst html = generateGerberViewerHtml(layers, { title: 'My Board' });\nawait writeFile('/tmp/gerber-viewer.html', html);\n\n// Then display via: av_display_file({ file_path: '/tmp/gerber-viewer.html', title: 'My Board' })\n```\n\n## Supported File Extensions\n\n| Extension | Type |\n|-----------|------|\n| `.gbr`, `.ger` | Generic Gerber |\n| `.gtl` | Top copper |\n| `.gbl` | Bottom copper |\n| `.gts` | Top solder mask |\n| `.gbs` | Bottom solder mask |\n| `.gto` | Top silkscreen |\n| `.gbo` | Bottom silkscreen |\n| `.gtp`, `.gbp` | Solder paste |\n| `.gko`, `.gm1`, `.gm2`, `.gm3` | Board outline / mechanical |\n| `.drl`, `.xln`, `.exc` | Excellon drill |\n| `.g1`–`.g4` | Inner copper layers |\n| `.pho`, `.art` | Photoplotter / artwork |\n\n## Viewer Features\n\n- **Single layer mode**: View one layer at a time with click-to-select in sidebar\n- **All layers mode**: Overlay all layers with adjustable transparency\n- **Layer visibility toggles**: Show/hide individual layers via eye icon\n- **Color coding**: Layers are auto-colored by type (red=top copper, blue=bottom copper, cyan=drill, green=soldermask, yellow=silkscreen, white=outline)\n- **Zoom/pan**: Mouse wheel zoom, click-drag pan, fit-to-view button\n- **Layer sorting**: Copper layers first, then outline, silkscreen, soldermask, drill. Empty layers are filtered out.\n\n## postMessage API (AI Control)\n\nThe viewer iframe supports these messages for programmatic control:\n\n```javascript\n// Select a layer by index or name\n{ type: \"gerber_select_layer\", index: 0 }\n{ type: \"gerber_select_layer\", name: \"F_Cu\" }\n\n// Switch between single and all-layers mode\n{ type: \"gerber_set_mode\", mode: \"single\" }\n{ type: \"gerber_set_mode\", mode: \"all\" }\n\n// Set opacity for all-layers mode (0-1)\n{ type: \"gerber_set_opacity\", opacity: 0.6 }\n\n// Toggle layer visibility\n{ type: \"gerber_toggle_layer\", index: 2 }\n\n// Request current state\n{ type: \"gerber_get_info\" }\n// Response: { type: \"gerber_info\", layers: [...], mode, activeLayer, zoom }\n```\n\n## Manual Rendering (without MCP tool)\n\nIf the MCP tool isn't available, generate and display manually:\n\n```javascript\nimport { collectGerberFiles, renderGerberLayers, generateGerberViewerHtml } from '/home/adom/gallia/viewer/gerber-viewer.js';\nimport { writeFile } from 'fs/promises';\n\nconst paths = await collectGerberFiles('/path/to/gerber-dir/');\nconst layers = await renderGerberLayers(paths);\nconst html = generateGerberViewerHtml(layers, { title: 'My Board' });\nawait writeFile('/tmp/gerber-viewer.html', html);\n\n// Then use av_display_file to show it\n```\n\n## File Locations\n\n```\n/home/adom/gallia/viewer/gerber-viewer.js     -- Core rendering engine (tracespace → SVG → HTML)\n/home/adom/gallia/viewer/mcp/server.js         -- av_gerber_display MCP tool\n/home/adom/gallia/viewer/kicad-api-client.js   -- pcbExportGerbers() for KiCad → Gerber export\n/home/adom/gallia/viewer/registry.json         -- File type → skill mapping\n/home/adom/gallia/viewer/viewer/index.html     -- Viewer dropdown entry (GerberView)\n```\n\n## Troubleshooting\n\n| Symptom | Cause | Fix |\n|---------|-------|-----|\n| Empty layers in sidebar | Gerber file has no geometry | Normal — empty layers are auto-filtered |\n| Drill holes misaligned | tracespace drill unit mismatch | Built-in fix converts drill SVGs to match copper coordinate system |\n| \"No Gerber files found\" | Wrong directory or no recognized extensions | Check file extensions match the supported list |\n| KiCad Gerber export fails | KiCad CLI service not running | Check `pcbExportGerbers` health via `checkHealth()` from kicad-api-client.js |",
  "author": {
    "name": "Kyle Bergstedt",
    "email": "[email protected]"
  },
  "visibility": {
    "public": true
  },
  "hero": null,
  "sample_prompts": [],
  "discovery_triggers": [],
  "discovery_pitch": null,
  "metadata": {},
  "created_at": "2026-05-28T05:30:00.794Z",
  "updated_at": "2026-05-28T05:30:00.794Z",
  "sub_skills": [],
  "parent_app": null,
  "org": "adom"
}