Circular logo badge via SVG Canvas

Composed logo demonstrating Engine.createSVGCanvas at its most practical: radial-gradient disc background, accent ring, tick-mark wreath, chevron crest, and dual-font text (Inter + JetBrains Mono). Output is real SVG — copy-paste into Figma / Illustrator / the web at any size without re-rasterising.

Badge
Badge — Circular logo badge via SVG Canvas
JavaScript
// Circular badge / logo composed into an SVGCanvas — gradients,
// concentric rings, a tick-mark wreath and centred text. Showcases
// the typical "build a logo in code" use case where SVG output is
// the natural target (scales cleanly, copies into Figma / web).
// demo_svg_badge.js
//!NOIMAGE
//!OUTPUT: OUTPUT
//!PARAM: SIZE:integer=600,min=200,max=1600
//!PARAM: TITLE:string=OPTICSCRIPT
//!PARAM: TAGLINE:string=vector engine
//!PARAM: ACCENT:string=#e94560
//!PARAM: TICKS:integer=48,min=12,max=120

const svg = Engine.createSVGCanvas(SIZE, SIZE);
const cx = SIZE / 2, cy = SIZE / 2;
const R = SIZE * 0.45;

// 1) Background — radial gradient disc
svg.radialGradient(px(cx, cy * 0.85), R * 1.2,
  ["#1e293b", "#0b1220"], [0, 1]);
svg.drawPath(Engine.createPath().rect(0, 0, SIZE, SIZE));

// 2) Outer accent ring
svg.pen(ACCENT, SIZE * 0.012)
   .drawPath(Engine.createPath().circle(cx, cy, R), true);

// 3) Tick-mark wreath — N radial ticks just inside the ring
const tickPath = Engine.createPath();
const tickOuter = R - SIZE * 0.025;
const tickInner = R - SIZE * 0.06;
for (let i = 0; i < TICKS; i++) {
  const a = (i / TICKS) * 2 * Math.PI - Math.PI / 2;
  const x1 = cx + Math.cos(a) * tickInner;
  const y1 = cy + Math.sin(a) * tickInner;
  const x2 = cx + Math.cos(a) * tickOuter;
  const y2 = cy + Math.sin(a) * tickOuter;
  tickPath.moveTo(x1, y1).lineTo(x2, y2);
}
svg.pen([0.91, 0.27, 0.38, 0.55], SIZE * 0.004).drawPath(tickPath, true);

// 4) Inner badge field — filled disc with subtle gradient
svg.radialGradient(px(cx, cy - R * 0.15), R * 0.9,
  ["#334155", "#0f172a"], [0, 1]);
svg.drawPath(Engine.createPath().circle(cx, cy, R * 0.72));

// 5) Crest mark — three stacked chevrons (looks like ^^^)
const chevW = R * 0.4, chevH = R * 0.10, chevGap = R * 0.07;
svg.save().translate(cx, cy - R * 0.05);
for (let i = 0; i < 3; i++) {
  const yy = -chevGap * (i - 1);
  const chev = Engine.createPath()
    .moveTo(-chevW / 2, yy + chevH)
    .lineTo(0, yy)
    .lineTo(chevW / 2, yy + chevH);
  svg.pen(ACCENT, SIZE * 0.010 - i * SIZE * 0.002).drawPath(chev, true);
}
svg.restore();

// 6) Title + tagline
svg.drawText(TITLE, cx, cy + R * 0.32, {
  font: "Inter", size: SIZE * 0.075, color: "#ffffff", anchor: "middle",
});
svg.drawText(TAGLINE, cx, cy + R * 0.50, {
  font: "JetBrains Mono", size: SIZE * 0.030, color: "#94a3b8", anchor: "middle",
});

// 7) Established-year ribbon at the bottom of the inner field
svg.drawText("· EST. 2026 ·", cx, cy + R * 0.62, {
  font: "JetBrains Mono", size: SIZE * 0.022, color: ACCENT, anchor: "middle",
});

// Serialise + rasterise for preview
const out = svg.toString();
const img = Engine.loadSVG(out, 1.0);
Engine.saveImage(img, "OUTPUT");

`badge ${SIZE}px · ${out.length} chars SVG`;

// © 2026 Michael Lechner · mlc OpticScript · https://mlcgo.eu · Elastic License 2.0