Arc 6 Quest A6

The Illuminators' Workshop

Git for design, LFS, SVG and design tokens

In the west wing of the Citadel, bathed in the soft light of stained glass windows, lies the Illuminators' Workshop. Here, the realm's artists create the ornaments, illustrations and interfaces that bring scrolls to life. Their digital brushes produce visual works that cannot be reduced to text - and that's precisely the challenge.

The Master Illuminator observes you with curiosity. "You know how to version code, Versioner. But do you know how to version art? A 200 MB Photoshop file? A complete design system? Color tokens shared across ten applications? Welcome to our world. It's beautiful, but it doesn't follow your usual rules."

The problem with graphic assets

In a software project, designers produce files very different from source code:

  • Large source files: .psd (Photoshop), .ai (Illustrator), .sketch, .fig (Figma) - from 10 MB to 500 MB each
  • Binary formats: Git cannot compute textual diffs
  • Frequent modifications: a designer may save 50 times a day
  • Numerous variants: icon-v1.psd, icon-v2.psd, icon-v2-final.psd, icon-v2-final-REAL.psd...

Without an adapted solution, a repository with graphic assets quickly becomes unmanageable:

# A repo without Git LFS, after 6 months of design:
du -sh .git/
# 4.7 GB    .git/

# Every version of every PSD is stored in full in the history.
# Cloning takes 45 minutes.
# Nobody is happy.

Graphic assets are not like code. They are large, binary, and change often. You need adapted tools and workflows to version them correctly.

Git LFS for design

You may have already encountered Git LFS (Large File Storage) in other quests. Here's a quick refresher and the patterns specific to design.

Principle reminder

Git LFS replaces large files in your repository with small "pointer" files. The real files are stored on a separate LFS server. Result: the repository stays lightweight, clones are fast.

# Installation (once per machine)
git lfs install

# In your project, track design files
git lfs track "*.psd"
git lfs track "*.ai"
git lfs track "*.sketch"
git lfs track "*.fig"
git lfs track "*.xd"
git lfs track "*.tiff"
git lfs track "*.raw"

# This modifies .gitattributes
cat .gitattributes
# *.psd filter=lfs diff=lfs merge=lfs -text
# *.ai filter=lfs diff=lfs merge=lfs -text
# *.sketch filter=lfs diff=lfs merge=lfs -text
# *.fig filter=lfs diff=lfs merge=lfs -text
# *.xd filter=lfs diff=lfs merge=lfs -text
# *.tiff filter=lfs diff=lfs merge=lfs -text
# *.raw filter=lfs diff=lfs merge=lfs -text

Complete LFS patterns for design

# .gitattributes - recommended patterns for a design repo

# Design source files
*.psd filter=lfs diff=lfs merge=lfs -text
*.psb filter=lfs diff=lfs merge=lfs -text
*.ai filter=lfs diff=lfs merge=lfs -text
*.sketch filter=lfs diff=lfs merge=lfs -text
*.fig filter=lfs diff=lfs merge=lfs -text
*.xd filter=lfs diff=lfs merge=lfs -text

# High resolution images
*.tiff filter=lfs diff=lfs merge=lfs -text
*.tif filter=lfs diff=lfs merge=lfs -text
*.raw filter=lfs diff=lfs merge=lfs -text
*.bmp filter=lfs diff=lfs merge=lfs -text

# Exported images (optional - some prefer not to LFS PNGs)
*.png filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text

# Fonts
*.otf filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.woff filter=lfs diff=lfs merge=lfs -text
*.woff2 filter=lfs diff=lfs merge=lfs -text

# Videos and animations
*.mp4 filter=lfs diff=lfs merge=lfs -text
*.mov filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text

Tip: For PNG and JPG files, the decision depends on your situation. If they're small icons (a few KB), no need for LFS. If they're high-resolution mockups (several MB), LFS is recommended. The rule: LFS for any file over 500 KB.

Visual diff for images

When a designer modifies a mockup, how do you know what changed? Visual diff tools compare two versions of an image and show the differences.

git-diff-image

git-diff-image is an open source tool that integrates directly into git diff to display visual differences between two versions of an image:

# Installation
git clone https://github.com/ewanmellor/git-diff-image.git
cd git-diff-image
./install.sh

# After installation, git diff automatically shows
# visual differences for images
git diff HEAD~1 -- assets/hero-banner.png
# Opens a window with both versions side by side
# and an overlay view showing the modified pixels

Beyond Compare and Kaleidoscope

For professional use, tools like Beyond Compare (cross-platform) or Kaleidoscope (macOS) offer advanced features:

  • Side by side mode: both versions next to each other
  • Overlay mode: one image on top of the other with a slider
  • Difference mode: only differing pixels are displayed
  • Synchronized zoom: zoom into a detail in both versions
# Configure Beyond Compare as diff tool for images
git config --global diff.tool bc4
git config --global difftool.bc4.cmd '"C:/Program Files/Beyond Compare 4/BComp.exe" "$LOCAL" "$REMOTE"'

# Usage
git difftool HEAD~1 -- assets/hero-banner.png
# PowerShell - identical configuration
git config --global diff.tool bc4
git config --global difftool.bc4.cmd '"C:\Program Files\Beyond Compare 4\BComp.exe" "$LOCAL" "$REMOTE"'

SVG in Git - the dream format

The SVG (Scalable Vector Graphics) format is a special and wonderful case for versioning: it's XML, therefore text. Git can compute diffs, and you can see exactly what changed.

# An SVG file is text:
cat icon-home.svg
# <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
#   <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
# </svg>

# Git diff works perfectly:
git diff icon-home.svg
# -  <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
# +  <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"
# +        fill="#333333"/>

SVG advantages in Git

  • Readable diffs: you see exactly which attribute changed
  • Lightweight files: no need for Git LFS
  • Scalable: no quality loss, perfect for icons and illustrations
  • Mergeable: in theory, Git can merge SVG modifications (with caution)

Optimization with SVGO

SVGO (SVG Optimizer) cleans and optimizes SVG files exported from design software. SVGs exported from Illustrator or Figma often contain unnecessary code:

# Installation
npm install -g svgo

# Optimize an SVG file
svgo icon-home.svg
# icon-home.svg: 1.24 KB -> 0.45 KB (63.7% reduction)

# Optimize an entire folder
svgo -f assets/icons/ -o assets/icons-optimized/

# Custom configuration (.svgo.config.js)
cat > .svgo.config.js << 'EOF'
module.exports = {
  plugins: [
    'preset-default',
    'removeDimensions',         // Use viewBox instead of width/height
    {
      name: 'removeAttrs',
      params: {
        attrs: ['data-name']    // Remove Illustrator attributes
      }
    }
  ]
}
EOF

# Tip: add SVGO as a pre-commit hook
# to automatically optimize SVGs before each commit

Tip: Prefer SVG for anything that can use it: icons, logos, simple illustrations, graphics. Reserve bitmap formats (PNG, JPG) for photos and complex images that don't vectorize well.

Designers + developers workflow

The biggest challenge isn't technical - it's human. How do you get designers (who think in pixels) and developers (who think in code) to work together on the same repository?

Who touches what?

# Clear structure with separation of responsibilities
my-project/
β”œβ”€β”€ src/                    # Developers: application code
β”œβ”€β”€ assets/
β”‚   β”œβ”€β”€ raw/                # Designers: source files (PSD, AI, Sketch)
β”‚   β”‚   └── hero-banner.psd
β”‚   β”œβ”€β”€ exported/           # Designers: final exports
β”‚   β”‚   β”œβ”€β”€ hero-banner.png
β”‚   β”‚   β”œβ”€β”€ hero-banner@2x.png
β”‚   β”‚   └── icons/
β”‚   β”‚       β”œβ”€β”€ home.svg
β”‚   β”‚       └── search.svg
β”‚   └── fonts/              # Shared: fonts used
β”œβ”€β”€ tokens/                 # Shared: design tokens (JSON/YAML)
└── docs/
    └── design/             # Designers: visual documentation

Naming conventions

Strict conventions prevent chaos:

  • Lowercase with hyphens: hero-banner.png, not Hero Banner.png or HeroBanner.png
  • No spaces: spaces in filenames cause problems everywhere
  • Size suffixes: icon@1x.png, icon@2x.png, icon@3x.png
  • No "final" in the name: Git manages versions, not the filename

Anti-pattern: logo-v3-final-FINAL-fixed-2.psd. With Git, the latest version is always logo.psd on the main branch. Period.

File locking for binary assets

Two designers can't modify the same PSD file simultaneously - there's no possible merge on a binary. The solution: Git LFS file locking.

# Configure locking in .gitattributes
# *.psd filter=lfs diff=lfs merge=lfs -text lockable
# *.ai filter=lfs diff=lfs merge=lfs -text lockable

