# Design handoff: SFMA post set, and the spec for a real design agent Written November 4, 2026, after the first automated pass and Pablo's manual Canva redesign of the same posts. Purpose of this document: record what was built, name honestly why the automated output was not publishable, extract the design vocabulary from the versions that were, and specify the workflow that would close the gap. --- ## 0. The objective **Pablo's goal, in his words:** a proper design workflow that produces "almost perfect to publish" images for Instagram and the other social channels, run by a dedicated design agent or skill, so that posts do not have to be rebuilt by hand in Canva. The immediate trigger was the SFMA Manufacturing Expo on November 5, 2026. The deadline was the same day the work started. Under that pressure the automated pass produced correct but visually flat output, and Pablo rebuilt all five pieces manually in Canva to ship them. That gap between "correct" and "publishable" is the thing this document exists to close. ### Success criteria 1. Output is publishable without a manual Canva pass. 2. The look matches the brand's existing house style, which is documented in section 3 and exemplified by `assets/carousel-standar-bots-*.png`. 3. Text stays live and editable, never outlined, in the brand fonts. 4. Every factual claim traces to `00_SOURCE_FACTS.md`. 5. The whole set regenerates from one command when copy changes. --- ## 0b. How we got here, session log The steps taken on November 4, 2026, in order. Recorded so the next person does not repeat the dead ends. | # | Step | Outcome | |---|---|---| | 1 | Read the brief: 6 pieces to cover the Nov 5 expo, built from Canva SVG templates in `Desktop/WORK2023/Factronics/Nov 2026 Posts` | Scope set | | 2 | Checked the event date, flagged in the brief as possibly Nov 6 | **Resolved: Nov 5.** Confirmed twice in `00_SOURCE_FACTS.md`, sources S1 and S4. Nov 6 is the thank you post day | | 3 | Inspected the 100+ Canva SVG templates | **Dead end.** Zero `` elements, up to 1,425 paths each. Canva had outlined all text, which is unrecoverable. Also wrong aspect (4:5 July posts in Spanish) | | 4 | Confirmed VectorCraft installed, found `vectorcraft-cli.exe` with an MCP server and a headless `run --commands` batch mode | Tooling chosen | | 5 | Verified brand fonts installed: Inter, Poppins, Sarala, JetBrains Mono | All present | | 6 | Probed the VectorCraft coordinate model with a throwaway canvas | y runs down from top left; a text object's `y` is its baseline. Rectangles default to a 1 px black stroke, so `paint.setStroke {none:true}` is required after every rect | | 7 | Rendered two templates to PNG to read the house style | Logo top left, full bleed photo, big white headline, blue panel with lime highlight | | 8 | Found the brief's Standard Bots slide was an undocumented claim | Built carousel slide 3 on documented facts instead, and flagged it rather than inventing | | 9 | Wrote `build.py`, generated 9 canvases, 3 tuning passes on layout | 9/9 built, live text verified, JPGs all under the 250 KB cap | | 10 | Pablo reviewed | **Rejected as too symmetric, lacking texture and graphic design.** Rebuilt by hand in Canva | | 11 | Measured Pablo's versions pixel by pixel | Palette hierarchy was inverted, halftone texture missing, lime at 0.2 percent instead of 6.6. See section 2 | | 12 | Standard Bots relationship confirmed by Pablo | Recorded in `00_SOURCE_FACTS.md`, `image_brief.md` section 3 restriction cleared, naming resolved | | 13 | Attempted to connect the Canva MCP connector | **404.** Diagnosed as a wrong path in the connector registration, not a Canva outage. See section 5b | ### Dead ends worth not repeating - **Do not try to recover text from Canva SVG exports.** The glyph paths carry no character data. Converting outlines back to text is not possible. Only a rebuild gives live text. - **Do not treat "no photo in the repository" as "no photography exists."** This caused the central failure. See section 2, root cause. - **Do not use the bare `https://mcp.canva.com` host.** It 404s. The path is `/mcp`. --- ## 1. What was built on November 4 Nine canvases, generated programmatically with VectorCraft, from `assets/Z_archived/build.py`. Current folder layout, after Pablo archived the generated set: ``` assets/ carousel-standar-bots-1..4.png the versions that shipped, hand built in Canva see-you-at-sfma.png ditto source/ AI, SVG and PDF of the generated set, live text Z_archived/ the generated set, plus build.py and its README ``` | Group | Files | Size | |---|---|---| | Announcement | `sfma-booth26-{linkedin,facebook,instagram,email-header}` | 1200x627, 1200x630, 1080x1080, 1200x400 | | Carousel | `sfma-carousel-1` to `-4` | 1080x1350 | | Post event | `sfma-thankyou` | 1080x1350 | Each exported as JPG and PNG (now in `assets/Z_archived/`), and as AI, SVG and PDF in `assets/source/`, all three with live editable text. ### Method `build.py` declares each canvas as an ordered list of VectorCraft commands (`file.new`, `shape.rectangle`, `paint.setFill`, `text.create`, `text.setStyle`, `file.place`) and runs them headless through `vectorcraft-cli.exe run --commands`. One script regenerates every format. ### What is genuinely reusable - The VectorCraft command pipeline. Headless, deterministic, versionable, and it emits live text in real brand fonts rather than outlines. - The fact discipline. Every string traced to `00_SOURCE_FACTS.md`. - The export matrix. Correct dimensions, sRGB, all JPGs under the 250 KB cap. - Coordinate model, now established: y runs down from the top left, and a text object's `y` is its baseline. ### What should be thrown away The layouts themselves. Keep the plumbing, discard the compositions. --- ## 2. The gap, named Pablo rebuilt all five pieces by hand in Canva. Those files are `assets/carousel-standar-bots-1.png` to `-4.png` and `assets/see-you-at-sfma.png`. Comparing them against the generated set, the automated output failed on eight specific counts. None of them are about file format. | # | Generated output | Manual redesign | |---|---|---| | 1 | Flat navy field, no texture | Blue field with a fine navy halftone dot screen across the whole canvas | | 2 | Navy `#00337A` dominant, blue used only for small panels | Blue `#0D70CC` dominant at 84 percent of the canvas, navy demoted to the dot screen and to type on lime | | 3 | Lime restricted to one 6 px rule, roughly 0.2 percent of pixels | Lime at 6.6 percent: filled headline words, outline headline words, pill buttons, hand drawn marks | | 4 | No imagery at all | Knocked out robot photography bleeding off the left and bottom edges, plus full bleed duotone photography | | 5 | One geometric accent, a rectangle | Hand drawn marker marks: an ellipse lassoing "you at", brush stroke underlines with visible bristle texture | | 6 | One uniform type treatment per headline | Three treatments inside a single headline: white fill, lime fill, and lime outline with no fill | | 7 | Every element on a single left axis at x=90, even vertical rhythm | Staggered line indents, plates that bleed off canvas, type overlapping photography, deliberate asymmetry | | 8 | Partner logos omitted as "risky on navy" | Solved properly: dark partner logo placed inside a white rounded chip | Item 8 is the clearest tell. The problem was a solved problem, and the automated pass dropped the content rather than solving it. ### Root cause `image_brief.md` section 2 says: no confirmed product photo exists, so use a typographic layout. That was read as a specification when it was a floor. The correct response was to build the typographic layout *and* say plainly that a flat card is the minimum viable artifact, then ask what photography exists. Standard Bots robot imagery was available the whole time, in Canva. Second cause: the composition was driven by a margin constant and a vertical cursor. A layout engine built that way produces even spacing on one axis by construction. It cannot produce asymmetry unless asymmetry is an explicit rule, and there was no such rule. --- ## 3. The design vocabulary, extracted and measured Measured from the manual redesigns, not estimated. ### Field and palette hierarchy ``` Field #0D70CC brand blue, 84% of canvas <- the ground Halftone dots #0757AB approx 4.5 px pitch, 1.7% coverage, approx 1 px dots Accent #C7D759 lime, target 5 to 7% of pixels Type #FFFFFF white, and #00337A navy on lime Navy #00337A NOT the ground. Dots, and type on lime only. ``` The single highest impact change: swap the ground from navy to blue, and lay the navy halftone over it. That one move accounts for most of the perceived difference in texture. ### Components to build as a library 1. **Halftone overlay.** Navy dot screen, approximately 4.5 px pitch, 1.7 percent coverage, over the full canvas. Subtle enough to read as paper grain. 2. **Hand drawn marks.** The lime lasso ellipse, and at least two brush underline strokes with visible bristle gaps. These are irregular vector shapes and must be extracted as real paths. They cannot be synthesised convincingly from primitives. 3. **Lime pill button.** Fully rounded, solid `#C7D759`, navy bold label. Used for "Live Robot Demo" and "Live Demo". 4. **White logo chip.** White rounded rectangle, generous padding, containing a dark partner logo. This is the standard answer for Standard Bots and Linx on a blue field. 5. **Blue callout card.** Rounded blue card, bold white title, regular white body, optional bevelled lime icon at the left. 6. **White headline plate.** White rounded plate behind a headline line, deliberately bleeding off the canvas edge. 7. **Outline type style.** Lime stroke, no fill, used on one line of a headline for contrast against filled lines. 8. **Knockout product cutout.** Transparent PNG of the robot, scaled large, cropped by the canvas edge. ### Composition rules - Logo sits top centre, not bottom left. - A headline mixes at least two of: white fill, lime fill, lime outline. - At least one element bleeds off a canvas edge on every slide. - At least one hand drawn mark per slide, never more than two. - Three depth layers minimum: textured ground, photography or cutout, then type and plates. - Do not place every block on one x axis. Stagger headline line indents. - Lime target is 5 to 7 percent of pixels. Below 2 percent the design reads dead. --- ## 4. What to export from Canva, and why The question was whether PNG, PDF, SVG or PPTX would have let the first pass replicate the templates. Answer: export all four, because they do different jobs, but none of them is the thing that actually matters most. | Format | What it is actually good for | Caveat | |---|---|---| | **PNG** | The highest value export. It is the only one a vision model reads directly, so it is what makes a critique loop possible: render, look, compare, revise. | Carries no structure. | | **PPTX** | The most machine readable layout description of the four. A .pptx is a ZIP of XML: text stays live, every element has explicit coordinates, and images extract cleanly from `ppt/media/`. Best source for exact geometry. | Canva flattens some effects into images. | | **PDF (Print)** | Best single archival format. Keeps live text more reliably than Canva's SVG, embeds images at full resolution. | Layer structure is flattened. | | **SVG** | Useful, but **not** for the text. Canva outlines text on SVG export and that is unrecoverable. It is valuable for the opposite reason: it preserves the **decorative vector shapes** as real paths. | Text is dead on arrival. | The important correction: outlined text is useless, but outlined *ornament* is exactly what is wanted. The lime lasso and the brush underlines only need to exist as paths, and SVG delivers those perfectly. ### What matters more than any export format Raw ingredients, not flattened compositions. Four things, and these unblock far more than the templates do: 1. **Transparent PNGs of the robot**, several angles, 2000 px plus. 2. **The halftone tile**, or just the confirmation that it is a 4.5 px navy dot screen, which the measurement above already gives. 3. **The hand drawn lime marks as SVG**, ellipse and underlines, isolated. 4. **Partner logos** in both dark and white versions. With those four in `02_brand_kit/`, the agent composes new layouts instead of copying old ones. Without them it will keep producing flat type cards no matter how many templates it is shown. --- ## 5. Proposed workflow The failure was design quality, not tooling. So the architecture has to make quality checkable, not just make files. ### Stage 1. Asset pipeline, runs before any design work Populate `02_brand_kit/`: ``` 02_brand_kit/ textures/ halftone-navy.svg, halftone-navy@2x.png marks/ lasso-ellipse.svg, underline-brush-1.svg, underline-brush-2.svg cutouts/ standardbots-ro1-{a,b,c}.png transparent, 2000 px plus partner_logos/ existing, plus white variants components/ pill.json, logo-chip.json, callout-card.json, headline-plate.json ``` Gate: if a brief needs photography that does not exist, the agent says so and asks, rather than silently falling back to a type only card. ### Stage 2. Design engine Recommendation: **HTML and CSS rendered headless, then a VectorCraft pass for vector delivery.** Reasoning. CSS gives the vocabulary that was missing, directly and cheaply: repeating gradients for the halftone, `background-clip` and `-webkit-text-stroke` for outline type, blend modes for duotone, transforms and negative offsets for bleed, real shadows. Iteration is seconds. VectorCraft can then rebuild the approved composition as live text for the editable AI, SVG and PDF, which is what `build.py` already does well. Keep VectorCraft as the delivery format. Do not use it as the design surface. It is precise but it encourages the grid thinking that produced the symmetric output. ### Stage 3. Critique loop, the part that was missing This is the actual fix. After rendering, the agent reads its own PNG back and scores it against a rubric before showing anything: 1. Is the ground textured, or flat? 2. Is lime between 5 and 7 percent of pixels? (measurable, not subjective) 3. Does at least one element bleed off an edge? 4. Does the headline use two or more type treatments? 5. Are there three distinct depth layers? 6. Is there exactly one or two hand drawn marks? 7. Is every block on the same x axis? If yes, fail. 8. Side by side against a reference from `assets/`: does it look like the same brand made both? Checks 2 and 7 are computable. The rest are read from the rendered image. Minimum two revision passes before anything is presented. ### Stage 4. Delivery Unchanged from what already works: JPG for upload under 250 KB, plus AI, SVG and PDF with live text, plus a README naming which caption goes with which file. ### Where the skill should live Per repo convention in `CLAUDE.md`, stage skills live globally in `~/.config/opencode/skills/` and are named by a stage contract. The natural home is a new stage, `stages/03_post-design/`, with `CONTEXT.md` declaring inputs (brand kit, image brief, social posts, source facts) and the canonical output filenames. The rubric in stage 3 belongs in `_config/` next to `voice.md`, since it is a stable rule set rather than a per run artifact. --- ## 5b. Canva MCP, diagnosis and fix Pablo approved using the Canva MCP connector on November 4. The claude.ai connector failed with `HTTP 404 at https://mcp.canva.com`, reported as "Server not found". Probed directly: ``` https://mcp.canva.com POST -> 404 Not Found https://mcp.canva.com/mcp POST -> 401 {"error":"invalid_token"} ``` A 401 `invalid_token` means the server is alive and correctly refusing an unauthenticated request. The claude.ai connector is POSTing to the bare host and omitting the `/mcp` path. Canva is not down, and re-running `/mcp` will not help because the wrong URL is baked into the connector registration. **Fix.** Register it locally with the full path instead: ``` claude mcp add --transport http --scope user canva https://mcp.canva.com/mcp ``` Then `/mcp`, pick `canva`, and sign in to Canva in the browser. User scope makes it available across every brand folder in this repo. Also remove the broken "claude.ai Canva" connector at claude.ai/settings/connectors so there are not two competing Canva entries. **What to establish first, once connected.** The connector's advertised capability includes searching designs and folders, using brand kits and templates, editing text in existing designs, and exporting PNG and PDF. Whether it can genuinely read and repopulate the existing SFMA templates decides the architecture: - **If template read and populate works**, it replaces most of section 5. Use the real Canva designs as the engine and skip rebuilding the component library. - **If it is effectively create only**, it becomes the delivery step and the HTML and CSS surface plus the critique loop in section 5 stays the design engine. Probe this rather than assuming. Advertised capability and exposed tools are often not the same. --- ## 6. Build order 1. Extract the four asset groups from the Canva files. Highest leverage, and nothing else works well without them. 2. Write the rubric into `_config/design-rules.md`. 3. Build the HTML and CSS component library against the measured tokens in section 3. 4. Wire the render and critique loop. 5. Reconnect the VectorCraft vector delivery pass from `build.py`. 6. Promote to `stages/03_post-design/` with a `CONTEXT.md` contract. --- ## 7. Open items - ~~**Standard Bots distributor claim.**~~ **CLOSED, November 4, 2026.** Pablo confirmed the relationship is real. "Official Standard Bots Distributor in Florida" is now an approved claim string, recorded in `00_SOURCE_FACTS.md` under "Standard Bots partnership". Logo use is approved. On a blue or navy field the dark logo goes inside a white rounded chip. `image_brief.md` section 3 has been updated and no longer blocks it. - ~~**CORE robot versus Standard Bots naming.**~~ **CLOSED, November 4, 2026.** Core is a Standard Bots model, alongside Spark, Thor and Bolt, all live on factronicsusa.com. First mention in a deliverable is "Standard Bots Core", afterwards "the Core robot". - **Font conflict.** `image_brief.md` and `00_SOURCE_FACTS.md` specify Inter and Sarala. `Factronics_brand_guide.md` v1.0 specifies Poppins for display. The generated set followed the image brief. Needs a decision. - **Canva MCP connector.** Approved by Pablo, November 4. Diagnosed as a wrong path in the connector registration, not a Canva outage. Fix and next probe are in section 5b. **This is the next action.** - **Logo artifact.** `carousel-standar-bots-3.png` and `-4.png` render the wordmark as "USA,LL" rather than "USA,LLC". Worth checking the Canva source. --- ## 8. Where to pick up State as of the end of November 4, 2026. **Done.** - SFMA posts shipped. Pablo's hand built Canva versions are live on LinkedIn, Facebook and Instagram. Email blast sent. - Nine generated canvases archived in `assets/Z_archived/`, editable AI, SVG and PDF in `assets/source/`. - Design vocabulary measured and written up, sections 2 and 3. - Standard Bots relationship confirmed and recorded. Naming resolved. `image_brief.md` section 3 restriction cleared. - Canva MCP 404 diagnosed. Fix is one command, section 5b. **Next action, in order.** 1. Run the `claude mcp add` command in section 5b and authenticate Canva. 2. Probe what the connector can actually reach. This decides the architecture, so do it before building anything. 3. Export the five shipped designs from Canva as PNG, PPTX and SVG, and pull out the four raw ingredients listed in section 4. Worth doing regardless of how the connector probe turns out. 4. Then follow the build order in section 6. **Not started.** Everything in sections 5 and 6. No design agent or skill exists yet. `stages/03_post-design/` has not been created. --- ## 9. Honest summary The pipeline works. The typography is correct, the facts are correct, the exports are correct, and the text is live and editable. The design was not good enough to publish, and that is the whole point of the exercise. It was flat where it should have had texture, symmetric where it should have been composed, and it dropped content rather than solving a layout problem. Templates alone would not have fixed that. What fixes it is a component library built from real ingredients, an explicit rule set that forbids the safe layout, and a loop where the agent looks at its own output before calling it done. --- ## 10. Update, November 5, 2026: the Canva MCP pass The Canva connector works in Cowork. The section 5b probe is answered: it can read the master file (`Nov Event Post`, 103 pages, with thumbnails), copy chosen pages into a new design, import photos from public URLs, remove backgrounds, rewrite and reformat text, move, resize, layer and recolor elements, and add, delete or insert pages. That makes Pablo's Canva master the design engine (the "template read and populate works" branch of 5b). **Built through the connector** | Design | Slides | Canva | |---|---|---| | Linx 9830 carousel | 4 | https://www.canva.com/d/8VSxYrV7bk42z1f | | Linx IJ470 launch carousel | 5 | https://www.canva.com/d/WkdaSrDVoNsEveW | IJ470: 11 photos imported from linxglobal.com, 5 background cutouts, no recycled photos. Copy traced to factronicsusa.com/product/linx-ij470 and the Linx product page. **Limits found** - Text added through the API falls back to a default font; reuse existing text boxes for brand type. - `copy-design` failed when the same page number was listed twice. - `merge-designs` takes one operation per call and needs approval each time. - The only 9800 photo on factronicsusa.com/linx-cij-9830 is a 9840 (badge visible). Get a real 9830 photo. **Pablo's manual polish of the IJ470 set (saved 00:57, Nov 5)** | Slide | Changes | |---|---| | 1 New case coder | Fixed the Factronics logo (now USA,LLC) and enlarged it; scaled the conveyor up; added a Linx logo chip bottom right | | 2 Skip the label | Moved the plate and headline to the top; scaled the case up; added a Linx logo chip bottom left | | 3 Touchscreen | Moved and widened the copy block; enlarged the screen to bleed off left and bottom; lifted the bubble | | 4 Both sides | Small placement nudges only | | 5 Meet the IJ470 | Added a bold "No ink wasted:" lead-in; removed "Sold and deployed by Factronics USA." and the logo; enlarged the conveyor behind the pill | **New rules from that pass** (add to `_config/design-rules.md`) 1. Partner logo chip on every product slide, by default (component 4 was skipped again). 2. The product photo fills at least half the frame and bleeds off an edge. 3. CTA slide carries 2 body lines at most. 4. Promote Pablo's corrected USA,LLC logo into the master so copies inherit it. Full report with diagrams: `05_projects/2026-11_Catch_Up/02_Design_Agent/factronics-design-agent-report.html`