Gatsby Mini Project — Build a Complete Gatsby Site
In this tutorial, you will learn about Gatsby Mini Project. We cover key concepts, practical examples, and best practices to help you master this topic.
Build a complete Gatsby site from scratch: a portfolio blog with Markdown, CMS content, image optimization, SEO, and PWA features for production.
In this lesson, you'll apply everything you've learned to build a real-world Gatsby portfolio and blog.
What You'll Learn
How to architect a Gatsby site, combine multiple data sources, implement all optimization features, and deploy with CI/CD.
Why It Matters
Building a complete project solidifies your understanding and creates a portfolio piece you can show potential employers or clients.
flowchart TD
A[Portfolio Site] --> B[Home Page]
A --> C[Blog]
A --> D[Portfolio]
A --> E[About]
B --> F[Featured Projects]
B --> G[Recent Posts]
C --> H[Post Pages]
C --> I[Tag Pages]
C --> J[Pagination]
D --> K[Project Pages]
E --> L[Bio + Skills]
style A fill:#639,color:#fff
Project Structure
portfolio/
├── content/
│ ├── blog/ # Markdown blog posts
│ └── projects/ # Markdown project descriptions
├── src/
│ ├── components/ # Header, Footer, SEO, Cards
│ ├── pages/ # Home, Blog, Portfolio, About
│ ├── templates/ # Blog post, Project, Tag archive
│ └── styles/ # Global CSS, CSS Modules
├── static/ # Favicon, fonts, robots.txt
├── gatsby-config.js
├── gatsby-node.js
└── package.json
gatsby-config.js
module.exports = {
siteMetadata: {
title: 'Jane Developer',
description: 'Full-stack developer and writer. Building secure, performant web applications.',
siteUrl: 'https://jane-dev.example.com',
author: 'Jane Developer'
},
plugins: [
'gatsby-plugin-react-helmet',
'gatsby-plugin-image',
'gatsby-plugin-sharp',
'gatsby-transformer-sharp',
{
resolve: 'gatsby-source-filesystem',
options: { name: 'blog', path: `${__dirname}/content/blog/` }
},
{
resolve: 'gatsby-source-filesystem',
options: { name: 'projects', path: `${__dirname}/content/projects/` }
},
'gatsby-transformer-remark',
'gatsby-plugin-sitemap',
{
resolve: 'gatsby-plugin-manifest',
options: { name: 'Jane Developer', short_name: 'JaneDev', start_url: '/', background_color: '#639', theme_color: '#639', icon: 'src/images/icon.png' }
},
'gatsby-plugin-offline'
]
};
gatsby-node.js
const path = require('path');
const { createFilePath } = require('gatsby-source-filesystem');
exports.onCreateNode = ({ node, getNode, actions }) => {
const { createNodeField } = actions;
if (node.internal.type === 'MarkdownRemark') {
const slug = createFilePath({ node, getNode });
createNodeField({ node, name: 'slug', value: slug });
}
};
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions;
const result = await graphql(`
query {
posts: allMarkdownRemark(
filter: { fileAbsolutePath: { regex: "/content/blog/" } }
sort: { frontmatter: { date: DESC } }
) { nodes { fields { slug } frontmatter { tags } } }
projects: allMarkdownRemark(
filter: { fileAbsolutePath: { regex: "/content/projects/" } }
) { nodes { fields { slug } } }
}
`);
// Create blog post pages
const posts = result.data.posts.nodes;
posts.forEach((post, i) => {
createPage({
path: `/blog${post.fields.slug}`,
component: path.resolve('./src/templates/blog-post.js'),
context: {
slug: post.fields.slug,
prev: i < posts.length - 1 ? posts[i + 1].fields.slug : null,
next: i > 0 ? posts[i - 1].fields.slug : null
}
});
});
// Create project pages
result.data.projects.nodes.forEach(project => {
createPage({
path: `/portfolio${project.fields.slug}`,
component: path.resolve('./src/templates/project.js'),
context: { slug: project.fields.slug }
});
});
// Create tag pages
const tags = [...new Set(posts.flatMap(p => p.frontmatter.tags || []))];
tags.forEach(tag => {
createPage({
path: `/tags/${tag}/`,
component: path.resolve('./src/templates/tag.js'),
context: { tag }
});
});
};
Features Implemented
- Blog: Markdown posts with tags, pagination, prev/next navigation
- Portfolio: Project showcase pages with images and descriptions
- SEO: Meta tags, Open Graph, JSON-LD schema per page
- Images: Optimized with
gatsby-plugin-image, AVIF/WebP, lazy loading - PWA: Manifest, service worker, offline support
- Sitemap: Auto-generated
sitemap.xml - RSS: Feed for blog subscribers
- Performance: Code splitting, image optimization, preloading
- CI/CD: GitHub Actions deploy to Netlify
Running the Project
gatsby develop
Output: The portfolio site runs at http://localhost:8000 with full hot-reloading.
gatsby build && gatsby serve
Output: Production build at http://localhost:9000. Lighthouse score: 95+ Performance, 100 Accessibility, 100 Best Practices, 100 SEO.
Mini Project Checklist
- Home page with featured projects and recent posts
- Blog with pagination (6 posts per page)
- Individual post pages with prev/next navigation
- Project portfolio pages
- Tag archive pages
- About page with bio
- SEO component on every page
- Image optimization with gatsby-plugin-image
- PWA with offline support
- Sitemap and RSS feed
- Production Lighthouse scores 95+
Extend the project: add a contact form with Gatsby Function, dark mode toggle, search with gatsby-plugin-local-search, or comments with a third-party service.
FAQ
Congratulations
You've completed the Gatsby course. You now have a solid foundation in Gatsby development — from installation and configuration to advanced topics like SSR, DSG, Functions, and deployment. Continue building Gatsby sites and refer back to individual lessons when you need a refresher.
Return to the Gatsby course home to review any lesson or explore other web frameworks.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro