Skip to content

Gatsby Mini Project — Build a Complete Gatsby Site

DodaTech Updated 2026-06-28 4 min read

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

How do I add a CMS to this portfolio?

: Add gatsby-source-contentful and create pages from Contentful entries alongside the Markdown content.

Can I use this as a template for client projects?

: Yes. Fork the project, replace content, update branding, and deploy. It's production-ready.

How do I add animations?

: Use CSS transitions, framer-motion through preact/compat, or react-spring for page transitions.

Can I add e-commerce?

: Integrate gatsby-source-Shopify or gatsby-source-woocommerce for headless commerce.

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