Osy#the first language built for agents
Agents firstAgentic appsWorkflowsDurable Execution — built inSecurityTestingThe editorThe UI modelOne program

Reference / UI

SVG assets

Svg(Art.Hexgrid) — a named SVG asset, rendered inline with its own colours

Drop a `.svg` into `model/art/` and render it with `Svg(Art.Hexgrid)`. Unlike an icon, an asset keeps its own colours, gradients and patterns — it is the illustration, background or multi-colour logo counterpart to the single-colour `Icon`. The name is checked at compile time, and the asset is placed with ordinary style props.

stable2 examples compiled by CIuiassetssvg

Summary#

An SVG asset is a file in your app, not data. Put a .svg in model/art/ and it becomes part of your app's vocabulary:

model/
  art/
    hexgrid.svg
    hero.svg
    logo-full.svg
[Composable]
component Splash() {
  render {
    Box(position: Position.Relative, minH: "100vh") {
      Svg(Art.Hexgrid, position: Position.Absolute, inset: 0, z: "-1");   // a full-bleed background
      Text("Welcome");
    }
  }
}

This compiles against the drop-ship-order sample, whose art/ folder really does contain hexgrid.svg — the name is checked against the files the app ships.

Adding an asset is dropping a file in. There is nothing to register and nothing to import.

Signature#

Svg(Art.Hexgrid) · Svg(Art.Hexgrid, position: Position.Absolute, inset: 0) — a named SVG asset, placed with style props

Description#

Asset or icon?#

Reach for an asset when the artwork carries its own colours — an illustration, a background pattern, a hero image, a full-colour logo. Reach for an icon when it's a single-colour glyph that should follow the surrounding text colour.

Icon(name)Svg(name)
Lives inmodel/icons/model/art/
Colourrecoloured to the current text colourits own colours, gradients, <pattern>s
Sizingan em square (size:)placed with style props (w:/h:/position:/…)
ForUI glyphsillustrations, backgrounds, multi-colour logos

The name is checked#

Svg(Art.Hexgrid) names the asset by a bare identifier, checked against the assets your app actually declares. A typo is a compile error with a suggestion:

unknown SVG asset 'hexgrd' (declared assets: hero, hexgrid, logo). Did you mean 'hexgrid'?

Because the name is an identifier, an asset's file name must be one toologo_full.svg, not logo-full.svg. A kebab-case file is rejected with the rename to make.

The name is never an expression. A local variable called hexgrid does not change what Svg(Art.Hexgrid) means — the asset vocabulary always wins. An asset chosen at runtime is a content concern, not chrome: use Image(src) for that.

Sizing and placing an asset — ordinary style props#

An asset keeps its own colours, so there is no size:/color:. Instead it takes the ordinary style props, so you place it like any other element — a sized inline logo, or a full-bleed background behind a card:

[Composable]
component Wordmark() {
  render { Svg(Art.LogoFull, w: 140); }            // an inline, fixed-width logo
}

[Composable]
component Patterned() {
  render {
    Box(position: Position.Relative) {
      Svg(Art.Hexgrid, position: Position.Absolute, inset: 0, z: "-1");   // tiles behind the box's content
      Slot;
    }
  }
}

By default an asset fills the box you give it, so a full-bleed background is position: Position.Absolute; inset: 0 on a position: Position.Relative parent, and a fixed-size asset is just w:/h:. Anything other than the asset name and style props is a compile error.

What an asset may contain#

An asset is drawing: shapes, groups, and the paint machinery that gives it colour — linearGradient, radialGradient, pattern, clipPath, mask, and a <defs> block, with in-document fill="url(#…)" references to them. Its colours are kept exactly as drawn.

Anything that could run, load, or reach outside the file is a compile error, naming the file:

'evil.svg' contains a <script> element — scripting, styling, embedding, external
references and animation are not allowed in an SVG asset.

That covers <script>, <style>, <image>, <use>, <a>, animation elements, any on… handler, and any URL that leaves the document — an external or data: image, a javascript: link, a url(https://…). A url(#id) that points inside the same asset (a gradient or pattern fill) is fine; each asset's ids are kept separate, so two assets that happen to use the same id never collide. An SVG is a place scripts can hide, and your assets are placed directly into your pages — so the rule is an allow-list, and it is not negotiable.

Assets from a UI kit#

A kit's assets land in your app tree alongside your own and are picked up the same way. Two files claiming the same name is an error naming both, so an asset always resolves to exactly one file.

How assets are delivered — inline, on the first byte#

A server-rendered page paints its assets inline on the very first byte — no request, no flash. Change an asset and the delivered copy changes with it; leave it alone and browsers keep the copy they already have.

Custom glob, if model/art/ doesn't suit you:

app Admin {
  model "model/**/*.osy";
  svg "assets/art/*.svg";
}

Passing an asset around — Art is a type#

Art is a type, so an SVG asset can be a component parameter, a return value or a stored field:

[Composable]
component Badge(string label, Art art) {
  render {
    Stack {
      Svg(art, w: 120);
      Text(label);
    }
  }
}

// at the call site
Badge("Grid", Art.Hexgrid);

The vocabulary is built from the files themselves, so there is nothing to declare — and an app that ships no model/art/ files simply has no Art type yet, which the compiler says in those words.

See also#

  • icons — the single-colour glyph counterpart, recoloured to the current text colour.
  • style props — the position/inset/w/h props that place an asset.
  • theme tokens — the tokens the surrounding layout resolves against.

Related

icons

Drop `.svg` files into `model/icons/` and render them with `Icon(Icons.Search)`. The name is checked at compile time…

style props

Inside a `variants` block, each `Name = value` is a style prop from a fixed vocabulary the renderer maps to CSS — paint…

theme tokens

A `theme` block names your app's design tokens — colors, spacing, radii, and more — as reusable values. A token can…

layout primitives

The built-in layout primitives and how they arrange children. `Stack` stacks children in a column, `Row` lays them in a…