# Gerber Viewer

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

## What the user asked to view

$ARGUMENTS

## MCP Tool

Use `av_gerber_display` to display Gerber files:

```
mcp__adom-viewer__av_gerber_display({
  directory: "/path/to/gerber-output/",
  title: "My PCB Board"
})
```

Or specify individual files:

```
mcp__adom-viewer__av_gerber_display({
  files: ["/path/to/board-F_Cu.gtl", "/path/to/board-B_Cu.gbl", "/path/to/board.drl"],
  title: "Selected Layers"
})
```

### Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `directory` | string | one of dir/files | Path to folder containing Gerber/drill files |
| `files` | string[] | one of dir/files | Array of specific file paths |
| `title` | string | no | Tab title in the viewer |
| `group` | string | no | Tab group name for grouping related tabs |
| `instance` | string | no | Target AV instance ID |

## Full Workflow: From KiCad PCB to Gerber Viewer

The most common workflow is exporting Gerbers from a `.kicad_pcb` file and displaying them:

### Step 1: Export Gerbers via KiCad CLI Service

```javascript
import { pcbExportGerbers } from '/home/adom/gallia/viewer/kicad-api-client.js';

const result = await pcbExportGerbers(
  '/path/to/board.kicad_pcb',
  '/tmp/gerbers.zip',
  {
    layers: 'F.Cu,B.Cu,F.SilkS,B.SilkS,F.Mask,B.Mask,Edge.Cuts', // optional filter
    drillFormat: 'excellon',
  }
);
// result: { outputPath, fileCount, files[] }
```

### Step 2: Extract the ZIP

```javascript
import { execSync } from 'child_process';
execSync(`python3 -c "import zipfile; zipfile.ZipFile('${zipPath}').extractall('${outputDir}')"`);
```

Or use Node:

```bash
cd /path/to/output && python3 -c "import zipfile; zipfile.ZipFile('/tmp/gerbers.zip').extractall('.')"
```

### Step 3: Display in Gerber Viewer

```
mcp__adom-viewer__av_gerber_display({
  directory: "/path/to/output/",
  title: "Board Name"
})
```

### One-Shot Script (recommended)

```javascript
// node --input-type=module
import { pcbExportGerbers } from '/home/adom/gallia/viewer/kicad-api-client.js';
import { collectGerberFiles, renderGerberLayers, generateGerberViewerHtml } from '/home/adom/gallia/viewer/gerber-viewer.js';
import { writeFile } from 'fs/promises';
import { execSync } from 'child_process';

// Export Gerbers from KiCad
const zipPath = '/tmp/gerbers.zip';
const gerberDir = '/tmp/gerbers-out';
await pcbExportGerbers('/path/to/board.kicad_pcb', zipPath);
execSync(`mkdir -p ${gerberDir} && python3 -c "import zipfile; zipfile.ZipFile('${zipPath}').extractall('${gerberDir}')"`);

// Render and generate HTML
const paths = await collectGerberFiles(gerberDir);
const layers = await renderGerberLayers(paths);
const html = generateGerberViewerHtml(layers, { title: 'My Board' });
await writeFile('/tmp/gerber-viewer.html', html);

// Then display via: av_display_file({ file_path: '/tmp/gerber-viewer.html', title: 'My Board' })
```

## Supported File Extensions

| Extension | Type |
|-----------|------|
| `.gbr`, `.ger` | Generic Gerber |
| `.gtl` | Top copper |
| `.gbl` | Bottom copper |
| `.gts` | Top solder mask |
| `.gbs` | Bottom solder mask |
| `.gto` | Top silkscreen |
| `.gbo` | Bottom silkscreen |
| `.gtp`, `.gbp` | Solder paste |
| `.gko`, `.gm1`, `.gm2`, `.gm3` | Board outline / mechanical |
| `.drl`, `.xln`, `.exc` | Excellon drill |
| `.g1`–`.g4` | Inner copper layers |
| `.pho`, `.art` | Photoplotter / artwork |

## Viewer Features

- **Single layer mode**: View one layer at a time with click-to-select in sidebar
- **All layers mode**: Overlay all layers with adjustable transparency
- **Layer visibility toggles**: Show/hide individual layers via eye icon
- **Color coding**: Layers are auto-colored by type (red=top copper, blue=bottom copper, cyan=drill, green=soldermask, yellow=silkscreen, white=outline)
- **Zoom/pan**: Mouse wheel zoom, click-drag pan, fit-to-view button
- **Layer sorting**: Copper layers first, then outline, silkscreen, soldermask, drill. Empty layers are filtered out.

## postMessage API (AI Control)

The viewer iframe supports these messages for programmatic control:

```javascript
// Select a layer by index or name
{ type: "gerber_select_layer", index: 0 }
{ type: "gerber_select_layer", name: "F_Cu" }

// Switch between single and all-layers mode
{ type: "gerber_set_mode", mode: "single" }
{ type: "gerber_set_mode", mode: "all" }

// Set opacity for all-layers mode (0-1)
{ type: "gerber_set_opacity", opacity: 0.6 }

// Toggle layer visibility
{ type: "gerber_toggle_layer", index: 2 }

// Request current state
{ type: "gerber_get_info" }
// Response: { type: "gerber_info", layers: [...], mode, activeLayer, zoom }
```

## Manual Rendering (without MCP tool)

If the MCP tool isn't available, generate and display manually:

```javascript
import { collectGerberFiles, renderGerberLayers, generateGerberViewerHtml } from '/home/adom/gallia/viewer/gerber-viewer.js';
import { writeFile } from 'fs/promises';

const paths = await collectGerberFiles('/path/to/gerber-dir/');
const layers = await renderGerberLayers(paths);
const html = generateGerberViewerHtml(layers, { title: 'My Board' });
await writeFile('/tmp/gerber-viewer.html', html);

// Then use av_display_file to show it
```

## File Locations

```
/home/adom/gallia/viewer/gerber-viewer.js     -- Core rendering engine (tracespace → SVG → HTML)
/home/adom/gallia/viewer/mcp/server.js         -- av_gerber_display MCP tool
/home/adom/gallia/viewer/kicad-api-client.js   -- pcbExportGerbers() for KiCad → Gerber export
/home/adom/gallia/viewer/registry.json         -- File type → skill mapping
/home/adom/gallia/viewer/viewer/index.html     -- Viewer dropdown entry (GerberView)
```

## Troubleshooting

| Symptom | Cause | Fix |
|---------|-------|-----|
| Empty layers in sidebar | Gerber file has no geometry | Normal — empty layers are auto-filtered |
| Drill holes misaligned | tracespace drill unit mismatch | Built-in fix converts drill SVGs to match copper coordinate system |
| "No Gerber files found" | Wrong directory or no recognized extensions | Check file extensions match the supported list |
| KiCad Gerber export fails | KiCad CLI service not running | Check `pcbExportGerbers` health via `checkHealth()` from kicad-api-client.js |
