# How to add a blog post index to your Vuepress site
Vuepress allows you to write Vue (opens new window) in your Markdown files which is ideal for us to use to add dynamic sections to a Vuepress site. It also gives you access to some site metadata (opens new window). The $site
array contains
an array called pages
containing metadata of all your site's pages which is ideal
for displaying an index of blog posts on a home page!
# Add some frontmatter
Firstly, for our code to be able to recognise which pages are blog posts, we need to add a boolean field to our blog posts' frontmatter (opens new window).
We can also add a "date" field to use to use order our posts by date posted.
So to each of our blog posts' markdown files, we can add the following at the top:
---
title: "Your post's title"
blog: true
date: 2019-04-16
---
2
3
4
5
You can also add categories, tags, etc. to your posts' frontmatter.
# Create a custom component
Next we can create a custom component at .vuepress/components/BlogPosts.vue
that
we will use to display the list of posts.
<template>
</template>
<script>
export default {
props: {
pages: Array
},
};
</script>
2
3
4
5
6
7
8
9
10
We give the component a prop called pages
that will contain the array of all our
site's pages.
You can add the component to the page on which you want to display the list like this:
<BlogPosts :pages="$site.pages" />
# Filter your pages for blog posts
To display only blog posts and not all pages in our lists of posts, we can create
a computed property called posts
that will check whether the blog
frontmatter
value is true for a page.
Then we can use a v-for
(opens new window) directive to loop through all of the
pages in posts
and display each of their titles:
<template>
<ul>
<li v-for="post in posts" :key="post.key">
<div class="post">
<router-link class="title" :to="post.path">
{{ post.title }}
</router-link>
</div>
</li>
</ul>
</template>
<script>
export default {
props: {
pages: Array
},
computed: {
posts: function() {
return this.pages.filter(isBlogPost);
}
},
methods: {
isBlogPost(page) {
return "blog" in page.frontmatter && page.frontmatter.blog;
}
}
};
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Example output:
# Sort by date
Now you can start to do more sorting or filter on your pages. For example, to sort the posts by date descendingly:
<template>
<ul>
<li v-for="post in posts" :key="post.key">
<div class="post">
<router-link class="title" :to="post.path">
{{ post.title }} ({{ post.date.toDateString() }})
</router-link>
</div>
</li>
</ul>
</template>
<script>
export default {
props: {
pages: Array
},
computed: {
posts: function() {
return this.pages
.filter(this.isBlogPost)
.map(this.convertPageDate)
.sort(this.dateCompare());
}
},
methods: {
isBlogPost(page) {
return "blog" in page.frontmatter && page.frontmatter.blog;
},
convertPageDate(page) {
return { ...page, date: new Date(page.frontmatter.date) };
},
dateCompare(desc = true) {
let multiplier = desc ? -1 : 1;
return function(a, b) {
return multiplier * (a.date - b.date);
};
}
}
};
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Example output:
Newsletter
If you'd like to subscribe to my blog, please enter your details below. You can unsubscribe at any time.