AstroJs: Is it possible to have multiple returns inside getStaticPaths()?

344 Views Asked by At

I am working on a project using AstroJS. The goal is to have a few images, a title, and a description appear on a single page following the dynamic routes method using the getStaticPaths function.

Start with Image library

src
  images
    apple
      apple-01.jpg
      apple-02.jpg
      apple-03.jpg
      apple-03.jpg
    banana
      banana-01.jpg
      banana-02.jpg
      banana-03.jpg
      banana-03.jpg

And page outcome as expected

/page/{path}
------------
    {Title}
    {Description}
    {Image}
    {Image}
    {Image}

------------

Fortunately, I've succeeded in getting multiple images onto a single page following Bryce Russell's coding example. However, I am struggling to find a way to include the title and description, despite trying some form of Data Passing Props in combination with Bryce Russell's coding example.

This code below is my 8th attempt, and...

// [page].astro
---
import fg from "fast-glob";

export async function getStaticPaths() {

//Data array for titles and description based on image folder name 
  const labels = [
    {page: 'image folder name', title: "Title goes here", desc: "description goes here"},
    {page: 'image folder name', title: "Title goes here", desc: "description goes here"}
  ];

//Create labels (Title and Description) based on [page].astro
   return labels.map((label) => {
    return {
      params: { id: label.page },
      props: { title: label.title, desc: label.desc }
    };
  });


// Get all collection folder paths: 'src/images/[collection]'
  const collections: string[] = fg.sync("src/images/*", {
    onlyDirectories: true,
  });

// Create a new route for every collection
  return collections.map((collection) => {
    return {
      params: { collection: collection.split("/").pop() },
      props: {
        images: fg.sync(`${collection}/**/*.{png,jpg}`).map((img) => img.replace("", "/")),
      },
    };
  });
}

export interface Props {
  images: string[];
}

const { collection } = Astro.params;
const { label } = Astro.params
const { images, title, desc } = Astro.props;
---
<div>
  <section>
      {title}
      {desc}
  </section>
  <section>
    {
      images.map((img) => (
        <img src={img} loading="lazy"  />
      ))
    }
  </section>
</div>

Obviously, I've made it so sloppy, and I knew this is not the correct way to do this. Clearly, getStaticPaths() will not allow two returns of .map() in the same function. Unless I am missing something?

As much as I've tried to find solutions, I have looked into Astro docs, attempted to find some tips, examples, or tricks. I am not having any luck.

So I was hoping I could get some help finding solutions and getting a better understanding of how to use getStaticPaths() to collect multiple images and data (title and description) into a single page following a routing path. Unless there is another way to do this? What would you recommend?

Thanks in advance.

1

There are 1 best solutions below

4
On BEST ANSWER

As you've discovered, Astro.glob and import.meta.glob() don't work if the path contains dynamic parts like the name of something in a collection. But the following works:

Create a collection

Start the fruit content collection by placing the following in src/content/fruit/apple.yaml

title: 'Apple'
description: 'Appples are awesome.'
images:
  - src: './apple-1.jpg'
    alt: 'image one desc'
  - src: './apple-2.jpg'
    alt: 'image two desc'

Don't forget to add the image files, e.g. src/content/fruit/apple-1.jpg

Describe your collection for schema validation and image handling by placing the following in src/content/config.ts:

import { defineCollection, z } from "astro:content";

// from https://docs.astro.build/en/guides/images/#images-in-content-collections
const fruitCollection = defineCollection({
  schema: ({ image }) => z.object({
    title: z.string(),
    description: z.string(),
    images: z.array( z.object({
      src: image(),
      alt: z.string(),
    })),
  }),
});

export const collections = {
  fruit: fruitCollection,
};

Generate the pages using getStaticPaths

Have Astro generate the pages by placing the following in src/pages/[...slug].astro:

---
import { Image } from "astro:assets";
import { getCollection } from 'astro:content';


// from https://docs.astro.build/en/tutorials/add-content-collections/#generate-pages-from-a-collection
export async function getStaticPaths() {
  const entries = await getCollection('fruit');
  return entries.map(entry => ({
    params: { slug: entry.id }, props: { entry },
  }));
}

const { entry } = Astro.props;
---
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Astro</title>
  </head>
  <body>
    <h1>{entry.data.title}</h1>
    <p>{entry.data.description}</p>
    {entry.data.images.map(image =>
      <Image src={image.src} alt={image.alt} />)}
  </body>
</html>

Visit http://localhost:4321/apple/