Images & Assets
Add images, videos, and static assets to your HolyDocs documentation with automatic optimization.
Overview
HolyDocs supports images, videos, and static assets as first-class content. Images are served through the /_assets/ endpoint with automatic optimization, and the build pipeline validates all asset references to catch broken links before deployment.
Need to embed a live capture of a webpage rather than a static file? Use the <Screenshot> component. It renders device-framed, gradient-backed screenshots from any URL at build time and caches the result on the CDN — no manual PNG uploads required.
Image Syntax
Use standard Markdown syntax or HTML <img> tags in your MDX files:
mdx
mdx<img src="/images/dashboard.png" alt="Screenshot of the dashboard" />
Both approaches are equivalent. The Markdown syntax is shorter, while the HTML tag gives you access to additional attributes like width, height, and className.
Always include descriptive alt text for accessibility. Screen readers and search engines rely on alt text to understand image content. Avoid generic text like "image" or "screenshot."
Image Paths
Image paths starting with / are resolved relative to your docs root directory and served via the /_assets/ endpoint at build time.
textdocs/ docs.json introduction.mdx images/ logo-light.svg logo-dark.svg dashboard.png guides/ setup-step-1.png setup-step-2.png
Reference images from any MDX file using their path from the docs root:
mdx
You can also use absolute URLs for externally hosted images:
mdx
Supported Formats
| Format | Extension | Best For |
|---|---|---|
| PNG | .png | Screenshots, diagrams, images with transparency |
| JPEG | .jpg, .jpeg | Photographs, complex images where file size matters |
| SVG | .svg | Logos, icons, diagrams that need to scale cleanly |
| WebP | .webp | Modern format with superior compression for photos and graphics |
| GIF | .gif | Short animations, simple visual demos |
Prefer SVG for logos and line-art diagrams — they scale perfectly at any resolution and are typically smaller than raster equivalents. Use WebP over PNG or JPEG when browser support is not a concern (all modern browsers support WebP).
Image Sizing
Control image dimensions using HTML attributes:
mdx<img src="/images/logo.svg" alt="HolyDocs logo" width={200} />
mdx<img src="/images/architecture.png" alt="System architecture diagram" width={600} height={400}/>
For responsive behavior, combine with CSS utility classes:
mdx<img src="/images/banner.png" alt="Feature banner" className="w-full max-w-2xl mx-auto rounded-lg"/>
Image Alignment
Center an image using wrapper utilities:
mdx<div className="flex justify-center"> <img src="/images/diagram.svg" alt="Flow diagram" width={500} /></div>
Place images side-by-side using a grid:
mdx<div className="grid grid-cols-2 gap-4"> <img src="/images/before.png" alt="Before redesign" /> <img src="/images/after.png" alt="After redesign" /></div>
Light and Dark Mode Images
Documentation often needs different image variants for light and dark modes — diagrams with white backgrounds look wrong on a dark page, and vice versa.
Using the picture Element
The <picture> element lets the browser select the right image based on the user's color scheme preference:
mdx<picture> <source media="(prefers-color-scheme: dark)" srcSet="/images/diagram-dark.png" /> <img src="/images/diagram-light.png" alt="Architecture diagram" /></picture>
Using CSS Classes
Alternatively, use CSS utility classes to show and hide images based on the active theme:
mdx<img src="/images/diagram-light.png" alt="Architecture diagram" className="block dark:hidden" /><img src="/images/diagram-dark.png" alt="Architecture diagram" className="hidden dark:block" />
When using the CSS approach, both images are loaded but only one is visible. The <picture> element is more efficient because the browser only downloads the matching source. For large images, prefer <picture>.
Logo Configuration
Configure your site logo in docs.json with separate variants for light and dark modes:
json{ "logo": { "light": "/images/logo-light.svg", "dark": "/images/logo-dark.svg" }}
If both modes use the same logo, provide a single string:
json{ "logo": "/images/logo.svg"}
The logo appears in the top-left corner of the navigation header. HolyDocs automatically switches between variants based on the active theme.
Logo Sizing
Logos are displayed at a maximum height of 28px in the header. For best results:
- Use SVG format for crisp rendering at any display density
- Design your logo to be legible at small sizes
- Keep the aspect ratio reasonable (wide logos up to ~160px wide work well)
Favicon Configuration
Set your site favicon in docs.json:
json{ "favicon": "/images/favicon.svg"}
For separate light and dark mode favicons:
json{ "favicon": { "light": "/images/favicon-light.svg", "dark": "/images/favicon-dark.svg" }}
SVG favicons are recommended because they scale to any size and support prefers-color-scheme media queries for automatic light/dark switching within a single file.
Videos
YouTube
Embed a YouTube video using a standard iframe:
mdx<iframe width="100%" height="400" src="https://www.youtube.com/embed/VIDEO_ID" title="Video title" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen/>
Vimeo
Embed a Vimeo video:
mdx<iframe width="100%" height="400" src="https://player.vimeo.com/video/VIDEO_ID" title="Video title" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen/>
Self-Hosted Video
For short video clips and screen recordings, use the <video> element with a file in your images directory:
mdx<video src="/images/demo.mp4" controls width="100%" className="rounded-lg border"> Your browser does not support the video element.</video>
Responsive Video Wrapper
Wrap video embeds in a responsive container to maintain aspect ratio across screen sizes:
mdx<div className="relative w-full" style={{ paddingBottom: '56.25%' }}> <iframe className="absolute inset-0 w-full h-full rounded-lg" src="https://www.youtube.com/embed/VIDEO_ID" title="Getting started with HolyDocs" frameBorder="0" allowFullScreen /></div>
Static Assets Directory
Organize your static assets in a consistent directory structure:
textdocs/ images/ logo-light.svg logo-dark.svg favicon.svg og/ default.png getting-started.png guides/ setup-step-1.png setup-step-2.png screenshots/ dashboard.png editor.png
All files in the images/ directory are included in the build output and served at /_assets/images/. Other asset directories work the same way — any file referenced from MDX is bundled automatically.
File Size Best Practices
Compress PNG and JPEG files using tools like ImageOptim, TinyPNG, or Squoosh before adding them to your repository. A 2MB screenshot can often be reduced to 200KB without visible quality loss.
SVG for logos and simple diagrams. WebP or JPEG for photographs and complex graphics. PNG for screenshots that need pixel-perfect clarity or transparency. GIF only for simple animations under 500KB.
Always provide width and height attributes on images. This prevents layout shift (CLS) during page load, which impacts both user experience and Core Web Vitals scores.
Aim for no more than 3-4 images per page, with each image under 500KB. If a page requires many screenshots (e.g., a step-by-step guide), consider lazy-loading images below the fold.
Name files descriptively: dashboard-overview.png is better than IMG_4023.png. Good filenames improve SEO, make the codebase navigable, and help when reviewing pull requests.