# Before modifying a file, lock it
git lfs lock assets/raw/hero-banner.psd
# Locked assets/raw/hero-banner.psd

# See locked files
git lfs locks
# ID    Path                           Owner      Locked At
# 1234  assets/raw/hero-banner.psd     alice      2026-03-09T14:30:00Z

# After committing, unlock
git lfs unlock assets/raw/hero-banner.psd

# If a colleague tries to modify a locked file:
git push
# Forbidden: assets/raw/hero-banner.psd is locked by alice

Figma integration and design tokens

Figma is today's dominant design tool. Its files are stored in the cloud (not in Git), but you can create a bridge between Figma and Git through design tokens.

What is a design token?

A design token is an abstract design value: a color, a font size, a spacing, a border radius. Instead of writing #3B82F6 everywhere, you write color.primary.500.

# tokens/colors.json - Design tokens in W3C format
{
  "color": {
    "primary": {
      "50":  { "$value": "#EFF6FF", "$type": "color" },
      "100": { "$value": "#DBEAFE", "$type": "color" },
      "500": { "$value": "#3B82F6", "$type": "color" },
      "700": { "$value": "#1D4ED8", "$type": "color" },
      "900": { "$value": "#1E3A5F", "$type": "color" }
    },
    "neutral": {
      "0":   { "$value": "#FFFFFF", "$type": "color" },
      "100": { "$value": "#F3F4F6", "$type": "color" },
      "900": { "$value": "#111827", "$type": "color" }
    }
  },
  "spacing": {
    "xs":  { "$value": "4px",  "$type": "dimension" },
    "sm":  { "$value": "8px",  "$type": "dimension" },
    "md":  { "$value": "16px", "$type": "dimension" },
    "lg":  { "$value": "24px", "$type": "dimension" },
    "xl":  { "$value": "32px", "$type": "dimension" }
  },
  "font": {
    "family": {
      "heading": { "$value": "Inter, sans-serif", "$type": "fontFamily" },
      "body":    { "$value": "Inter, sans-serif", "$type": "fontFamily" },
      "mono":    { "$value": "JetBrains Mono, monospace", "$type": "fontFamily" }
    },
    "size": {
      "sm":  { "$value": "14px", "$type": "dimension" },
      "md":  { "$value": "16px", "$type": "dimension" },
      "lg":  { "$value": "20px", "$type": "dimension" },
      "xl":  { "$value": "24px", "$type": "dimension" }
    }
  },
  "border": {
    "radius": {
      "sm":   { "$value": "4px",  "$type": "dimension" },
      "md":   { "$value": "8px",  "$type": "dimension" },
      "full": { "$value": "9999px", "$type": "dimension" }
    }
  }
}

Export from Figma to Git

Several Figma plugins allow you to export tokens directly in a usable format:

  • Tokens Studio for Figma: the most popular. Synchronizes tokens between Figma and a Git repository (GitHub, GitLab). Designers modify in Figma, tokens are automatically updated in the repo.
  • Figma Tokens: manual or automated export to JSON
  • Figma API: custom scripts to extract styles
# Workflow with Tokens Studio
# 1. The designer modifies a color in Figma
# 2. Tokens Studio detects the change
# 3. Tokens Studio creates a Pull Request on GitHub
#    with the updated tokens.json file
# 4. The developer reviews and merges the PR
# 5. CI/CD generates the CSS/SCSS/JS variables

Style Dictionary - transforming tokens

Style Dictionary (by Amazon) transforms design tokens JSON into variables usable on any platform:

# Installation
npm install -g style-dictionary

# Configuration (config.json)
cat > config.json << 'EOF'
{
  "source": ["tokens/**/*.json"],
  "platforms": {
    "css": {
      "transformGroup": "css",
      "buildPath": "build/css/",
      "files": [{
        "destination": "variables.css",
        "format": "css/variables"
      }]
    },
    "scss": {
      "transformGroup": "scss",
      "buildPath": "build/scss/",
      "files": [{
        "destination": "_variables.scss",
        "format": "scss/variables"
      }]
    },
    "js": {
      "transformGroup": "js",
      "buildPath": "build/js/",
      "files": [{
        "destination": "tokens.js",
        "format": "javascript/es6"
      }]
    }
  }
}
EOF

# Generate variables for all platforms
style-dictionary build

# CSS result:
cat build/css/variables.css
# :root {
#   --color-primary-50: #EFF6FF;
#   --color-primary-500: #3B82F6;
#   --spacing-sm: 8px;
#   --spacing-md: 16px;
#   --font-size-md: 16px;
#   --border-radius-md: 8px;
# }

