Hi there 👋
I’m Andrew, a Software Engineer, and a person who contributes to open source a lot. I have a blog based on gatsby and forked from lumen - the fast and flexible framework that makes building websites with any CMS, API, or database fun again.
Today I’m having fun with GraphQL for the first time in my life.
GraphQL is a query language for your API and a server-side runtime for executing queries using a type system you define for your data. GraphQL isn’t tied to any specific database or storage engine and is instead backed by your existing code and data.
Goal: fetch 10 public repositories, sorted by stars, descending order.
Here is Github GraphQL Explorer, it will help us with testing GraphQL queries.
First of all, take a look at a reference to API objects to determine what we need to use for pulling repositories. Let’s try to run the easiest query - fetch the first 10 repositories using explorer.
viewer {
repositories(first: 10) {
edges {
node {
id
name
url
}
}
}
}
Now, add a bit more complexity to the filtering. I want to see only public repositories I created and repositories from organizations I’m in. The following block into the repositories filter:
ownerAffiliations: [OWNER, ORGANIZATION_MEMBER], privacy: PUBLIC, isFork: false, isLocked: false
Adding ordering by stars:
orderBy: { field: STARGAZERS, direction: DESC }
Adding more data for fetching: stars, forks, owner, description, and the first 3 languages used in the repository. So, here is the final query we have:
viewer {
repositories(ownerAffiliations: [OWNER, ORGANIZATION_MEMBER], privacy: PUBLIC, isFork: false, isLocked: false, first: 10, orderBy: { field: STARGAZERS, direction: DESC }) {
edges {
node {
id
name
url
owner {
login
}
description
stargazers {
totalCount
}
forkCount
languages(first: 3) {
nodes {
id,
name
}
}
}
}
}
}
For now, we have the GraphQL query, and the last thing is to adapt it to gatsby’s website.
For running GraphQL queries outside our website, we need to install and configure gatsby-source-graphql.
The next step is extending Gatsby with a new page, we need to add a new template under ./src/templates
folder.
Let’s call it projects-template.js
with the following content:
import React from 'react';
import { graphql } from 'gatsby';
const ProjectsTemplate = ({ data }) => {
const { title: siteTitle, subtitle: siteSubtitle } = useSiteMetadata();
const { html: pageBody } = data.markdownRemark;
const { frontmatter } = data.markdownRemark;
const {
viewer: {
repositories: { edges },
},
} = data.github;
const { title: pageTitle, description: pageDescription = '', socialImage } = frontmatter;
const metaDescription = pageDescription || siteSubtitle;
const socialImageUrl = socialImage?.publicURL;
return (
<Layout title={`${pageTitle} - ${siteTitle}`} description={metaDescription} socialImage={socialImageUrl} >
<Sidebar />
<Page title={pageTitle}>
<div dangerouslySetInnerHTML={{ __html: pageBody }} />
<Projects edges={edges}/>
</Page>
</Layout>
);
};
export const query = graphql`
query ProjectsPage($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
id
html
frontmatter {
title
date
description
socialImage {
publicURL
}
}
}
github {
viewer {
repositories(ownerAffiliations: [OWNER, ORGANIZATION_MEMBER], privacy: PUBLIC, isFork: false, isLocked: false, first: 10, orderBy: { field: STARGAZERS, direction: DESC }) {
edges {
node {
id
name
url
owner {
login
}
description
stargazers {
totalCount
}
forkCount
languages(first: 3) {
nodes {
id,
name
}
}
}
}
}
}
}
}
`;
export default ProjectsTemplate;
After creating the template, we also need to extend Gatsby’s createPages
method, I have it located in ./gatsby/create-pages.js
.
Inside the section where gatsby iterates over the content pages, let’s add the following code:
const { edges } = result.data.allMarkdownRemark;
_.each(edges, (edge) => {
// ...
if (_.get(edge, 'node.frontmatter.template') === 'projects') {
createPage({
path: edge.node.fields.slug,
component: path.resolve('./src/templates/projects-template.js'),
context: {
slug: edge.node.fields.slug,
projectsCount: siteConfig.author.projects.count * 2,
},
});
}
});
Since that, we have 3 different markdown templates: post
, page
, and the new one projects
.
It’s time to create a new markdown page with content for the projects page in the path ./content/pages/projects.md
:
---
title: "Projects"
template: "projects"
socialImage: "/media/robo-andrew.jpg"
---
Here is the list of github projects I've contributed to:
The following part template: "projects"
defines for createPages
method what template should be used, therefore Gatsby needs to load the projects template from ./src/templates/projects-template.js
.
Okay, now all the bits are connected to each other. Let’s see the result 👇
Public GitHub projects from my profile are pulled using GraphQL api and integrated into Gatsby’s blog.
Check out the live version on the projects page.
Find out useful content at:
Any feedback, contribution, or help is highly appreciated.
Thanks for your time and happy coding! 👋