Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Build a Modern Developer Blog with MyST Markdown and GitHub Pages

A good developer blog should be fast, static, easy to write in, and version controlled from day one. It should also let readers comment without forcing you to stand up a separate database or pay for a hosted commenting service. In this tutorial, I show you how to build exactly that kind of blog with the myst-blog-template and deploy it for free to GitHub Pages. Comments are backed by GitHub Discussions through Giscus, so the whole site remains static while still feeling interactive.

You can see the live demo to get a sense of what the finished blog looks like, and the source code is on GitHub.

Video tutorial: Build a Modern Developer Blog with MyST Markdown and GitHub Pages

What You Will Need

That is it. Everything else (the build, the deploy, the comment widget) is wired up for you by the template.

What the Template Delivers

Out of the box, the template gives you:

Create Your Repository from the Template

  1. Go to the myst-blog-template repository on GitHub.

  2. Click the green Use this template button in the upper right, then select Create a new repository.

  3. Choose your GitHub account as the owner and give the repository a name (for example, my-blog). The name becomes part of your URL, so keep it short and memorable.

  4. Optionally add a description like “Website for my blog.”

  5. Set the repository to Public or Private depending on whether you want others to see the source. The deployed site is public either way.

  6. Click Create repository. GitHub copies the template and then starts the first deployment workflow.

Enable GitHub Pages

The first automatic deploy will usually fail because GitHub Pages is not enabled yet. To fix that:

  1. Go to the new repository’s Settings tab.

  2. In the left sidebar, click Pages.

  3. Under Build and deployment, change the source to GitHub Actions.

  4. Go back to the Actions tab. Click into the failed workflow run and choose Re-run failed jobs.

  5. After a minute or two, the site goes live at https://username.github.io/repo-name.

To make the URL easy to find later, open the repository’s About section (the gear icon on the main page), check Use your GitHub Pages website, and save. The URL now appears at the top of the repository page.

Enable GitHub Discussions

Giscus stores every blog comment as a GitHub Discussion, so you need to turn that feature on before comments can work:

  1. Go to Settings and scroll down to the Features section.

  2. Check the box next to Discussions, then click Set up discussions and accept the default welcome post.

While you are in settings, two small preferences are worth enabling:

Neither is required, but both keep the repository history tidy.

Clone and Preview Locally

Clone the repository to your local machine so you can edit content in your editor:

git clone https://github.com/username/my-blog.git
cd my-blog

Install the Python dependencies listed in requirements.txt:

pip install -r requirements.txt

Then start the local development server:

myst start

The site is served at http://localhost:3000. Any change you save to a Markdown file is reflected in the browser almost instantly. For a comfortable editing experience, split your editor window and open the preview URL in the built-in browser panel, so the source and the rendered page sit side by side.

Add a New Blog Post

All posts live in the blog/ directory. To add a new post, create a file there with a short, descriptive name:

blog/my-first-post.md

Start the file with a YAML frontmatter block, then write the post body in Markdown:

---
title: "Build a Blog with MyST Markdown"
description: A step-by-step tutorial on building a blog with MyST Markdown.
thumbnail: https://example.com/my-thumbnail.jpg
keywords:
  - MyST Markdown
  - Blog
---

# Build a Blog with MyST Markdown

A short opening paragraph describing what the post covers.

After creating the post, register it on the homepage by adding a new card to the grid at the top of index.md:

