In this tutorial I’m going to show you how to create a simple blog using React, GraphQL and Cosmic JS. This is going to be the fastest and most light-weight blog built on a modern technology stack. Let’s get started.
View the demo
Install the Simple React Blog on Cosmic JS
View the codebase on GitHub
Make sure that you have Node.js and NPM installed on your machine, if not, visit the Node.js website to install the latest version.
Let’s start by creating a folder for our app. In your favorite terminal run the following commands:
mkdir simple-react-blog
cd simple-react-blog
Now let’s add a package.json file to import all of our dependencies for our app:
vim package.json
Add the following to our package.json file:
{
{
"scripts": {
"dev": "node server.js",
"build": "next build",
"start": "next build; NODE_ENV=production node server.js"
},
"dependencies": {
"axios": "^0.16.2",
"express": "^4.16.2",
"lodash": "^4.17.4",
"next": "^4.0.3",
"next-routes": "^1.1.0",
"react": "^16.0.0",
"react-dom": "^16.0.0"
}
}
It’s a pretty light dependency list for a pretty light app. So what we will install is:
Our scripts are necessary for starting our app in production and development.
Run the following command to install our dependencies:
npm i
Next, let’s begin building our blog pages. Create a pages folder and add the index.js file:
vim index.js
and add the following to index.js:
import axios from 'axios'
import _ from 'lodash'
import Footer from './partials/footer'
import Header from './partials/header'
import helpers from '../helpers'
import config from '../config'
export default class extends React.Component {
static async getInitialProps({ req }) {
const query = `{
objects(bucket_slug: "${config.bucket.slug}") {
_id
type_slug
slug
title
metadata
created_at
}
}`
return await axios.post(`https://graphql.cosmicjs.com/v1`, { query })
.then(function (response) {
return {
cosmic: {
posts: _.filter(response.data.data.objects, { type_slug: 'posts' }),
global: _.keyBy(_.filter(response.data.data.objects, { type_slug: 'globals' }), 'slug')
}
}
})
.catch(function (error) {
console.log(error)
})
}
render() {
if (!this.props.cosmic)
return <div>Loading...</div>
return (
<div>
<Header cosmic={ this.props.cosmic }/>
<main className="container">
{
this.props.cosmic.posts &&
this.props.cosmic.posts.map(post => {
const friendly_date = helpers.friendlyDate(new Date(post.created_at))
post.friendly_date = friendly_date.month + ' ' + friendly_date.date
return (
<div className="card" data-href={`/${post.slug}`} key={post._id}>
{
post.metadata.hero.imgix_url &&
<a href={`/${post.slug}`} className="blog-post-hero blog-post-hero--short" style={{ backgroundImage: `url(${post.metadata.hero.imgix_url})`}}></a>
}
<div className="card-padding">
<h2 className="blog__title blog__title--small">
<a href={`/${post.slug}`}>{post.title}</a>
</h2>
<div className="blog__author">
<a href={`/author/${post.metadata.author.slug}`}>
<div className="blog__author-image" style={{ backgroundImage: `url(${post.metadata.author.metafields[0].imgix_url}?w=100)`}}></div>
</a>
<div className="blog__author-title">by <a href={`/author/${post.metadata.author.slug}`}>{post.metadata.author.title}</a> on {post.friendly_date}</div>
<div className="clearfix"></div>
</div>
<div className="blog__teaser droid" dangerouslySetInnerHTML={{__html: post.metadata.teaser}}></div>
<div className="blog__read-more">
<a href={`/${post.slug}`}>Read more...</a>
</div>
</div>
</div>
)
})
}
</main>
<Footer />
</div>
)
}
}
There are a few things happening here:
cosmic
object. And use lodash to parse through Posts and Global Object types.For our single post, we add a post
property to our props. Post is found by matching the query.slug to the Object slug:
const gql_query = `{
objects(bucket_slug: "${config.bucket.slug}") {
type_slug
slug
title
content
metadata
created_at
}
}`
return await axios.post(`https://graphql.cosmicjs.com/v1`, { query: gql_query })
.then(function (response) {
return {
cosmic: {
posts: _.filter(response.data.data.objects, { type_slug: 'posts' }),
global: _.keyBy(_.filter(response.data.data.objects, { type_slug: 'globals' }), 'slug'),
post: _.find(response.data.data.objects, { slug: query.slug }),
}
}
})
.catch(function (error) {
console.log(error)
})
}
Check out the full file on GitHub.
This is the abridged version of the Simple React Blog available for download in the Cosmic JS Apps page. The full codebase includes a single post page view as well as a page dedicated to each author’s posts. View the full codebase on GitHub and deploy this app in a few clicks from your Cosmic JS dashboard by installing the app to your Cosmic JS Bucket.
**Recommended Courses: **
React.js: Building Production Ready Apps, Start to Finish
☞ https://goo.gl/pLNkRu
Build a Reddit-Like Messaging Board with React and Firebase
☞ https://goo.gl/gpe3Sx
Complete React JS web developer with ES6 - Build 10 projects
☞ https://goo.gl/6ZWtyS
Learn React : The World’s Most Lucrative JavaScript Library
☞ https://goo.gl/5DtSEu
☞ JavaScript for React Developers | Mosh
☞ React Tutorial - Learn React - React Crash Course [2019]
☞ Learn React - Full Course for Beginners - React Tutorial 2019
☞ JavaScript Programming Tutorial Full Course for Beginners
☞ Learn JavaScript - Become a Zero to Hero
☞ Page Transitions In React - React Router V6 and Framer Motion Tutorial