Posted on May 06, 2020
You've found your way to part 2. If you've landed here by mistake, make sure you check out part one first. Next we will get to the fun part of building the actual pages, write our GraphQL queries, and styling with Tailwind.
To see what we've built thus far, run the following command in the terminal (make sure you're in your project directory):
$ gridsome develop
Going to http://localhost:8080/
should pull up our site (or at least what will be our site :))
Under the pages
folder, add a file called Blog.vue
.
In the new Blog.vue file add the following code:
<template>
<Layout>
<div class="container grid grid-cols-1 justify-center px-auto mx-auto flex flex-wrap flex-col md:flex-row items-center ">
<div class="mx-0 px-auto max-w-xl mx-auto">
<h1 class="text-2xl font-bold leading-tight mb-6 mt-4 text-center text-primary">Blog</h1>
<ul>
<li v-for="{ node } in $page.posts.edges" :key="node.id">
<g-link :to="node.path">
<div class=" border-solid border-2 border-primary max-auto-sm overflow-hidden shadow-lg p-20 m-4 rounded-md">
<h1 class="text-2xl text-primary font-bold"> {{node.title}} </h1>
<p class="pt-5 text-darkgray"> {{node.description}} </p>
<p class="font-normal text-sm pt-5 text-primary"> Posted on {{node.date}} </p>
</div>
</g-link>
</li>
</ul>
</div>
</div>
</Layout>
</template>
<page-query>
query Posts {
posts: allContentfulBlogPost {
edges {
node {
id,
title,
description,
date (format: "MMMM DD, YYYY"),
path
}
}
}
}
</page-query>
<script>
export default {
metaInfo: {
title: 'Blog'
}
}
</script>
In the URL, add /blog
at the end of localhost:8080
. You should see a listing of our blogs (assuming you've added a published at least one in Contentful). Clicking on any of the blogs will yield no results just yet. This is because we need a way for gridsome to read our markdown from Contentful. We also need to create our blog template. To do this, we will first add a tool called "Markdown-It." Run the following in the terminal:
yarn add markdown-it
We first need to add a template file in the src/templates
directory called ContentfulBlogPost.vue
. Within our new file, add the following code:
<template>
<Layout>
<div class="container justify-center content-center grid grid-cols-1 py-10 px-auto markdown px-6 xl:px-12 w-full max-w-3xl mx-auto xl:w-3/4">
<h1 class="text-2xl mb-2 text-center text-primary">{{$page.post.title}}</h1>
<p class="font-light text-sm text-center text-gray mb-6"> Posted on {{$page.post.date}} </p>
<div id="body" class="max-auto-sm text-left" v-html="body" />
</div>
</Layout>
</template>
<page-query>
query Post ($path: String!) {
post: contentfulBlogPost (path: $path) {
id,
title,
body,
date (format: "MMMM DD, YYYY"),
path
}
}
</page-query>
<script>
import MarkdownIt from "markdown-it";
export default {
computed: {
body() {
const md = new MarkdownIt();
return md.render(this.$page.post.body);
}
}
};
</script>
<style>
#body{
color: #2d3748;
}
#body h1 {
font-size: 20px;
padding-bottom: 10px;
padding-top: 10px;
}
#body hr{
padding-bottom: 10px;
}
#body pre{
background-color: #2d3748;
color: #a0aec0;
margin: 20px;
padding: 20px;
border-radius: 20px;
display: flex;
flex-wrap: wrap;
}
#body pre code{
overflow: scroll;
}
#body ul li{
list-style-position: inside;
list-style-type: square;
}
#body ol{
padding-top: 10px;
padding-bottom: 10px ;
font-size: 20px;
list-style-type: decimal;
list-style-position: inside;
}
</style>
Great! Let's quickly recap some of what we've completed thus far:
Now we're going to add the finishing touches to our website. We're going to modify our Default.vue layout, update the Index.vue page (aka, the home page), and we will add an About.vue page. Let's get started.
Our Default.vue layout is injected into every page on our site. So rather than having to code our header and footer on each page, we're going to add the code once in the Default.vue layout. This also makes it easy to maintain, should we want to make edits later on. Add the following code to your Default.vue
layout file:
<template>
<div class="layout">
<header class="md:flex md:items-center md:justify-around p-4 pb-0 shadow-lg md:pb-4">
<!-- Global navigation -->
<nav class="flex flex-wrap items-center justify-around text-primary font-bold">
<div class="">
<ul class="list-reset md:flex md:items-center">
<li class="md:ml-4">
<g-link class="nav__link block no-underline py-2 hover:text-darkgray md:border-none md:p-0" to="/">Home</g-link>
</li>
<li class="md:ml-4">
<g-link class="nav__link block no-underline hover:text-darkgray py-2 text-grey-darkest md:border-none md:p-0" to="/about/">About</g-link>
</li>
<li class="md:ml-4 inline-block leading-none invisible hover:text-darkgray lg:visible sm:invisible">
<a class="nav_link hover:text-2xl" href="your github url"> <font-awesome :icon="['fab', 'github']"/> </a>
</li>
<li class="md:ml-4 inline-block leading-none hover:text-darkgray invisible lg:visible sm:invisible ">
<a class="nav_link" href="your twitter url"><font-awesome :icon="['fab', 'twitter']"/></a>
</li>
</ul>
</div>
</nav>
<!-- END Global navigation -->
</header>
<slot/>
<footer class="mt-20 font-light text-gray w-full text-center border-grey p-4 pin-b text-primary">
<p class="text-sm">Copyright © ADD YOUR NAME HERE 2020</p>
<div class="justify-between hover-blue space-x-3">
<a href="your github"> <font-awesome :icon="['fab', 'github']"/> </a>
<a href="your twitter url"><font-awesome :icon="['fab', 'twitter']"/></a>
</div>
<div>
<p class="font-light text-sm">Developed using Gridsome, Tailwindcss, and Contentful</p>
</div>
</footer>
</div>
</template>
<static-query>
query {
metadata {
siteName
}
}
</static-query>
Now, let's update our index.vue page so we have something nice to greet our visitors with. Add the following code to the Index.vue
page:
<template>
<Layout>
<g-image alt="" src="" width="" />
<div class="pt-24">
<div class="container pb-20 px-3 mx-auto flex flex-wrap flex-col md:flex-row items-center">
<!--Left Col-->
<div class="flex flex-col w-full md:w-2/5 justify-center justify-between text-center md:text-left pb-10">
<p class="uppercase tracking-loose w-full text-primary">Headline text</p>
<h1 class="py-4 text-5xl font-bold leading-tight w-full text-primary">My Blog Site!!</h1>
<p class="leading-normal text-2xl pb-8 w-full text-primary">Subtitle</p>
<g-link class="text-2xl justify-center" to="/blog"><button class="bg-primary text-white font-bold hover:bg-darkgray rounded-full my-6 py-4 px-8 shadow-lg ">Blog</button></g-link>
</div>
<!--Right Col-->
<div class="w-full md:w-3/5 py-6 text-center">
<img class="w-full md:w-5/5 z-50" src="../images/undraw_feeling_proud_qne1.svg">
</div>
</div>
</div>
<section class="container mx-auto pt-6">
<h1 class="text-2xl font-bold text-primary text-center">Projects</h1>
</section>
</Layout>
</template>
<script>
export default {
metaInfo: {
title: 'Home'
}
}
</script>
<style>
.home-links a {
margin-right: 1rem;
}
</style>
Create a new file called About.vue
under src/pages
. Add in the following code, making sure to add information relevant to you in the spaces provided:
<template>
<Layout>
<div class="container justify-center px-auto mx-auto flex flex-wrap items-center">
<div class="justify-center px-auto mx-auto text-center">
<h1 class="text-2xl leading-tight mb-6 mt-4 text-primary">About Me</h1>
<!--
-->
<div class=" text-darkgray">
<p>Add your info here
</p>
<br>
<p>Add your info here
</p>
<br>
<p>Add your info here
</p>
</div>
</div>
</div>
</Layout>
</template>
<script>
export default {
metaInfo: {
title: 'About'
}
}
</script>
<page-query>
query Person {
person: allContentfulPerson {
edges {
node {
id,
shortBio
}
}
}
}
</page-query>
Congratulations! You've made it all the way through. At this point you should have all the parts needed to have a personal blog/resume site up and running with Gridsome and Contentful. With a few modifications and styling to your own brand, you can have it in tip top shape!