The simplest way to run a blog on GitHub Pages.
Fork this repo (or use it as a template). Enable GitHub Pages. You have a blog. That's it.
No CLI to install. No config files to learn. No build tools on your machine. Write Markdown, push to GitHub, your site updates automatically.
See it in action: Live demo
- Fork this repository
- Go to Settings > Pages > Source: GitHub Actions
- Your blog is live at
https://YOUR-USERNAME.github.io/skunk-html/
To publish a post: add a Markdown file to the markdown-blog/ folder. The file name is the date - name it like 2025-03-24.md and start the file with a # Title heading. The title comes from the heading, the date comes from the file name. Push. Done.
- Zero local setup - everything runs on GitHub Actions
- Markdown -> HTML - write in Markdown, get a clean website
- RSS feed - your readers can subscribe (
/feed.xml) - Sitemap - search engines find your content (
/sitemap.xml) - SEO meta tags - Open Graph and Twitter Cards out of the box
- 404 page - a "not found" page in your site's style, generated automatically
- Dark mode - respects your visitors' system preference automatically
- Themes - choose from built-in color themes or tweak CSS variables
- Comments - optional Giscus integration
- Syntax highlighting - code blocks are highlighted automatically
- No dependencies on your machine - no Node.js, no Ruby, no Go
Edit Config.fs - you only need to change the values in quotes:
let siteTitle = "My Blog"
let siteDescription = "A blog powered by SkunkHTML"
let siteBaseUrl = "https://YOUR-USERNAME.github.io/skunk-html" // No trailing slash
let siteLanguage = "en"
let siteAuthor = "Your Name"
let siteImage = "assets/avatar.jpg" // Preview image for social sharesYou don't need to know F# - just edit the text between the quotation marks. The same file also contains the interface texts (like the "blog entries" heading and the 404 page messages) - translate them if your blog is not in English.
Base URL examples - set siteBaseUrl to match where your site is hosted:
- GitHub project page:
https://YOUR-USERNAME.github.io/skunk-html - GitHub user page (repo named
<user>.github.io):https://YOUR-USERNAME.github.io - Custom domain:
https://example.com - Self-hosted with subpath:
https://example.com/blog
SkunkHTML ships with multiple color themes. To switch themes, copy the contents of a theme file from themes/ into css/tweaks.css:
| Theme | File | Style |
|---|---|---|
| Default | css/tweaks.css |
Clean, minimal with dark mode |
| Ocean | themes/theme-ocean.css |
Cool blue tones (GitHub-inspired) |
| Terminal | themes/theme-terminal.css |
Green-on-dark hacker aesthetic |
| Ink | themes/theme-ink.css |
Warm serif typography (newspaper-inspired) |
All themes respect prefers-color-scheme - they look great in both light and dark mode.
- Blog posts: Markdown files in
markdown-blog/whose names start with a digit. The file name is the publication date (e.g.2025-03-24.md). The post title comes from the first# Headinginside the file. - Other pages: Markdown files in
markdown-blog/that don't start with a digit (e.g.about.md,featured.md) - Front page:
markdown-blog/index.md- optional welcome content displayed above the post list
Customize the header, footer, and page head by editing files in html/:
header.html- site navigation and logofooter.html- footer contenthead.html- meta tags, CSS links, and faviconsscript_giscus.html- Giscus comments configuration
skunk-html/
├── .github/workflows/ # GitHub Actions build & deploy
├── assets/ # Avatar, favicon, shared resources
├── css/ # Stylesheets (styles.css + tweaks.css)
├── fonts/ # Custom fonts
├── html/ # HTML fragments (header, footer, head)
├── markdown-blog/ # Your content goes here
│ └── images/ # Images used in articles
├── scripts/ # Syntax highlighting script
├── themes/ # Alternative color themes
├── Config.fs # Your site settings (title, URL, texts)
├── SkunkUtils.fs # Utility functions
├── SkunkHtml.fs # HTML generation engine
├── Program.fs # Build entry point
└── skunk-html.fsproj # F# project file
To pick up engine improvements later, use GitHub's Sync fork button (or merge upstream manually). Everything that makes your blog yours lives in Config.fs and the content folders (markdown-blog/, html/, css/, assets/, fonts/) - engine updates normally don't touch those, so syncing merges cleanly.
You don't need this for normal use - GitHub Actions handles everything. But if you want to preview locally:
git clone https://github.com/mg0x7BE/skunk-html.git
cd skunk-html
dotnet restore
dotnet runYour site will be in skunk-html-output/. Requires .NET.
When you push a Markdown file to markdown-blog/, GitHub Actions runs a small F# program that converts your Markdown to HTML using FSharp.Formatting, generates RSS and sitemap, wraps everything in a clean layout based on MVP.css, and deploys to GitHub Pages.
The entire build engine is ~400 lines of F#. No frameworks. No plugins. No magic.
Suggestions, bug reports, and pull requests welcome. Use discussions, issues, or PRs.
Unlicense - do whatever you want with it.
- MVP.css - styling
- microlight.js - syntax highlighting
- FSharp.Formatting - Markdown processing
