// Tutorial //

Building a blog with Gridsome: Listing All Posts and Pagination

Published on November 5, 2018
    Default avatar
    By Alex Jover Morales
    Developer and author at DigitalOcean.
    Building a blog with Gridsome: Listing All Posts and Pagination

    While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

    In the previous post I described how to get started with Gridsome, a Vue.js technology that you can use to build data-driven static websites based on different resources that are accessible using GraphQL.

    In the previous post, you can also see how to use local markdown files as a data source and render posts for each of them.

    However, we don’t have a page to render a list of posts yet, so let’s see how can we manage to get that working.

    Listing all Blog Posts

    We already have the post template ready (thus all the posts created will use that template), but we might need a page where we list all the posts.

    We’ll add that list of all posts on a page, and for this example, let’s use the home page, located at pages/Index.vue.

    If we check the GraphQL explorer, we’ll see there is a allPost query available with many parameters:

    allPost(
      sortBy: String = "date"
      order: SortOrder = DESC
      perPage: Int = 25
      skip: Int = 0
      page: Int = 1
      regex: String
    ): PostConnection
    

    If you explore the PostConnection schema, you’ll see that we can get all posts titles and paths by using the following query, which we should put in pages/Index.vue:

    pages/Index.vue
    <page-query>
    query Posts {
      posts: allPost {
        edges {
          node {
            title
            path
          }
        }
      }
    }
    </page-query>
    

    The only thing left to do is to loop through the posts to print the links to them. For that, Gridsome already includes a <g-link> component, which is a wrapper for router-link:

    pages/Index.vue
    <template>
      <Layout>
        <p v-for="post in $page.posts.edges">
          <g-link :to="post.node.path">
            {{ post.node.title }}
          </g-link>
        </p>
      </Layout>
    </template>
    

    That should do it. The home page should list all your blog posts!

    Adding Pagination

    Listing all the posts on the same page is a bit optimistic. When we have several of them, the UX can be negatively impacted if the user has to navigate through tons of items.

    That’s why we usually need pagination to provide a better navigation experience for users.

    Fortunately, Gridsome is ahead and provides us with an easy way to add pagination. If you remember from the last article, the PostConnection schema from the GraphQL layer already provides us with some parameters to paginate the data:

    allPost(
      sortBy: String = "date"
      order: SortOrder = DESC
      perPage: Int = 25
      skip: Int = 0
      page: Int = 1
      regex: String
    ): PostConnection
    

    In particular, we can use the perPage, skip and page parameters in order to control the pagination behavior. Although skip might not be necessary very often, it can be used to tell how many items the query must skip.

    Let’s continue by creating 3 or 4 more articles so we have enough to see the pagination working.

    Then, we can use the @paginate directive, along with the parameters from the PostConnection in order to write a query for paginated posts:

    query Posts ($page: Int) {
      posts: allPost (perPage: 2, page: $page) @paginate {
        edges {
          node {
            title
            path
          }
        }
      }
    }
    

    I’ve set the perPage parameter to 2 in order to have several pages with a few posts.

    If you’d like, remember that you can try out this query in the GraphQL playground available at http://localhost:8080/___explore. If you do that, keep in mind to set the page query variable to any value starting from 1:

    GraphQL Playground

    In order to control the pagination, we also need the pagination information to be returned. If you inspect again the PostConnection schema, you’ll see that it has the properties totalCount and pageInfo. Let’s use them to return that info:

    query Posts ($page: Int) {
      posts: allPost (perPage: 2, page: $page) @paginate {
        totalCount
        pageInfo {
          totalPages
          currentPage
          isFirst
          isLast
        }
        edges {
          node {
            title
            path
          }
        }
      }
    }
    

    If you run this query in the explorer, you’ll see data similar to this returned:

    {
      "data": {
        "posts": {
          "totalCount": 5,
          "pageInfo": {
            "totalPages": 3,
            "currentPage": 1,
            "isFirst": true,
            "isLast": false
          },
          "edges": [
            {
              "node": {
                "title": "An awesome article 4",
                "path": "/blog/awesome-post-4"
              }
            }
          ]
        }
      }
    }
    

    Now that we have the query in place, let’s first update the <page-query> block in the home page:

    pages/Index.vue
    <page-query>
    query Posts ($page: Int) {
      posts: allPost (perPage: 2, page: $page) @paginate {
        totalCount
        pageInfo {
          totalPages
          currentPage
          isFirst
          isLast
        }
        edges {
          node {
            title
            path
          }
        }
      }
    }
    </page-query>
    

    Then, we can use the special Pager component that comes with Gridsome.

    The Pager component works simply by passing the pageInfo data to its info property. So, to setup pagination, it’d be as simple as importing it and using it:

    pages/Index.vue
    <template>
      <Layout>
        <p v-for="post in $page.posts.edges">
          <g-link :to="post.node.path">
            {{ post.node.title }}
          </g-link>
        </p>
        <Pager :info="$page.posts.pageInfo"/>
      </Layout>
    </template>
    
    <page-query>
    // ...
    </page-query>
    
    <script>
    import { Pager } from "gridsome";
    
    export default {
      components: {
        Pager
      }
    };
    </script>
    

    If you navigate to http://localhost:8080 you should see the navigation component rendered and fully working.

    Note that the component has no styles, so you might see the numbers quite close together. That’s intentional, so you have full control of the pagination styling.

    If you want to see all the options of the Pager component, check out the docs.

    Wrapping Up

    If you reached this point, you already know all the basics on how to build a blog and any similar website using Gridsome, including both creating pages based on data and list them from any page, including pagination.

    Sure, the Gridsome project is still at an early stage in the development, but it looks so exciting and seems to have a great future ahead since it’s following the Gatsby path!

    Don’t forget to check out the code sample repo and the online demo for this article!

    Stay cool 🦄


    Want to learn more? Join the DigitalOcean Community!

    Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in our Questions & Answers section, find tutorials and tools that will help you grow as a developer and scale your project or business, and subscribe to topics of interest.

    Sign up
    About the authors
    Default avatar
    Developer and author at DigitalOcean.

    Still looking for an answer?

    Was this helpful?
    Leave a comment

    This textbox defaults to using Markdown to format your answer.

    You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!