Pull to refresh

Gatsby and its Greatness

Level of difficultyEasy
Reading time6 min
Views404

I’m Aleksei Volkov, a front-end engineer at Luxoft. Our clients often present new requirements, but our focus remains on cost savings. A single application can replace days of bureaucracy, and a single line of code can carry a hefty price tag.

As part of my role, I prioritize choosing the right tools. To tackle server-related expenses, AWS bills, and Google FCP metrics, I’ve delved into serverless technologies. My preferred way to showcase achievements? Blogging.


The Evolution of Blogging

In the internet’s early days, blogging was straightforward. A server with PHP and MySQL allowed you to share your thoughts globally. Even FTP access with an index.html file sufficed.

However, as the web evolved, so did blogging requirements. Non-programmers needed user-friendly web interfaces, faster loading times, and seamless daily publishing. Platforms like Reddit, WordPress, and Tumblr emerged, but they faced a common issue: website ownership.

LinkedIn load up to 30 MB of JavaScript
LinkedIn load up to 30 MB of JavaScript

Today, hosting a basic blog still requires purchasing MySQL and PHP hosting. Notably, popular personal sites like LinkedIn load up to 30 MB of JavaScript. But is there a simpler, nearly free way? Can we publish weekly serving just an HTML file and using a WYSIWYG editor? 🤔


A New Way of Storing and Distributing Content

Sanity IO

Sanity Editor
Sanity Editor

Sanity IO is a headless CMS that empowers you to create and host content exclusively under your control. Here’s what makes it stand out:

  1. Customizable WYSIWYG: The WYSIWYG (What You See Is What You Get) editor is fully configurable. You decide how your content appears to your audience.

  2. Portable Text: A novel way of distributing content, similar to old-school HTML. You create content blocks in the editor, and then these blocks can be rendered differently by various frontends based on their values and parameters.

  3. Export and Import: Seamlessly move your content in and out of Sanity IO.

In essence, Sanity IO liberates content creators, developers, and users by providing a flexible and tailored content management experience.

GatsbyJS

Gatsby deploy
Gatsby deploy

GatsbyJS is a powerful static site generator that streamlines web development. Here’s why it’s a game-changer for bloggers and writers:

  1. Static HTML/CSS/JS Bundle: Gatsby fetches data, styles, and logic during the build process and compiles them into static files. Your blog becomes a collection of lightweight, pre-rendered pages, reducing server load and enhancing loading speed for readers.

  2. Magic of Build Time: Similar to NextJS or server-side rendering techniques, Gatsby performs its magic during the build phase. When a user visits your site, their browser reads only the HTML and CSS — no server-side processing required.

  3. Perfect for Static Sites: Whether you’re a blogger, writer, or running a content-focused site, Gatsby is an ideal choice. Plus, it plays well with GitHub Pages.


Installation and Configuration

Sanity IO

  1. Sign Up: Create an account on Sanity IO.

  2. Project Creation: Set up a new project.

  3. Schema Configuration: Define your content schema.

  4. Start Creating: With everything set up, dive into content creation right away!

To get started, visit the Sanity documentation and install the command-line interface and Sanity Studio.

npm install - global sanity@latest

Additionally, consider installing @sanity/code-input for pasting code examples.

So your sanity.config.ts would be like next example. Rest plugins are not needed for now.

// sanity.config.ts
import {structureTool} from 'sanity/structure'
import {schemaTypes} from './schemaTypes'
import {codeInput} from '@sanity/code-input'

export default {
  name: 'default',
  title: 'My Sanity Project',

  projectId: 'odwqzjob',
  dataset: 'production',

  plugins: [structureTool(), codeInput()],

  schema: {
    types: schemaTypes,
  },
}

Hit npm run deploy to get an online Editor for your content (local writing is also possible). And finally npm run deploy-graphql to publish api for frontend part.

GatsbyJS

GatsbyJS requires a bit more setup. You’ll need to install the Gatsby CLI, create a new site, and then configure your sources and plugins. However, once you’ve done that, you can start building your site.

Start with documentation and install command line interface for GatsbyJS. For minimal start it’s needed to configure main page, config file and single blog post file.

npm init gatsby
cd my-gatsby-site
npm run develop

GatsbyJS uses GraphQL to fetch data, so use it to get sanity posts. Do the same for single post, but also get _rawBody field which represents Portable Text. It can be rendered with official plugin. Then, the only task is left is making post pages on build time — so configure gatsby-node.ts.

