Free Setup Guide

Canva AI 2.0 without Canva: layered edits with ComfyUI and Inkscape

AI tools love spitting out flat images. That is useless when you need to fix just the headline, swap the product photo, and keep everything else locked. Canva AI 2.0 solved that inside Canva. You can do the same on your machine for free.

Adam BurgeAdam BurgeNano Flow

Here is the stack I use: ComfyUI (an open-source Stable Diffusion node editor) to generate the visual, Inkscape (an open-source vector editor) for real layers and layout, plus ImageMagick (an open-source image CLI) to check and batch sizes. You keep text and logos as editable SVG text. You only replace the one image or line you want.

Plan the file like a real campaign. Keep text and logo as vector layers in an SVG. Use a linked image layer for the product photo so you can swap it without touching the rest. Generate the background or product visual once in ComfyUI, then update the SVG link.

Install ComfyUI and open it. It runs locally and gives you a browser UI.

bash
git clone https://github.com/comfyanonymous/ComfyUI.git && cd ComfyUI && python3 main.py

Verify it is up: visit http://127.0.0.1:8188 or run curl -s localhost:8188 | head -n1. You should see HTML from ComfyUI. Next, install Inkscape and ImageMagick, then make a simple SVG template with layers named headline, product, bg, logo. Export different sizes with Inkscape’s CLI per channel. Only then worry about prompt tweaks in ComfyUI. Stop here if you only need the quick local loop.


Plan the file like a real campaign. Keep text and logo as vector layers in an SVG. Use a linked image layer for the product photo so you can swap it without touching the rest. Generate the background or product visual once in ComfyUI, then update the SVG link.

Install ComfyUI and open it. It runs locally and gives you a browser UI.

bash
git clone https://github.com/comfyanonymous/ComfyUI.git && cd ComfyUI && python3 main.py

Verify it is up: visit http://127.0.0.1:8188 or run curl -s localhost:8188 | head -n1. You should see HTML from ComfyUI. Next, install Inkscape and ImageMagick, then make a simple SVG template with layers named headline, product, bg, logo. Export different sizes with Inkscape’s CLI per channel. Only then worry about prompt tweaks in ComfyUI.

Setup

We will use three free tools:

  • ComfyUI (an open-source Stable Diffusion node editor) for image generation
  • Inkscape (an open-source vector editor) for layered layouts
  • ImageMagick (an open-source image CLI) for quick checks and basic batch ops
  • xmlstarlet (an XML CLI) to edit text and image links inside SVG by id

macOS

bash
# Python, Git
xcode-select --install || true
brew install python3 git

# ComfyUI
git clone https://github.com/comfyanonymous/ComfyUI.git
cd ComfyUI
python3 -m venv .venv && source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt || true

# Inkscape, ImageMagick, xmlstarlet
brew install --cask inkscape
brew install imagemagick xmlstarlet

Start ComfyUI:

bash
source .venv/bin/activate
python main.py

Ubuntu/Debian Linux

bash
sudo apt update
sudo apt install -y python3-venv python3-dev git inkscape imagemagick xmlstarlet curl

git clone https://github.com/comfyanonymous/ComfyUI.git
cd ComfyUI
python3 -m venv .venv && source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt || true
python main.py

Windows 10/11

  • Install Python 3.10+ from python.org and check “Add Python to PATH”.
  • Install Git for Windows.
  • Install Inkscape from inkscape.org. Install ImageMagick and xmlstarlet via Chocolatey:
bash
choco install inkscape imagemagick xmlstarlet -y

Then open PowerShell:

bash
git clone https://github.com/comfyanonymous/ComfyUI.git
cd ComfyUI
python -m venv .venv; .\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
python .\main.py

Models for ComfyUI

Place at least one checkpoint in ComfyUI/models/checkpoints. Example using Hugging Face CLI to pull SDXL Turbo (SDXL is a Stable Diffusion XL model):

bash
pip install huggingface_hub
huggingface-cli download stabilityai/sdxl-turbo sdxl-turbo.safetensors --local-dir models/checkpoints

Verify

  • ComfyUI: curl -s http://127.0.0.1:8188 | grep -i ComfyUI || echo UI up should print HTML with ComfyUI in it.
  • Inkscape: inkscape --version should show Inkscape 1.2+.
  • ImageMagick: magick -version should work.
  • xmlstarlet: xmlstarlet --version should print a version line.

Create a layered SVG template

Make a minimal SVG with named ids for each layer. The product image is a linked <image> so you can swap the file path without touching layout.

bash
mkdir -p campaign/{assets,build}
cat > campaign/template.svg <<'SVG'
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="1080" height="1080" viewBox="0 0 1080 1080">
<g id="bg">
<rect x="0" y="0" width="1080" height="1080" fill="#0f172a"/>
</g>
<g id="logo">
<text id="logo_text" x="60" y="120" fill="#ffffff" font-size="64" font-family="Inter, Arial">ACME</text>
</g>
<g id="headline">
<text id="headline_text" x="60" y="260" fill="#ffffff" font-size="88" font-family="Inter, Arial" xml:space="preserve">Your summer upgrade</text>
</g>
<g id="product">
<image id="product_img" x="580" y="360" width="420" height="420" href="assets/product.png"/>
</g>
<g id="cta">
<rect x="60" y="940" width="320" height="80" rx="12" fill="#22c55e"/>
<text id="cta_text" x="80" y="995" fill="#0b141d" font-size="42" font-family="Inter, Arial">Shop now</text>
</g>
</svg>
SVG

