# SVG Editing Workflow
## Flipping/Mirroring
The `translate` compensates for the flip moving content off-canvas. Values should match the viewBox dimensions.
```xml
...
...
```
## Combining Multiple SVGs
Merge SVGs by placing their content into a single `` element. Adjust positions using `transform="translate(x, y)"` or by wrapping in `` groups.
```xml
BrandName
```
## Boolean Operations as Compound Paths
Design tools have union, subtract, intersect, and exclude. In raw SVG, achieve these with compound paths and fill rules.
### Union (combine two shapes)
Merge both shapes' path data into a single ``. With the default `fill-rule="nonzero"`, overlapping same-direction subpaths just fill.
For a true outline-only union (merged contour), you'd need to calculate the actual merged path. In practice, either accept overlapping paths (they render the same when filled) or manually trace the combined outline.
### Subtract (cut one shape out of another)
Use `fill-rule="evenodd"` with overlapping subpaths. The intersection becomes transparent:
```xml
```
Alternatively, use `` for non-path shapes.
### Intersect (keep only the overlap)
Use `` with one shape clipping the other:
```xml
```
### Exclude (XOR: only non-overlapping areas)
Use `fill-rule="evenodd"` with both shapes in a single path. Where they overlap, the fill cancels out. The key difference from union: with `evenodd`, the overlapping region is transparent. With `nonzero` (default), it's filled.
## Multi-Variant Preview Page
When creating multiple logo/icon options, use the data-driven preview system. This separates the static HTML scaffold from the variant data, so iterating on designs only requires updating a small data file.
### Setup
1. **Copy `assets/preview.html`** to the project directory using `cp` with the absolute path from where this skill was loaded (e.g., `cp /path/to/this/skill/assets/preview.html ./preview.html`). Do not read it into context or modify it.
2. **Write `variants.js`** in the same directory with the variant data (format below).
3. **Auto-open** with `open preview.html` (macOS) or `xdg-open preview.html` (Linux).
### `variants.js` Format
```js
window.VARIANTS = {
projectName: "Acme",
brandName: "Acme",
concepts: [
{
name: "Geometric",
variants: [
{
id: "01",
name: "Prism",
description: "Light refracting through a triangular prism. Suggests transformation.",
light: "logo-prism.svg",
dark: "logo-prism-dark.svg"
},
{
id: "02",
name: "Hexagon Stack",
description: "Layered hexagons suggesting modularity and structure.",
light: "logo-hex.svg"
}
]
}
]
};
```
| Field | Required | Notes |
|-------|----------|-------|
| `projectName` | Yes | Used in page title and heading |
| `brandName` | Yes | Shown in nav bar mockups |
| `concepts[].name` | Yes | Section heading (group by concept, not layout) |
| `concepts[].variants[].id` | Yes | Short identifier, e.g. "01", "02" |
| `concepts[].variants[].name` | Yes | Variant name shown on card |
| `concepts[].variants[].description` | Yes | Metaphor explanation |
| `concepts[].variants[].light` | Yes | Path to light-background SVG |
| `concepts[].variants[].dark` | No | Path to dark-background SVG. Omit for monochrome (auto-applies `filter:brightness(0) invert(1)`) |
### What the preview renders per card
The scaffold in `assets/preview.html` reads `variants.js` and generates:
- **Size ramp** (16, 32, 64px) on white background
- **Dark background row** (16, 32, 64px) using the dark SVG or monochrome filter
- **Favicon mockup** (16px in a browser tab strip)
- **Nav bar mockup** (logo + brand name, light and dark)
- **Click-to-compare** bar (pin up to 4 cards for side-by-side evaluation)
- **Live reload** (3s poll cache-busts SVG images and reloads `variants.js`, no manual refresh needed)
### Iteration workflow
| Change type | What to update | Then |
|-------------|---------------|------|
| Edit an SVG (colors, shapes, paths) | Just the `.svg` file | Nothing. Live reload picks it up in 3s. |
| Add/remove/rename a variant | `variants.js` | Nothing. Live reload picks it up in 3s. |
| Replace a variant (new SVG + new filename) | The `.svg` file + `variants.js` | Nothing. Both auto-reload. |
| Add a new concept group | `variants.js` | Nothing. Live reload picks it up in 3s. |
| Change project or brand name | `variants.js` | Nothing. Live reload picks it up in 3s. |
**Do NOT rewrite `preview.html`.** It is a static scaffold copied from the skill assets. All project-specific data lives in `variants.js`.
### Checklist
- **Copy `assets/preview.html`** to the project directory (do not modify it)
- **Write `variants.js`** with all variant data
- **Group by concept** (e.g., "Geometric", "Network / Graph", "Abstract")
- **Description per card** explaining the metaphor and what it conveys
- For colored logos, provide a `-dark.svg` variant (not CSS filters)
- For monochrome logos, omit the `dark` field (auto-applies invert filter)
- **Auto-open** the preview so the user sees options immediately
- On subsequent iterations, **only edit `variants.js`** and SVG files. Live reload handles the rest.
## Workflow Tips
1. **Start with shape primitives**, convert to paths only when needed for optimization or compound operations
2. **Use relative coordinates** (`m`, `l`, `c`) when hand-writing paths. Easier to reason about incrementally
3. **Test at multiple sizes**: render at 16px, 24px, 48px, and 200px to verify clean scaling
4. **Keep a monochrome version**: if using color, ensure it also works with a single `currentColor`
5. **Validate the output**: open in a browser, not just a code editor. Check for rendering artifacts
6. **Round coordinates to the grid**: snap to integers on 24x24 canvas for pixel-perfect rendering at 1x