nuxt3tailwind

How to build a static blog part 10

Monday, 10 July 2023


Blog tag navigation

We've added the ability to tag each post in our blog, so we should allow the user to click on a tag to see a list of all the posts that have that tag. The blog index page and the blog page both render the blog tags with a link to a /tag/tag page so lets build it.

Add a folder inside /pages/blog, called tag. Then a file inside called [...slug].vue. Paste this in. Notice the query function to pull out all the posts with that slug, and the way we're using a computed property to return the results fully typed so we can pass that to the BlogPostsList.vue component, once it has loaded.

<script lang="ts" setup>
import { Article } from '~/types/types'

const { params } = useRoute()
useHead({
    title: `Posts Tagged with ${params.slug[0]}`,
    meta: [{ name: 'description', content: 'Blog Post tag archive' }],
})
// Search the content in the blog folder
// for posts where the tags include this one.
// Sort them in reverse date order, and
// only show the info we need in this component
const parsedContent = await queryContent('blog')
    .where({ tags: { $contains: params.slug[0] } })
    .sort({ date: -1 })
    .only(['_path', 'title', 'description', 'tags'])
    .find()

const articles = computed(() => {
    return parsedContent as Article[]
})
</script>
<template>
    <div>
        <h1>Posts tagged with '{{ params.slug[0] }}'</h1>
        <hr />
        <BlogPostsList
            v-if="articles.length > 0"
            :articles="articles"
        ></BlogPostsList>
        <p v-else>Sorry, nothing found.</p>
    </div>
</template>

We also need to add in the Back button component, so our readers can also get back to the menu. Add a new file in the components folder called BackButton and pop this in it:

<script setup lang="ts">
defineProps<{
    to?: string
}>()
</script>

<template>
    <nuxt-link
        :to="to ? to : '/'"
        class="router__link"
        @click.native="to ? null : $router.go(-2)"
    >
        <svg
            width="38"
            height="8"
            viewBox="0 0 38 8"
            xmlns="http://www.w3.org/2000/svg"
            class="inline"
        >
            <path
                d="M0.646446 3.64644C0.451183 3.84171 0.451183 4.15829 0.646446 4.35355L3.82843 7.53553C4.02369 7.73079 4.34027 7.73079 4.53553 7.53553C4.7308 7.34027 4.7308 7.02369 4.53553 6.82842L1.70711 4L4.53553 1.17157C4.7308 0.976308 4.7308 0.659725 4.53553 0.464463C4.34027 0.269201 4.02369 0.269201 3.82843 0.464463L0.646446 3.64644ZM38 3.5L1 3.5L1 4.5L38 4.5L38 3.5Z"
                fill="currentColor"
            />
        </svg>
        <small>
            <slot>go back</slot>
        </small>
    </nuxt-link>
</template>

<style lang="postcss">
.router__link {
    @apply hover:text-sky-700 dark:hover:text-sky-500;
    & svg {
        @apply transition-all duration-500 ease-in-out;
    }
}

.router__link:hover svg {
    @apply -translate-x-1;
}
</style>

That's it, our blog is fully functional, and we can write some posts as markdown in the content/blog folder and see them in our browser. Don't forget the frontmatter, which is used for the title, description, tags etc. Also remember that the posts slug in the url comes from the filename of the markdown file, so only use url friendly characters in the filename. I would use an excerpt of the title, all lower case, and with hyphens - in between, like this: my-super-post.md . Happy blogging!

Next post →


go back