How does Pluto decide what to show graphically?

as you’ve figured it out, just implement show(io::IO, m::MIME"image/svg+xml", c) . It’s simpley

using Compose 

struct DrawConfig
	c::Compose.Context
	width
	height
end 

import Base

function Base.show(io::IO, m::MIME"image/svg+xml", d::DrawConfig)
	backend = SVG(io, d.width, d.height)
	draw(backend, d.c)
end 

DrawConfig(compose(compose(context(), rectangle()), fill("tomato")), 4cm, 4cm)

done, and pluto just call show for you

the good thing about that is you never needs to touch svg. Until you want native interaction from browser, that you have to inject some attributes and more likely, js code script element, this could be done by combining Compose, specically draw part, with some xml package, like EzXML.jl