# SCSS result:
cat build/scss/_variables.scss
# $color-primary-50: #EFF6FF;
# $color-primary-500: #3B82F6;
# $spacing-sm: 8px;

Design tokens are the bridge between design and code. Versioned in Git as JSON, they are the shared source of truth between designers and developers. When a designer changes a color, the git diff shows exactly: "#3B82F6" -> "#2563EB".

The W3C Design Tokens format

The W3C Design Tokens Community Group is working on a standard for design tokens. The format we used above ($value, $type) is the emerging W3C format. It aims to become the universal standard.

Format structure

# W3C Design Tokens format
{
  "group-name": {
    "token-name": {
      "$value": "...",          # The token value
      "$type": "color",         # The type (color, dimension, fontFamily, etc.)
      "$description": "..."     # Optional description
    }
  }
}

# Supported types:
# color       - colors (#hex, rgb, hsl)
# dimension   - sizes (px, rem, em)
# fontFamily  - font families
# fontWeight  - weights (400, 700, bold)
# duration    - animation durations (200ms)
# cubicBezier - animation curves
# shadow      - box shadows
# gradient    - gradients

The advantage of using the W3C format: all tools are converging toward this standard. Tokens Studio, Style Dictionary, and many other tools already support it.

Organizing a design repo

my-design-system/
β”œβ”€β”€ assets/
β”‚   β”œβ”€β”€ raw/                     # Design sources (PSD, AI, Sketch)
β”‚   β”‚   β”œβ”€β”€ illustrations/       # High resolution illustrations
β”‚   β”‚   β”œβ”€β”€ photography/         # Reference photos
β”‚   β”‚   └── mockups/             # Screen mockups
β”‚   └── exported/                # Optimized exports ready to use
β”‚       β”œβ”€β”€ icons/               # Optimized SVG icons
β”‚       β”‚   β”œβ”€β”€ home.svg
β”‚       β”‚   β”œβ”€β”€ search.svg
β”‚       β”‚   └── user.svg
β”‚       β”œβ”€β”€ logos/               # Logos in various formats
β”‚       β”‚   β”œβ”€β”€ logo-full.svg
β”‚       β”‚   β”œβ”€β”€ logo-icon.svg
β”‚       β”‚   └── logo-full.png
β”‚       └── images/              # Product images
β”œβ”€β”€ tokens/                      # Design tokens (source of truth)
β”‚   β”œβ”€β”€ colors.json
β”‚   β”œβ”€β”€ spacing.json
β”‚   β”œβ”€β”€ typography.json
β”‚   └── shadows.json
β”œβ”€β”€ build/                       # Generated files (in .gitignore)
β”‚   β”œβ”€β”€ css/variables.css
β”‚   β”œβ”€β”€ scss/_variables.scss
β”‚   └── js/tokens.js
β”œβ”€β”€ components/                  # Documented components
β”‚   β”œβ”€β”€ button/
β”‚   β”‚   β”œβ”€β”€ button.md            # Component documentation
β”‚   β”‚   └── button-preview.png   # Visual preview
β”‚   └── card/
β”‚       β”œβ”€β”€ card.md
β”‚       └── card-preview.png
β”œβ”€β”€ docs/                        # Design system documentation
β”‚   β”œβ”€β”€ getting-started.md
β”‚   └── contribution-guide.md
β”œβ”€β”€ .gitattributes               # LFS patterns
β”œβ”€β”€ .gitignore
β”œβ”€β”€ config.json                  # Style Dictionary config
└── package.json

Tip: The build/ folder should be in .gitignore - it's automatically generated by Style Dictionary. Only the tokens/ files (the source of truth) are versioned.

Practical exercise - Design repo with LFS and tokens

