# Videos

Self-hosted videos use the same `![alt](url)` markdown syntax as images. Drop a `.mp4`, `.webm`, `.ogv`, `.mov`, or `.m4v` file into `media/` and reference it like any other asset:

```markdown
![Marketing video](/media/launch.mp4)
```

This renders a `<video>` element with `controls`, `playsinline`, and `preload="metadata"` — sensible defaults for marketing pages, product demos, and embedded clips.

## Sizing and shape

All the sizing and shape modifiers from [Images](/docs/images) carry over:

```markdown
![Demo](/media/demo.mp4 +width:800 +corner:curve)
```

| Modifier | What it does |
|---|---|
| `+width:N` | Caps max width at N pixels |
| `+height:N` | Sets explicit height (videos crop with `object-fit: cover`) |
| `+crop:WxH` | Fixed dimensions, cover-fit |
| `+corner:subtle` / `+corner:curve` | Rounded corners (6px / 16px) |
| `+circle` / `+square` / `+rect` | Aspect-ratio + cover-fit |
| `+bw` / `+sepia` | CSS filter effects |

## Video-only modifiers

| Modifier | What it does |
|---|---|
| `+autoplay` | Autoplays on load. Implies `muted` and `loop` (browsers block autoplay with sound). |
| `+muted` | Mutes the video by default. |
| `+loop` | Loops playback. |
| `+nocontrols` | Hides the playback controls. |
| `+poster:filename.jpg` | Shows a poster image before playback. Resolved against `/media/`. |

## Examples

Standard marketing video, full controls, capped width:

```markdown
![Product launch](/media/launch.mp4 +width:900 +corner:curve)
```

Silent looping background hero:

```markdown
![Hero loop](/media/hero-loop.mp4 +autoplay +width:1200 +corner:curve)
```

With a poster frame:

```markdown
![Demo](/media/demo.mp4 +poster:demo-poster.jpg +width:800)
```

## Layout blocks

Videos work inside `gallery:` and `image-row:` blocks too — you can mix images and videos freely:

```markdown
gallery:
  ![Screenshot one](/media/screenshot-1.jpg)
  ![Demo video](/media/demo.mp4)
  ![Screenshot two](/media/screenshot-2.jpg)
```

Lightbox/expand is image-only and is silently ignored on videos.

## Alignment

Use the standard alignment fences to center or left/right-align a video:

```markdown
center:
![Centered demo](/media/demo.mp4 +width:800 +corner:curve)
/center
```

When a centered video's width exceeds the page content column, it overhangs equally on both sides of the column rather than clipping to the left edge — handy for wide product demos inside a narrow text column.

See [Content Alignment](/docs/content-alignment) for the full alignment reference.

## Device variants

Embed a different video for desktop and mobile by wrapping each in a `desktop:` / `mobile:` fence:

```markdown
desktop:
![Wide desktop demo](/media/demo-web.mp4 +autoplay +width:1200 +corner:curve)
/desktop

mobile:
![Portrait mobile demo](/media/demo-mobile.mp4 +autoplay +corner:curve)
/mobile
```

The desktop variant shows above 768px viewport width; the mobile variant shows at or below. Switching is pure CSS — no JavaScript, no flash. The hidden variant still issues a `preload="metadata"` request, so keep both files reasonably sized.

Device fences aren't video-specific — they wrap any markdown (text, images, sections, mixed content), so you can also use them for "tap" vs. "click" copy, mobile-only callouts, or desktop-only diagrams.

## Hosting

Videos in `media/` are uploaded to your configured media CDN (R2/S3) automatically on deploy, just like images. The build rewrites `/media/foo.mp4` URLs in your HTML to the CDN URL, and only changed files are re-uploaded (tracked by content hash). See [Media Hosting](/docs/media-hosting) for setup.

Videos are **not** run through the image optimizer — there's no resizing, transcoding, or format conversion. Encode your videos at the target size and bitrate before adding them to `media/`. For marketing videos, H.264 MP4 at 1080p with a 2–4 Mbps bitrate is a reasonable default; ship a `.webm` (VP9 or AV1) variant alongside if you want smaller files for modern browsers.

## When to use embeds instead

If you're embedding from YouTube, Vimeo, or another video host, use the [embed shortcode](/docs/embeds) instead — it produces a responsive iframe and doesn't upload anything to your CDN:

```markdown
embed: https://www.youtube.com/watch?v=VIDEO_ID
```

Use native video embeds when you want full control over hosting, no third-party players, no tracking, and a single deploy step.