Docs & Code Guide

Embed a diagram in Astro Starlight: remote images pass through, local imports get baked

By the engineer who builds Datadef, from client work on data platforms · Reviewed August 21, 2026

Starlight is the docs framework people move to when Docusaurus feels heavy, and it inherits the Astro asset pipeline wholesale. That pipeline draws a sharp line: assets you import are processed, hashed and written into the build output, while a remote URL in markdown is left exactly as you typed it and fetched by the reader. For an architecture diagram, that second path is the one you want, and there are three ways to accidentally end up on the first.

7 min readFor teams running documentation on Astro Starlight

See it as a diagram

Everything below, as a diagram you can edit. Describe yours and see it in seconds.

138/20003 credits left
Try:

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
---

![Platform architecture](https://datadef.io/api/embed/my-platform-a1b2c3d4)

<!-- Wider render for a full-width docs column -->
![Platform architecture](https://datadef.io/api/embed/my-platform-a1b2c3d4?width=2400&height=1400&scale=2)

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

If your Starlight site publishes a version per release, commit an exported PNG for frozen versions and keep the live URL on the current one. The exported and live pictures come from the same render, so they agree on the day you cut the version. More on that trade in diagram versioning.

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?

No, not unless you configure the host under image.domains or image.remotePatterns. A plain markdown image with an external address is left untouched and fetched by the reader browser, which is what allows the picture to change without a rebuild. Configuring the host makes Astro download and process it at build time instead.

Why does my Astro build fail on a remote image?

The Image component from astro:assets requires width and height for a remote source, because it cannot infer the dimensions without downloading the file. Supply both, use inferSize, or drop back to plain markdown image syntax or an img tag for remote sources.

Can I use an iframe in a Starlight markdown page?

Yes. Astro passes raw HTML in markdown through to the output without sanitizing it, so an iframe renders in .md and .mdx alike. It is the right choice for a large diagram, since readers get pan and zoom instead of a scaled-down static image.

The image works locally but is broken on the deployed docs site. Why?

Check the Content Security Policy of the deployed site. A policy with img-src limited to self blocks external images regardless of what the markdown says, and the failure appears only after deployment. The same applies to frame-src for iframes. The browser console names the blocked directive directly, which is faster than re-reading the markdown looking for a typo that is not there.

Do docs readers need an account to see the diagram?

No. A publicly shared project serves both an image URL and a chrome-less interactive page that open for anyone. Publicly shared also means anyone with the address can view it, so keep confidential detail out of a diagram that sits on a public docs site.