SVG Export
Why
Qpixel can currently export ANSI .txt, but there is no vector export path for web, docs, or design workflows. We also now support more than block pixels: the canvas can contain block elements, line-drawing glyphs, arrows, and free text, so SVG export needs to be defined against the real editor model rather than the original block-art-only assumption.
Objective
Ship a reliable SVG export flow that preserves crisp pixel-aligned output by default, keeps ANSI export unchanged, and creates a clear path toward smarter shape reduction without blocking the first usable release.
Scope
- Add SVG export as a first-class export option in the editor UI
- Ship block export first for block-based characters
- Define fallback behavior for non-block glyphs introduced in
c2 - Add a repeatable verification workflow for crisp, non-antialiased output
- Timebox shape export as a research/prototype track rather than a release blocker
- Defer PNG export unless it falls out naturally from the SVG pipeline
Deliverables
- Toolbar/UI support for SVG export
app/utils/svg.tsor equivalent export module- Character classification for block-geometry vs text/glyph fallback
- Block SVG export with default crisp sizing
- Rectangle-merging optimization for obvious same-color runs
- Fixture sheet and repeatable QA flow
- Short write-up on full shape export feasibility and recommended next step
Outcome Target
By the end of c4, Qpixel should have a production-usable SVG export path with crisp block rendering, safe handling of mixed-content canvases, and enough research completed to choose the right shape-merging strategy without guessing.
Execution Plan
1. Define the export contract
- Keep the current ANSI copy/export flow exactly as-is
- Introduce a dedicated SVG export utility, separate from ANSI serialization
- Standardize export sizing around SVG/CSS pixels, not physical DPI
- Default to
1SVG unit per editor cell and expose scale presets like1x,2x,4x - Export with explicit
viewBox,width,height, andshape-rendering="crispEdges"where applicable - Decide background behavior up front: transparent by default, optional solid background later if needed
2. Split canvas content into exportable categories
- Treat block-style characters as geometry-driven cells that can become vector shapes
- Treat non-block glyphs as glyph/text output, not rectangles
- Build a small classifier layer so export logic can branch by character family instead of hardcoding per feature
- Fail safely: if a character cannot be converted to geometry, export it as positioned text rather than dropping it
3. Ship block export MVP
- Add an export surface in the toolbar for
.svg - Serialize each block-capable cell into SVG primitives at cell-aligned coordinates
- Start with per-cell output for correctness and simplicity
- Support foreground color per cell
- Preserve empty cells as transparent space
- Verify that the generated SVG opens cleanly in browsers and design tools
4. Add a smarter middle step before full shape export
- Implement rectangle merging for adjacent same-color full-cell blocks as the first optimization pass
- Keep this optimization optional and lossless
- Use it to reduce SVG size without taking on full polygon union complexity
- Treat this as the likely default optimization for
c4
This is the main additional strategy worth considering: we do not need to jump directly from "one rect per cell" to "perfect merged polygons." A rectangle-merging pass gives most of the benefit with far less algorithmic risk.
5. Timebox shape export research
- Research/compare approaches for converting merged cell regions into simple orthogonal paths
- Evaluate at least these options: edge tracing around occupied cells by color, union of cell rectangles followed by contour extraction, and run-length/scanline merging as a preprocessing stage
- Produce a recommendation on whether full shape export belongs in
c4or a follow-up cycle
Success for this track is a recommendation and a small prototype, not necessarily a production-ready second export mode.
6. Build QA and verification tooling
- Create a small fixture sheet covering full blocks, partial blocks (
▀,▄,▌,▐), quadrants/diagonals, mixed colors, and mixed content with non-block glyph fallback - Add a local QA page or dev-only panel that renders the live editor preview, exported SVG inline, rasterized SVG at
1xand2x, and offset/zoom views for spotting blur or half-pixel alignment - Add lightweight pixel checks where possible by rasterizing the SVG to canvas and asserting there are no unexpected semi-transparent edge pixels in crisp modes
Do not block on AI-based visual introspection. First ship a deterministic QA sheet that makes failures obvious. If we still need an AI-assisted review step after that, it can be layered on top of saved screenshots rather than embedded in the core implementation.
7. Handle PNG as a stretch goal
- If block SVG export is stable, add PNG export by rendering the generated SVG to canvas and downloading a raster image
- Keep this out of the critical path for
c4
Success Criteria
- ANSI export still behaves exactly as before
- A user can export
.svgfrom the editor without manual post-processing - Default SVG output renders crisply at
1xand2xon the QA sheet - Non-block characters are preserved via an explicit fallback path
- We have a documented decision on whether full shape export ships now or moves to the next cycle
Open Questions
- Should SVG text/glyph fallback use the same Menlo-style preview stack, or should it be intentionally limited to broadly available monospace fonts?
- Do we want an optional solid background color in the export, or is transparent-first enough for
c4? - Is "shape export" required for cycle completion, or is a validated recommendation sufficient once block export is solid?
Visual record
7 captures — heroes, page slices, and full-page renders. Click to view.