// index.tsx
import { HeadFC, PageProps, graphql } from "gatsby";
import React from "react";

function IndexPage({ data }: PageProps<Queries.ArticlesQuery>) {
  const articles = data.allSanityPost.nodes;
  return (
    <div>
      <h1>Home Page</h1>
      <ul>
        {articles.map((article) => (
          <li key={article.id}>
            <a href={article.slug?.current}>{article.title}</a> (
            {article.publishedAt})
          </li>
        ))}
      </ul>
    </div>
  );
}

export default IndexPage;

export const Head: HeadFC = () => <title>Home Page</title>;

export const articlesQuery = graphql`
  query Articles {
    allSanityPost(sort: { publishedAt: DESC }, limit: 100) {
      nodes {
        slug {
          current
        }
        title
        id
        publishedAt(formatString: "DD.MM.YYYY")
      }
    }
  }
`;
// Post.tsx
import * as React from "react";
import { graphql, Link, type HeadProps, HeadFC } from "gatsby";
import { PortableText } from "@portabletext/react";
import type { PortableTextBlock } from "@portabletext/types";

import portableTextComponents from "../utils/portableText";

function Post({ data }: { data: Queries.PostQuery }) {
  const post = data?.sanityPost;

  if (post == null) {
    return (
      <p>
        Post not found. Go <Link to="/">to home page</Link>.
      </p>
    );
  }

  return (
    <article>
      <header>
        <h1>{post.title}</h1>
        <p>
          <time dateTime={post.publishedAt}>{post.publishedAt}</time>
        </p>
      </header>
      <main>
        {post._rawBody != null && (
          <PortableText
            value={post._rawBody as unknown as PortableTextBlock[]}
            components={portableTextComponents}
          />
        )}
      </main>
    </article>
  );
}

export default Post;

export const Head = ({ data }: HeadProps<Queries.PostQuery>) => {
  const postTitle = data.sanityPost?.title ?? "";

  return <title>{postTitle}</title>;
};

export const PostQuery = graphql`
  query Post($slug: String!) {
    sanityPost(slug: { current: { eq: $slug } }) {
      id
      title
      publishedAt(formatString: "DD.MM.YYYY")
      _rawBody
    }
  }
`;
// gatsby-node.ts
import { type CreatePagesArgs, type GatsbyNode } from "gatsby";
import path from "path";

async function turnPostsIntoPages({
  graphql,
  actions,
}: CreatePagesArgs): Promise<void> {
  // 1. Get a template for this page
  const postTemplate = path.resolve("./src/templates/Post.tsx");
  // 2. Query all posts
  const {
    data,
  }: {
    data?: {
      allSanityPost: {
        nodes;
      };
    };
  } = await graphql(`
    query AllPosts {
      allSanityPost(sort: { publishedAt: DESC }, limit: 100) {
        nodes {
          title
          slug {
            current
          }
        }
      }
    }
  `);

  const posts = data?.allSanityPost?.nodes ?? [];
  // 3. Loop over each post and create a page for that post
  posts.forEach(function createPostPage(post) {
    console.log("📄 Creating page for Article:", post.title);
    actions.createPage({
      path: post.slug.current,
      component: postTemplate,
      context: {
        slug: post.slug.current,
      },
    });
  });
}

export const createPages: GatsbyNode["createPages"] =
  async function createPages(params) {
    Promise.all([turnPostsIntoPages(params)])
      .then(function logSuccess() {
        console.log("✅ Finished creating pages.");
      })
      .catch(function logError(error) {
        console.error("❌ Failed to create pages:", error);
      });
  };

Done! You have Sanity Editor in the Internet, now you can publish Gatsby part in GitHub pages of in Netlify.


Conclusion

When comparing traditional blogging to static blogging, several key differences emerge.

  1. Traditional Blogging:

  • Requires a constantly running server, which can be expensive.

  • Involves fetching requests in React, potentially slowing down your site.

  1. Static Blogging with Sanity IO and GatsbyJS:

  • Eliminates the need for an always-on server.

  • Stores content in a headless CMS and serves it as static files, reducing costs and improving load speed.

In 2024, services like Sanity IO and GatsbyJS empower content creators by offering database services, full content control, and zero-cost hosting for static HTML files. Why not give it a try? Create a Gatsby website today, fetch your existing data, and stay tuned for more insights from Luxoft! 🚀

Tags:
Hubs:
+2
Comments0

Articles