#paginate() routing options

7 messages · Page 1 of 1 (latest)

stray epoch
#

Is it possible to use the paginate() function within getStaticPaths to generate the following routes:

  • /blog (the first blog page)
  • /blog/page/2 (the second blog page)
  • /blog/page/3 (the third blog page)
  • etc.
    So the first page should be on the /blog root level/ and the rest under /blog/page/[...page]
shadow owl
#

Hi @stray epoch!
The paginate function returns an array, so you could map over the returned data to update the params format.
For example, with a file named src/pages/blog/[...page].astro, you could use the following:

export const getStaticPaths = (async ({ paginate }) => {
  const posts = await getCollection("posts");

  return paginate(posts).map((paginatedPosts) => {
    return {
      ...paginatedPosts,
      params: {
        ...paginatedPosts.params,
        page: paginatedPosts.params.page
          ? `/page/${paginatedPosts.params.page}`
          : undefined,
      },
    };
  });
}) satisfies GetStaticPaths;
stray epoch
#

thx @shadow owl !! , I'm going to try this later this evening and update this thread.

stray epoch
#

Hi @shadow owl ,
your solution worked perfectly for the generated page (/blog, /blog/page/2, /blog/page/3 etc).

However the page object is not correctly providing the correct values unfortunately.

E.g on page 2 I get:

  "start": 2,
  "end": 3,
  "size": 2,
  "total": 11,
  "currentPage": 2,
  "lastPage": 6,
  "url": {
    "current": "/blog/2",
    "next": "/blog/3",
    "prev": "/blog",
    "first": "/blog",
    "last": "/blog/6"
  }

page.url.prev is correct, but page.url.next is not, as it should have the value /blog/page/3.

Is that expected with this approach?

shadow owl
#

Hi @stray epoch! It seems you are right. I have never used the properties from page.url with this approach so I did not think about this problem. I use my own routing logic to support multiple languages and my own Pagination component...

But, by implementing your own logic to replace values ​​in page.url, I think it is doable. You need to add props to the code I suggested previously:

export const getStaticPaths = (async ({ paginate }) => {
  const posts = await getCollection("posts");

  return paginate(posts).map((paginatedPosts) => {
    return {
      ...paginatedPosts,
      params: {
        ...paginatedPosts.params,
        page: paginatedPosts.params.page
          ? `/page/${paginatedPosts.params.page}`
          : undefined,
      },
      props: {
        ...paginatedPosts.props,
        page: {
          ...paginatedPosts.props.page,
          url: {
            current: `/blog`, // TODO
            next: `/blog/2`, // TODO
            prev: undefined, // TODO
            first: undefined, // TODO
            last: `/blog/3`, // TODO
          }
        }
      },
    };
  });
}) satisfies GetStaticPaths;

I don't have a ready-made solution. I marked in the example above the places that need to be updated with // TODO. For the first and last page (using paginatedPosts.props.page.lastPage), it should be pretty simple. For the current page, I think you'll need a ternary... something like:

paginatedPosts.props.page.currentPage === 1 ? "/blog" : `/blog/page/${paginatedPosts.props.page.currentPage}`

It remains to update prev and next.

stray epoch
#

Yes, I was also thinking of just constructing the url of the pages myself.
based on the "currentPage": 2, I can easily construct the links myself.
Probably that's by far the easiest solution.
Thx again!

shadow owl
#

Yes I think so too! Glad I could help!