2

I am working with Astro. The project uses quite a few images, and I want to simplify the way I currently add new images. My routes are like:

example.com/pictures/[collection]

( "[" and "]" stands for a dynamic route )

Allowing for example:

example.com/pictures/mixed-tecnique

example.com/pictures/graphite

example.com/pictures/acrylic


In the file pages/pictures/[collection].astro I want to do the following (or something similar):

---
import * as collections from "public/img/collections"

const { collection } = Astro.props
---

{collections[collection].map(imgSrc => <img src={imgSrc} />)}

So now, to have a new Collection route, I just have to create a new folder and drop the images there.

Is there any way to do something to reach the same result? Thanks in advance!!

2 Answers2

7

This is how I achieve:

---
const images = await Astro.glob("/src/assets/img/salon/*").then(files => {
  return files.map(file => file.default);
});
---

<div class="swiper">
  <!-- Additional required wrapper -->
  <div class="swiper-wrapper">
    <!-- Slides -->
    {
      images.map(image => (
        <div class="flex items-center justify-center swiper-slide">
          <img
            class="object-contain h-full rounded-lg"
            src={image}
            alt=""
            loading="lazy"
          />
        </div>
      ))
    }
  </div>
  ...
</div>

If you are using experimental assets feature:

{
  images.map(({ src /* width and height is also available */ }) => (
    <div class="flex items-center justify-center swiper-slide">
      <img
        class="object-contain h-full rounded-lg"
        src={src}
        alt=""
        loading="lazy"
      />
    </div>
  ))
}
gokudesu
  • 149
  • 2
  • 7
  • Does the `file.default` part return a relative file path? From docs I can see that if not a MD / Astro file, the return type is a `CustomDataFile { default: Record }` – David Min May 03 '23 at 16:12
  • @DavidMin it is the default behavior of rollup dynamic import of modules. `({ default: DefaultExport, NamedExport }) => { ... })`. Astro uses `vite`, which is using `rollup` under the hood. I may be wrong. – gokudesu May 06 '23 at 04:43
2

There are a bunch of different ways to implement a feature like this but here is a simple example making use of the fast-glob library

public
  pictures
    mixed-technique
      example.png
      example.png
      example.png
    graphite
      example.png
      example.png
      example.png
    arcylic
      example.png
      example.png
      example.png
// src/pages/pictures/[collection].astro
---
import fg from 'fast-glob';

export async function getStaticPaths() {
    // get all collection folder paths: 'public/pictures/[collection]'
    const collections: string[] = fg.sync('public/pictures/*', { onlyDirectories: true })

    // Create a new route for every collection
    return collections.map(collection => {

        // Create Route
        return {
            params: {
                // Return folder name of collection as dynamic parameter [collection]
                collection: collection.split('/').pop()
            },
            props: {
                // Return array of all image srcs in collection as prop 'images'
                images: fg.sync(`${collection}/**/*.{png,jpg}`).map(img => img.replace('public/', '/'))
            }
        }
    })
}

export interface Props {
    images: string[];
}

const { collection } = Astro.params

const { images } = Astro.props
---

<html lang="en">
    <head>
        <!-- ... -->
    </head>
    <body>
        { images.map(img => <img src={img}/>) }
    </body>
</html>

Note: I used fast-glob instead of Astro.glob or import.meta.glob() because it can take a variable as an argument (makes this logic easier/more dynamic) and because it only returns an array of file/folder paths instead of also attempting to return file content

Bryce Russell
  • 647
  • 3
  • 8
  • Oh, Thank you. I solved it by creating a NodeJS script to "scrap" the images folder and generate both the images map and the static paths. Anyway, your solution looks very good. Thanks! – Genaro Bonavita Jan 23 '23 at 14:28