See it as a diagram
Everything below, as a diagram you can edit. Describe yours and see it in seconds.
No account needed · Editable canvas, not a picture
Two image paths, one of which freezes at build time
Path one is the optimized one. You import a file from src/assets, hand it to the Image component from astro:assets, and Astro processes it during the build: resized, format-converted, given a content hash, emitted as a static file. Everything about that image is decided at build time, so it changes when you rebuild and never in between.
Path two is plain markdown with a remote address. Astro leaves the URL in the img tag and does no processing, because there is nothing local to process. The reader browser fetches it on page load, which means the picture can change without a rebuild, a commit or a deploy.
A docs site that rebuilds on every merge makes path one look harmless. It is not: the rebuild only refreshes the picture if somebody first regenerated the file and committed it, and that is the step teams skip. The remote URL removes the step rather than automating it.
--- title: Platform architecture ---  <!-- Wider render for a full-width docs column --> 
The three remote-image traps
The first trap is using the Image component with a remote src. Astro needs intrinsic dimensions it cannot infer without downloading the file, so a remote source requires explicit width and height, or inferSize set to true, or the inferRemoteSize() helper from astro:assets. Leave all three out and the build fails rather than the page breaking quietly, which at least tells you immediately.
The second trap is configuring image.domains or image.remotePatterns in astro.config for the diagram host. That flag exists to let Astro optimize remote images, and optimization means downloading and processing them at build time. Turning it on for your diagram host is precisely how you turn a live picture back into a build artifact. Leave the host out of that list.
The third is a Content Security Policy on the docs host with img-src set to self. The markdown is fine, the URL is fine, and the reader browser refuses the request. If the diagram shows as a broken image only on the deployed site and not in dev, check the response headers before checking anything else.
Raw HTML, MDX components, and the interactive view
Astro does not sanitize the HTML in your markdown, because your markdown is source code you control rather than user input. An iframe written in a .md or .mdx page reaches the rendered output as written. Point it at the interactive diagram page and readers get pan and zoom, which is worth having when the diagram has forty nodes and a docs column has 800 pixels.
In MDX, Starlight components compose around it: put the frame inside a Card, or a Tabs set with one tab per environment. Starlight also renders components in Markdoc through its Markdoc preset, if that is the authoring flavour your team picked.
The framing side is settled: the embed page is served with frame-ancestors allowing any parent, so nothing on the Datadef side refuses the frame. A site that sends its own frame-src restrictions in CSP is the one thing that can still block it.
<iframe src="https://datadef.io/embed/my-platform-a1b2c3d4" width="100%" height="560" style="border:1px solid var(--sl-color-gray-5); border-radius:8px" title="Platform architecture" ></iframe>
Dark mode without maintaining two pictures
Starlight sets a data-theme attribute on the root element and ships a light and a dark palette. The tidy solution is two renders swapped by a CSS rule scoped to that attribute, one per theme, which means two diagrams to keep current instead of one.
The cheaper solution is one render that carries its own background. It will not match the page perfectly on both themes, and readers do not notice a diagram sitting on its own canvas the way they notice a transparent PNG with black text on a dark page. Check yours on both themes before deciding you need the pair.
Versioned docs
Keeping the docs diagram matched to the code
The remote URL removes the export-and-commit chore, not the act of updating the diagram. Connect the repository read-only from GitHub, GitLab or Azure DevOps, pick a branch or tag, and the daily sync regenerates the diagram and an architecture.md from the source. Manual layout survives the sync, so a diagram you arranged by hand is not reshuffled overnight.
It does not read the whole repository, and it is specific about that. Selection walks the tree once, skips node_modules, dist, .next, .terraform, lockfiles and binaries, classifies what is left by how much architecture it carries, and takes files in that order until a hard budget stops it: 40 files, 250KB in total, 30KB per file, with a visible truncation marker written into anything longer. Per-class ceilings stop one loud directory from eating the budget, so under the architecture focus a repository with 300 dbt models contributes three of them and leaves room for sixteen infrastructure files. A compact summary of the top three directory levels with their file counts rides along, so the generator can see the shape of what was left out instead of assuming it does not exist.
For agent-driven docs work, the MCP server exposes repo_status and repo_refresh alongside the canvas tools, so an assistant can refresh the diagram in the same session that changed the code. See repo to diagram and agents.
FAQ
Does Astro optimize remote images in markdown?
Why does my Astro build fail on a remote image?
Can I use an iframe in a Starlight markdown page?
The image works locally but is broken on the deployed docs site. Why?
Do docs readers need an account to see the diagram?