Swap the product image path with xmlstarlet:

bash
xmlstarlet ed \
-N svg="http://www.w3.org/2000/svg" \
-u "/svg:svg/svg:g[@id='product']/svg:image[@id='product_img']/@href" \
-v "assets/shoes-green.png" \
campaign/template.svg > campaign/work.svg

Change the headline text:

bash
xmlstarlet ed \
-N svg="http://www.w3.org/2000/svg" \
-u "/svg:svg/svg:g[@id='headline']/svg:text[@id='headline_text']" \
-v "Light, strong, ready" \
campaign/work.svg > campaign/work2.svg

Export sizes for channels

Export to common sizes. Inkscape scales the page. Keep the same layout and typography. Adjust per size later if needed.

bash
inkscape campaign/work2.svg --export-type=png --export-filename=campaign/build/instagram.png -w 1080 -h 1080
inkscape campaign/work2.svg --export-type=png --export-filename=campaign/build/story.png -w 1080 -h 1920
inkscape campaign/work2.svg --export-type=png --export-filename=campaign/build/linkedin.png -w 1200 -h 627
inkscape campaign/work2.svg --export-type=png --export-filename=campaign/build/ad_square.png -w 1200 -h 1200

Quick check with ImageMagick:

bash
magick identify -format "%f %wx%h\n" campaign/build/*.png

Generate the product visual with ComfyUI

Use ComfyUI to create campaign/assets/shoes-green.png. Open http://127.0.0.1:8188, load a basic SDXL Turbo text-to-image workflow, prompt your product scene, and set output to campaign/assets/. When you want to change only the product, re-generate that file. The SVG keeps your headline, logo, and CTA untouched.

Optional REST call example after you save a workflow as workflow_api.json from ComfyUI:

bash
curl -X POST http://127.0.0.1:8188/prompt \
-H 'Content-Type: application/json' \
-d @workflow_api.json

Batch a whole week

Prepare a CSV with headline and product image per post.

bash
cat > campaign/batch.csv <<'CSV'
headline,product
Sunrise drop,assets/shoes-sun.png
Midweek restock,assets/shoes-blue.png
Final hours,assets/shoes-red.png
CSV

Run a tiny bash loop that edits the SVG and exports four sizes per row.

bash
while IFS=, read -r headline product; do
[ "$headline" = "headline" ] && continue
xmlstarlet ed -N svg="http://www.w3.org/2000/svg" \
-u "/svg:svg/svg:g[@id='product']/svg:image[@id='product_img']/@href" -v "$product" \
-u "/svg:svg/svg:g[@id='headline']/svg:text[@id='headline_text']" -v "$headline" \
campaign/template.svg > campaign/tmp.svg
base=$(echo "$headline" | tr ' ' '_' | tr -dc 'A-Za-z0-9_')
inkscape campaign/tmp.svg --export-type=png --export-filename=campaign/build/${base}_ig.png -w 1080 -h 1080
inkscape campaign/tmp.svg --export-type=png --export-filename=campaign/build/${base}_story.png -w 1080 -h 1920
inkscape campaign/tmp.svg --export-type=png --export-filename=campaign/build/${base}_li.png -w 1200 -h 627
inkscape campaign/tmp.svg --export-type=png --export-filename=campaign/build/${base}_ad.png -w 1200 -h 1200
echo "Built $headline"
done < campaign/batch.csv

Configuration tips

  • Fonts: install your brand fonts on the OS so Inkscape can use them. Keep font-family in the SVG to exact font names. If you package the project, also export a PDF with text as text, not paths.
  • Color: keep a swatches layer or use fill and stroke styles by id. Update palette by running one xmlstarlet command across ids.
  • Safe areas: draw invisible guides as rects for each channel. Keep text inside them. Toggle visibility per export if needed.
  • Multi-page: if you prefer real artboards, make pages in Inkscape 1.2+. Then export with --export-page="Instagram", --export-page="Story" per label.
  • Non-destructive product swaps: keep product as a linked image. Never embed. This keeps the SVG small and fast to edit with xmlstarlet.

Troubleshooting

  • Inkscape “Unknown option --export-page”: You are on an older version. Update to Inkscape 1.2 or later. Use --export-type=png -w -h as a fallback.
  • xmlstarlet edits do nothing: Your SVG has namespaces. Include -N svg="http://www.w3.org/2000/svg" and target ids with full XPath like shown above.
  • ComfyUI starts but no images generate: You did not place a checkpoint in models/checkpoints. Download SDXL Turbo or another model and place the .safetensors file there. Restart ComfyUI.

When it beats Canva

  • You only want to swap one layer without re-rendering the whole design. The SVG keeps text and logo pristine and you just refresh the product layer.
  • You need full control of fonts, exports, and file naming. The CLI gives you exact sizes and repeatable filenames for asset delivery.
  • You want a consistent campaign across Instagram, Stories, LinkedIn, and ads. One template, four export commands.
  • You work offline or with sensitive assets. Everything runs locally.
  • You need batch output. The CSV loop builds a week of creatives in one pass.

Sources

Want a hand?

Book a 30-min call.

Walk through your stack with us. We'll find the bottleneck and map out the exact wiring you need — free.

Book the callFree intro · 30 min · cal.com
Nano Flow

© 2026 Nano Flow. All rights reserved.