How To Embed Youtube Videos to Gatsby
Embed YouTube videos in Gatsby markdown and MDX using plugins. Step-by-step setup for Contentful and other headless CMS systems.

Note: Gatsby has been in maintenance mode since 2023. The latest release (v5.16.1, February 2026) added React 19 and Node.js 24 support, but active feature development has stopped. If you’re starting a new project, consider Next.js or Astro instead. The instructions below still work for existing Gatsby sites.
Gatsby doesn’t handle iframes out of the box. You can’t just paste a YouTube embed code into markdown and expect it to work — React sanitizes raw HTML. You need a plugin to convert video URLs into proper iframes during the build.
This guide covers two approaches: using a remark plugin for markdown content, and handling videos in MDX with a custom component.
Option 1: gatsby-remark-embed-video (recommended)
gatsby-remark-embed-video is the most maintained option in the Gatsby ecosystem. It supports YouTube, Vimeo, VideoPress, and Twitch. Last published 4 years ago (v3.2.1), but it still works with Gatsby 5.
It works with both gatsby-transformer-remark (markdown) and gatsby-plugin-mdx.
Install
npm i gatsby-remark-embed-video gatsby-transformer-remark
If you want responsive iframes (recommended), also install:
npm i gatsby-remark-responsive-iframe
Configure for markdown (gatsby-transformer-remark)
Add this to your gatsby-config.js:
{
resolve: "gatsby-transformer-remark",
options: {
plugins: [
{
resolve: "gatsby-remark-embed-video",
options: {
width: 800,
ratio: 1.77, // 16/9 aspect ratio
height: 400, // overrides ratio if set
related: false, // hide related videos at end
noIframeBorder: true,
loadingStrategy: "lazy",
containerClass: "embedVideo-container",
urlOverrides: [
{
id: "youtube",
embedURL: (videoId) =>
`https://www.youtube-nocookie.com/embed/${videoId}`,
},
],
},
},
"gatsby-remark-responsive-iframe", // must come after embed-video
],
},
},
The youtube-nocookie.com URL override uses YouTube’s privacy-enhanced mode — no cookies until the user clicks play. Good for GDPR compliance.
Configure for MDX (gatsby-plugin-mdx)
If you’re using MDX instead of plain markdown:
{
resolve: "gatsby-plugin-mdx",
options: {
gatsbyRemarkPlugins: [
{
resolve: "gatsby-remark-embed-video",
options: {
width: 800,
ratio: 1.77,
related: false,
noIframeBorder: true,
loadingStrategy: "lazy",
},
},
"gatsby-remark-responsive-iframe",
],
},
},
Usage in content
Add these tags on their own line in your markdown or MDX files:
`video: https://www.youtube.com/embed/2Xc9gXyf2G4`
`youtube: https://www.youtube.com/watch?v=2Xc9gXyf2G4`
`youtube: 2Xc9gXyf2G4`
`vimeo: https://vimeo.com/5299404`
`vimeo: 5299404`
`videoPress: https://videopress.com/v/kUJmAcSf`
`videoPress: kUJmAcSf`
`twitch: https://player.twitch.tv/?channel=dakotaz`
`twitch: https://player.twitch.tv/?autoplay=false&video=v273436948`
`twitch: 273436948`
`twitchLive: dakotaz`
You can also add accessibility titles:
`youtube: [My Video Title](https://www.youtube.com/watch?v=2Xc9gXyf2G4)`
Using with Contentful CMS
This approach works with Contentful or any headless CMS that outputs markdown. The key requirement: your content field must be markdown, not rich text.
In Contentful, create a text field with “Markdown” type. Then add the video tag on its own line in the editor:
`youtube: https://youtu.be/2Wmats7Q6ck`
When Gatsby builds, gatsby-transformer-remark processes the markdown and the embed-video plugin converts the tag into an iframe.
Important: plugin order matters
If you use gatsby-remark-responsive-iframe, gatsby-remark-images, or gatsby-remark-prismjs, the embed-video plugin must come first:
plugins: [
"gatsby-remark-embed-video",
"gatsby-remark-responsive-iframe",
"gatsby-remark-prismjs",
"gatsby-remark-images",
]
Wrong order will break video embedding.
Option 2: Custom React component (MDX only)
If you’re using MDX and want more control, skip the plugin entirely and create a YouTube component:
// src/components/YouTube.js
const YouTube = ({ id, title = "YouTube video" }) => (
<div style={{ position: "relative", paddingBottom: "56.25%", height: 0, overflow: "hidden" }}>
<iframe
src={`https://www.youtube-nocookie.com/embed/${id}`}
title={title}
style={{ position: "absolute", top: 0, left: 0, width: "100%", height: "100%" }}
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
loading="lazy"
/>
</div>
);
export default YouTube;
Then import and use it in your MDX files:
import YouTube from "../components/YouTube";
# My Post
Some content here.
<YouTube id="2Xc9gXyf2G4" title="Demo video" />
This gives you full control over the iframe attributes, styling, and lazy loading. No plugin dependency.
Which approach to choose
Use the plugin if:
- Your content comes from a headless CMS (Contentful, Sanity, etc.)
- Non-technical editors need to add videos by pasting URLs
- You have existing markdown content with video tags
Use a custom component if:
- You write content directly in MDX files
- You want full control over iframe attributes
- You want to avoid plugins that haven’t been updated in years
Troubleshooting
Videos not showing up? Check that your content field is markdown type, not rich text. Rich text in Contentful uses a different rendering pipeline that skips remark plugins.
Build errors after install? Clear the Gatsby cache:
gatsby clean && gatsby develop
Plugin conflicts? Make sure embed-video is listed before any other remark plugins in your config.
DigitalOcean $100 Free Vultr $100 Free Hetzner €20 Free Hostinger VPS

