Dynamically Import Images in Astro

Web Reaper
4 min read

In order to use Astroβs <Image /> component for image optimization, you need to import images in .astro files. But what if all you have is a string path of an image? This is where viteβs import.meta.glob comes in handy. Weβll expore this using two examples.
Note that I got started from this useful recipe in Astroβs docs, but had a slightly more complex example. Iβll go through both a simple example and the exact problem I came across while building the most recent theme - Dawnlight.
INFO
Youβre likely to run into it if you use any sort of git-based CMS, such as Keystatic
What is import.meta.glob?
This is a Vite capability to import multiple files using a glob pattern. Basically, we can import all potential images, and use our path as a key to get the image we need.
It will look something like const images = import.meta.glob('./dir/*.jpg')
Starting Code
This is a simple component we can use to demonstrate dynamic image imports.
---import { Image } from "astro:assets";
interface Props { imagePath: string; description: string;}
const { imagePath, description } = Astro.props as Props;
// need to turn the imagePath string into an imported image---
<div> <!-- this wont' work, as imagePath is not an imported image --> <Image src={imagePath} alt={description} width={600} /> <p>{description}</p></div>Dyanamically Importing Images - Simple Example
File Structure 1
The first important order of business - what is the path to our images? For the simple example, weβll say all images go to src/assets/{image}.
src/βββ assets/ βββ img1.jpg βββ img2.png βββ img3.jpegGlob Pattern 1
For this, we want to import all image related types (jpg, png, jpeg, gif). We can do this with the following glob pattern:
const images = import.meta.glob<{ default: ImageMetadata }>("/src/assets/*.{jpeg,jpg,png,gif}");INFO
ImageMetadata helps us define the type of the images variable.
Solution 1
Now lets put it all together. Weβll import all images, and then use our imagePath to get the image we need.
---import { Image } from "astro:assets";
interface Props { imagePath: string; description: string;}
const { imagePath, description } = Astro.props as Props;// image path looks like "src/assets/img1.jpg"
const images = import.meta.glob<{ default: ImageMetadata }>("/src/assets/*.{jpeg,jpg,png,gif}");---
<div> <Image src={images[imagePath]()} alt={description} width={600} /> <p>{description}</p></div>Production-ready Astro Templates

Templates with tons of features others leave out. I18n, CMS, animations, image optimization, SEO, and more.
Dyanamically Importing Images - Complex Example
File Structure 2
For the complex example, weβll solve the exact issue I had. In Keystatic you can set the path to images in the config file, and I like to keep images co-located with the content. This file structure looks like:
src/βββ content/ βββ blog/ βββ blog-slug-1/ β βββ img1.jpg β βββ img2.png βββ blog-slug-2/ βββ img3.jpegSo here itβs a little extra challenging, given the dynamic nature of the path. We canβt just import all images in the src/content/blog directory, and instead need to use some fancy glob patterns.
Glob Pattern 2
Letβs get fancy. The ** here in the glob pattern allows us to search recursively. We can use this to search for all images in any subfolder inside the src/content/blog directory.
const images = import.meta.glob<{ default: ImageMetadata }>( "/src/content/blog/**/*.{jpeg,jpg,png,gif}",);Solution 2
Like the previous example, lets put it all together by importing all images, then using our imagePath to get the image we need.
---import { Image } from "astro:assets";
interface Props { imagePath: string; description: string;}
const { imagePath, description } = Astro.props as Props;// image path looks like "src/content/blog/blog-slug-1/img1.jpg"
const images = import.meta.glob<{ default: ImageMetadata }>( "/src/content/blog/**/*.{jpeg,jpg,png,gif}",);---
<div> <Image src={images[imagePath]()} alt={description} width={600} /> <p>{description}</p></div>Throw an Error Message
Itβs a good idea to throw an error message if the image path is not found. This helps you track the error down at the source, rather than receiving some nonsense error message further down the line. So letβs add one!
---import { Image } from "astro:assets";
interface Props { imagePath: string; description: string;}
const { imagePath, description } = Astro.props as Props;
const images = import.meta.glob<{ default: ImageMetadata }>( "/src/content/blog/**/*.{jpeg,jpg,png,gif}",);
if (!images[imagePath]) throw new Error( `"${imagePath}" does not exist in glob: "/src/content/blog/**/*.{jpeg,jpg,png,gif}". See ImageComponent.astro to debug.`, );---
<div> <Image src={images[imagePath]()} alt={description} width={600} /> <p>{description}</p></div>