A reusable template for building blog websites with MyST Markdown, RSS/Atom feed generation, tag-based navigation, and automated deployment via GitHub Actions.
- MyST Markdown source format with Jupyter notebook integration
- Blog with RSS and Atom feed generation
- Tag-based navigation in the sidebar for browsing posts by topic
- Giscus comments (GitHub-backed) for blog posts
- GitHub Pages deployment on push to
main - Netlify PR previews for pull request review
- Pre-commit hooks: Black, codespell, nbstripout for code quality
- Click Use this template on GitHub to create a new repository
- Update
myst.ymlwith your site title, description, and table of contents - Replace sample posts in
posts/with your own - Add or update tag pages in
tags/to match your post tags - Update
generate_rss.pywith your site URL and metadata - Push to GitHub to trigger automated builds
.
├── myst.yml # MyST configuration
├── index.md # Landing page (blog post gallery)
├── custom.css # Custom CSS styling
├── requirements.txt # Python dependencies
├── generate_rss.py # RSS/Atom feed generation script
├── inject_comments.py # Giscus comment injection script
├── Dockerfile # Docker build for full site
├── logo.png # Site logo
├── fav.ico # Favicon
├── CNAME # Custom domain (optional)
├── posts/ # Blog posts
│ ├── sample-post.md # Sample blog post
│ └── images/ # Shared images
├── tags/ # Tag pages (sidebar navigation)
│ ├── myst-markdown.md # Posts tagged "MyST Markdown"
│ ├── tutorial.md # Posts tagged "Tutorial"
│ └── github-pages.md # Posts tagged "GitHub Pages"
├── .pre-commit-config.yaml # Pre-commit hook configuration
├── CONTRIBUTING.md # Contribution guidelines
├── CONDUCT.md # Code of conduct
└── .github/workflows/
├── build.yml # PR preview builds (Netlify)
└── deploy.yml # Production deployment (GitHub Pages)
Edit myst.yml:
project.title: your blog nameproject.description: site descriptionproject.keywords: your blog keywordssite.parts.footer: footer links (social profiles)
- Create a new
.mdfile inposts/with frontmatter (title, date, authors, description, tags) - Add a card entry in
index.mdlinking to the new post - Update relevant tag pages in
tags/to include the new post
- Create a new
.mdfile intags/with a card grid listing posts for that tag - Add the file to
project.tocunder the Tags section inmyst.yml
pip install -r requirements.txt
npm install -g mystmd
myst build --htmlThe built site will be in _build/html/.
pip install feedgen pyyaml
python generate_rss.pyReads frontmatter from posts/*.md and writes rss.xml and atom.xml.
Build and serve the site without installing any dependencies locally:
docker build -t myst-blog-template .
docker run --rm -p 3000:3000 -p 3100:3100 myst-blog-templateThen open http://localhost:3000 in your browser. If port 3000 is already in use, map to different ports (e.g., -p 3001:3000 -p 3101:3100 and open http://localhost:3001).
Pushes to main trigger the deploy.yml workflow, which:
- Builds the HTML site with MyST
- Generates
rss.xmlandatom.xmlfrom blog posts - Deploys everything to GitHub Pages
Pull requests trigger the build.yml workflow for preview deployments. Requires NETLIFY_AUTH_TOKEN and NETLIFY_SITE_ID secrets.
Giscus adds a GitHub-backed comment section to each blog post. To enable it:
- Go to giscus.app and follow the configuration steps for your repository
- Enable GitHub Discussions on your repository (Settings > General > Features > Discussions)
- Open
inject_comments.pyand replace the placeholder values with your Giscus configuration:data-repo: yourusername/repodata-repo-id: your repository ID (provided by giscus.app)data-category: the Discussions category to use (e.g.,General)data-category-id: the category ID (provided by giscus.app)
- The repository includes a custom
giscus-light.csstheme for light mode.inject_comments.pycopies it into_build/html/during deployment and keeps dark mode on Giscus's built-in dark theme. - The
deploy.ymlworkflow already runspython inject_comments.pyduring deployment, so comments will appear on the next push tomain
| Secret | Purpose |
|---|---|
NETLIFY_AUTH_TOKEN |
Netlify authentication for PR previews |
NETLIFY_SITE_ID |
Netlify site ID for PR previews |