Simple Image Gallery Using Gridsome

18 Jul 2020

This portfolio site I'm building needs a gallery of lettering images. I haven't found a specific tutorial for this use case. After googling for a while I found this Stackoverflow answer, it's for Nuxt but I tought it might work for Gridsome too.

So I'm documenting the process and sharing it with others who might want to do similar thing. Note this is a simple implementation that utilizes Webpack feature instead of GraphQL.

In my case, I'll be making the gallery under /lettering URL, so I'm making new file on /pages/Lettering.vue. There's two part of this: the page itself, and gallery of images. I'll be putting the image on ./static/images/lettering/.... It looks like this in directory structure: (other files ommited)

 โ”‚ โ””โ”€๐Ÿ“‚pages
 โ”‚ โ”‚ โ””โ”€๐Ÿ“œLettering.vue
 โ”‚ โ””โ”€...
 โ”‚ โ””โ”€๐Ÿ“‚images
 โ”‚ โ”‚ โ””โ”€๐Ÿ“‚lettering
 โ”‚ โ”‚ โ”‚ โ””โ”€ (image files goes here)
 โ”œโ”€ ...

I also introduce name template for the image files here: image-name_YY-MM-DD.jpg. I'm doing this so I can sort the images by Date later. You can change the name template to your liking.

Here's what goes into actual page Lettering.vue:

    <h1 class="mb-4 text-4xl leading-none uppercase lg:text-6xl">Lettering</h1>
    <div class="flex flex-wrap pb-20 -mx-3">
      <div class="w-full sm:w-1/2 md:w-1/3 lg:w-1/4" v-for="(image, index) in sortedImages" :key="index">
        <div class="px-3 my-3">
          <div class="relative shadow-lg" style="padding-bottom: 100%">
            <g-image class="absolute object-cover w-full h-full"
              :src="image.pathLong" :title="`20${image.year}-${image.month}-${}`"/>

export default {
  metaInfo: {
    title: 'Lettering'
  data() {
    return {
      images: []
  mounted() {
    this.importAll(require.context('../../static/images/lettering/', true, /\.jpg$/))
  computed: {
    sortedImages() {
      return this.images.sort((a, b) => (
        new Date(`20${b.year}`, b.month, -
        new Date(`20${a.year}`, a.month,
  methods: {
    importAll(r) {
      r.keys().forEach(key => (this.images.push({
        pathLong: r(key),
        pathShort: key,
        year: key.split('_').pop().replace('.jpg', '').split('-')[0],
        month: key.split('_').pop().replace('.jpg', '').split('-')[1],
        day: key.split('_').pop().replace('.jpg', '').split('-')[2],

To import all the images, we are utilizing webpack require.context inside the image directory. Then for each image, we put them into images array as an object with few attributes: pathLong, year, month, day. You can optimize or change the code to your liking, but for now it works okay.

I'm also using tailwind CSS here, with a minor rule breaking inline style for padding-bottom trickery to get that square div ratio.

Hope this helps! Thanks for reading.

Built with ๐Ÿ’– using Gridsome