:::{card} Build a Blog with MyST Markdown
:link: ./blog/my-first-post
:header: ![thumbnail](https://example.com/my-thumbnail.jpg)
April 22, 2026 – A step-by-step tutorial on building a blog with MyST Markdown.
:::

Inside the post body, you can use anything MyST Markdown supports. For example, embed an image with standard Markdown syntax:

![Caption text](https://example.com/image.jpg)

Or embed a YouTube video with the iframe directive:

:::{iframe} https://www.youtube.com/embed/VIDEO_ID
:width: 100%
A short caption describing the video.
:::

Save the file and the local preview updates immediately. The post now shows on the homepage card grid and has its own page at /blog/my-first-post.

Organize Posts with Categories

The sidebar is organized into category pages (MyST Markdown, GitHub Pages, Blog, and so on). Each category is just another Markdown file with its own card grid, listing only the posts that belong to that category.

To add an existing post to a category, open the category file (for example, myst-markdown.md) and add the same card entry you used on the homepage. A post can appear in several categories by adding the card to each relevant file.

To add a new category, create a new Markdown file at the project root (for example, geoai.md), add a heading and a card grid, and then register the file in myst.yml so it appears in the sidebar. Add the entry before the contact entry so the ordering reads naturally:

toc:
  - file: index.md
  - file: myst-markdown.md
  - file: github-pages.md
  - file: blog.md
  - file: geoai.md
  - file: contact.md

Save myst.yml and the new category shows up in the sidebar immediately.

Set Up Giscus Comments

Comments on each blog post are rendered by Giscus, which writes every comment as a GitHub Discussion on your repository. You need to tell the template which repository and which discussion category to use.

First, go to giscus.app and follow the configuration wizard:

  1. In the Repository field, paste your repo in username/repo-name format. The page checks whether the Giscus GitHub App is installed on that repository. If it is not, click the install link, pick your repository, and save.

  2. Choose how discussions are mapped to posts. The default (pathname) works well for most blogs.

  3. Pick a discussion category. General is a reasonable default. Announcements-only categories will not work, since Giscus needs to create new discussions from visitor comments.

  4. Scroll down and note the four values: data-repo, data-repo-id, data-category, and data-category-id. You need all four.

Next, open inject_comments.py in the root of your repository and replace the four corresponding values with the ones from the Giscus page. The script runs after myst build --html as part of the GitHub Actions workflow and injects the Giscus widget into each built blog post page. That is why the comment widget works even though the site itself is fully static.

Commit and push the updated inject_comments.py. Once the next GitHub Actions run finishes, open any post on your deployed site and scroll to the bottom. You should see the Giscus widget with a Sign in with GitHub button. After you sign in, you can write comments using standard Markdown, including code blocks, lists, and images. Each new comment shows up as a GitHub Discussion in your repository, and replies from Discussions are mirrored back onto the post in real time.

Customize the Branding

Two small files control the visual identity of your blog:

The site footer is defined near the bottom of myst.yml. Open that file, scroll to the footer section, and edit the links to point to your own personal website, social accounts, or anything else you want visitors to find.

Deploy and Verify

Once you are happy with the changes, commit and push to GitHub:

git add .
git commit -m "Add my first blog post"
git push

GitHub Actions rebuilds the site, runs the comment injection script, and redeploys to GitHub Pages. After a minute or two, refresh your site and verify that:

Leave a test comment from your own account. The comment appears on the post page and, at the same time, shows up in the Discussions tab of your repository. Replies work the same way in both directions.

Optional: Custom Domain

By default, your site is served at username.github.io/repo-name. To use a custom domain instead:

  1. Open the CNAME file at the repository root and replace the placeholder domain with your own (for example, myblog.com). Keeping the domain in CNAME means every deploy preserves it automatically, so you do not need to re-enter it in the GitHub Pages settings after each push.

  2. Update your domain’s DNS records to point to GitHub Pages, as described in GitHub’s custom domain documentation.

  3. In Settings > Pages, enter your custom domain and click Save.

After DNS propagation (usually a few minutes to a few hours), the site is served at your custom domain.

What is Next

This tutorial covers the full workflow from template to a deployed blog with working comments. If you want a personal website instead of a blog, see Build a Personal Website in 5 Minutes: No Coding Required and A Reusable Template for Building Websites with MyST Markdown. For a website that also generates a PDF CV from the same Markdown sources, check out Build a Professional CV Website with Auto PDF Generation Using MyST Markdown. If you are writing a journal article, the MyST article template walkthrough shows how to produce both a PDF and a website from a single source.

The MyST Markdown guide is the best reference for every directive and role the template supports, and the Giscus documentation covers more advanced configuration options for comments.

If you build your own blog with this template, feel free to share the link on social media. I would love to see what you publish.