Create a repository for a fictional design system (the Citadel's "Visual Grimoire") with Git LFS for assets and versioned design tokens:

  1. Create the recommended structure
  2. Configure Git LFS for design files
  3. Add design tokens in JSON (W3C format)
  4. Create SVG icons and optimize them
  5. Simulate a color change and observe the diff

Step 1 - Create the structure

# Create the repository
mkdir visual-grimoire
cd visual-grimoire
git init -b main

# Create the directory tree
mkdir -p assets/raw/illustrations
mkdir -p assets/raw/mockups
mkdir -p assets/exported/icons
mkdir -p assets/exported/logos
mkdir -p assets/exported/images
mkdir -p tokens
mkdir -p components/button
mkdir -p components/card
mkdir -p docs

Step 2 - Configure Git LFS

# Initialize Git LFS
git lfs install

# Track design files
git lfs track "*.psd"
git lfs track "*.ai"
git lfs track "*.sketch"
git lfs track "*.tiff"
git lfs track "*.raw"
git lfs track "assets/exported/images/*.png"
git lfs track "assets/exported/images/*.jpg"

# Create the .gitignore
cat > .gitignore << 'EOF'
# Generated files
build/
node_modules/

# OS
.DS_Store
Thumbs.db
Desktop.ini

# Editors
*.swp
*.swo
*~
EOF

# First commit
git add .gitattributes .gitignore
git commit -m "Initial configuration: Git LFS + .gitignore"

Step 3 - Add design tokens

# Create color tokens
cat > tokens/colors.json << 'EOF'
{
  "color": {
    "primary": {
      "500": { "$value": "#7C3AED", "$type": "color", "$description": "Main Grimoire violet" },
      "700": { "$value": "#5B21B6", "$type": "color", "$description": "Dark violet" }
    },
    "accent": {
      "500": { "$value": "#F59E0B", "$type": "color", "$description": "Illumination gold" }
    },
    "neutral": {
      "0":   { "$value": "#FFFFFF", "$type": "color" },
      "900": { "$value": "#1F2937", "$type": "color" }
    }
  }
}
EOF

# Create spacing tokens
cat > tokens/spacing.json << 'EOF'
{
  "spacing": {
    "xs": { "$value": "4px",  "$type": "dimension" },
    "sm": { "$value": "8px",  "$type": "dimension" },
    "md": { "$value": "16px", "$type": "dimension" },
    "lg": { "$value": "24px", "$type": "dimension" },
    "xl": { "$value": "32px", "$type": "dimension" }
  }
}
EOF

git add tokens/
git commit -m "Add color and spacing design tokens"

Step 4 - Create SVG icons

# Create a simple SVG icon
cat > assets/exported/icons/shield.svg << 'EOF'

  

EOF

cat > assets/exported/icons/scroll.svg << 'EOF'

  
  
  
  

EOF

git add assets/exported/icons/
git commit -m "Add shield and scroll SVG icons"

Step 5 - Simulate a color change

# The designer decides to change the main violet
sed -i 's/#7C3AED/#8B5CF6/' tokens/colors.json
sed -i 's/#5B21B6/#6D28D9/' tokens/colors.json

# Observe the diff - perfectly readable!
git diff tokens/colors.json
# -      "500": { "$value": "#7C3AED", "$type": "color", ...
# +      "500": { "$value": "#8B5CF6", "$type": "color", ...
# -      "700": { "$value": "#5B21B6", "$type": "color", ...
# +      "700": { "$value": "#6D28D9", "$type": "color", ...

# Commit the change
git add tokens/colors.json
git commit -m "Update primary color: lighter violet"

# The history clearly shows the evolution
git log --oneline
# abc1234 Update primary color: lighter violet
# def5678 Add shield and scroll SVG icons
# ghi9012 Add color and spacing design tokens
# jkl3456 Initial configuration: Git LFS + .gitignore

Concept summary

Concept Description
Git LFS for design Track PSD, AI, Sketch and other large binaries
File locking Lock a binary file to prevent conflicts
Visual diff Tools for visually comparing two versions of an image
SVG Text-based vector format - perfect diffs in Git
SVGO SVG optimizer, removes unnecessary code
Design tokens Abstract design values (colors, sizes) in JSON
W3C format Emerging standard for design tokens ($value, $type)
Tokens Studio Figma plugin for synchronizing tokens with Git
Style Dictionary Tool for transforming JSON tokens into CSS/SCSS/JS
Naming conventions Lowercase, hyphens, no spaces, no "final"

The Master Illuminator examines your repository with an approving smile. "You've understood the essentials: design and code don't live in separate worlds. They share the same source of truth - tokens. They live in the same repository - with LFS for large files. They speak the same language - that of Git."

"Too many projects fail because designers work in their corner and developers in theirs. Colors don't match, spacing is inconsistent, icons have three different names. With what you know now, you can build a bridge between these two worlds."

She hands you a brush whose handle is engraved with Git tree branches. "This is the symbol of the Versioning Illuminators. You now know that art, like code, deserves a history. That every pixel changed should be documented. That every color should have its source of truth. Go forth, and may your designs be as clean as your commits."