Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for How to Create a Static Site Generator with Go
Ekemini Samuel
Ekemini Samuel

Posted on

     

How to Create a Static Site Generator with Go

Static site generators are powerful tools that simplify the creation of lightweight, fast, and scalable websites. Whether you're building blogs, documentation, or small business sites, they transform content written in Markdown into efficient, static HTML files.

In this guide, we’ll create aStatic Site Generator (SSG) inGo, a programming language renowned for its performance, simplicity, and concurrency. We’ll build a CLI tool that takes Markdown files as input, processes them using a predefined HTML template, and outputs beautiful, static HTML pages.


Why Build This?

A static site generator can serve several practical purposes:

  • Documentation Sites: Generate fast-loading sites for technical documentation.
  • Blogs: Write your content in Markdown and deploy it effortlessly.
  • Prototyping: Quickly spin up static sites for small projects or showcases.

Why use Go for this project?

  • Speed: Go compiles to native machine code, making tools like this blazingly fast.
  • Concurrency: Go makes it easy to process multiple files simultaneously.
  • Simplicity: Go’s syntax is minimal, and building CLI tools is straightforward.

I had a great fun time building this project :)

Project Setup

Before diving into the code, let’s outline the structure of the project:

static-site-generator/├── cmd/│   └── ssg/│       └── main.go           # Entry point├── internal/│   ├── generator/│   │   └── html.go          # HTML generation logic│   ├── parser/│   │   ├── frontmatter.go   # YAML frontmatter parsing│   │   └── markdown.go      # Markdown processing│   └── watcher/│       └── watcher.go       # File change detection├── templates/│   └── default.html         # HTML template├── content/                 # Markdown files└── output/
Enter fullscreen modeExit fullscreen mode

If you want to build from scratch, run this command to initialize a Go module for the project

go mod init
Enter fullscreen modeExit fullscreen mode

Key Features:

  • Convert Markdown to HTML 📄

  • YAML frontmatter for metadata parsing

  • HTML templates for customizable output

  • Real-time file change detection with a watcher 👀

Building the Project

1. Clone the Repository

Before starting, clone the repository to your local machine:

git clone https://github.com/Tabintel/static-site-generator.gitcdstatic-site-generator
Enter fullscreen modeExit fullscreen mode

This will give you all the starter files and project structure needed to build and run the SSG.


2. Markdown Parser

The Markdown parser handles converting.md files into HTML content. It also enables extended features like automatic heading IDs.

internal/parser/markdown.go

packageparserimport("github.com/gomarkdown/markdown""github.com/gomarkdown/markdown/parser")typeMarkdownContentstruct{ContentstringTitlestringDatestringTags[]stringHTMLOutputstring}funcParseMarkdown(content[]byte)*MarkdownContent{extensions:=parser.CommonExtensions|parser.AutoHeadingIDsparser:=parser.NewWithExtensions(extensions)html:=markdown.ToHTML(content,parser,nil)return&MarkdownContent{Content:string(content),HTMLOutput:string(html),}}
Enter fullscreen modeExit fullscreen mode

✨Converts Markdown content into HTML format with extended feature support.


3. Frontmatter Parser

The frontmatter parser extracts metadata like title, date, tags, and description from Markdown files.

internal/parser/frontmatter.go

packageparserimport("bytes""gopkg.in/yaml.v2")typeFrontmatterstruct{Titlestring`yaml:"title"`Datestring`yaml:"date"`Tags[]string`yaml:"tags"`Descriptionstring`yaml:"description"`}funcParseFrontmatter(content[]byte)(*Frontmatter,[]byte,error){parts:=bytes.Split(content,[]byte("---"))iflen(parts)<3{returnnil,content,nil}varmetaFrontmattererr:=yaml.Unmarshal(parts[1],&meta)iferr!=nil{returnnil,content,err}return&meta,bytes.Join(parts[2:],[]byte("---")),nil}
Enter fullscreen modeExit fullscreen mode

🎯 Extracts and returns metadata along with the content of the Markdown file.


4. HTML Generator

The HTML generator uses Go’shtml/template package to create static HTML pages based on a template.

internal/generator/html.go

packagegeneratorimport("html/template""os""path/filepath")typeGeneratorstruct{TemplateDirstringOutputDirstring}funcNewGenerator(templateDir,outputDirstring)*Generator{return&Generator{TemplateDir:templateDir,OutputDir:outputDir,}}func(g*Generator)Generate(datainterface{},outputFilestring)error{iferr:=os.MkdirAll(g.OutputDir,0755);err!=nil{returnerr}tmpl,err:=template.ParseFiles(filepath.Join(g.TemplateDir,"default.html"))iferr!=nil{returnerr}out,err:=os.Create(filepath.Join(g.OutputDir,outputFile))iferr!=nil{returnerr}deferout.Close()returntmpl.Execute(out,data)}
Enter fullscreen modeExit fullscreen mode

🔧 Generates HTML files from templates and parsed Markdown content.


5. File Watcher

Our watcher monitors thecontent/ directory for changes and triggers rebuilds automatically.

This is built usinghttps://github.com/fsnotify/fsnotify

internal/watcher/watcher.go

packagewatcherimport("fmt""github.com/fsnotify/fsnotify""log""os""path/filepath")typeProcessFnfunc()errorfuncWatch(dirstring,processProcessFn)error{watcher,err:=fsnotify.NewWatcher()iferr!=nil{returnerr}deferwatcher.Close()done:=make(chanbool)gofunc(){for{select{caseevent,ok:=<-watcher.Events:if!ok{return}ifevent.Op&fsnotify.Write==fsnotify.Write{fmt.Printf("Modified file: %s\n",event.Name)iferr:=process();err!=nil{log.Printf("Error processing: %v\n",err)}}caseerr,ok:=<-watcher.Errors:if!ok{return}log.Printf("Error: %v\n",err)}}}()err=filepath.Walk(dir,func(pathstring,infoos.FileInfo,errerror)error{iferr!=nil{returnerr}ifinfo.IsDir(){returnwatcher.Add(path)}returnnil})iferr!=nil{returnerr}<-donereturnnil}
Enter fullscreen modeExit fullscreen mode

🚰 Detects file changes and automates the regeneration of static files.


6. Main Application

The entry point ties all components together and provides CLI options for customization.

cmd/ssg/main.go

packagemainimport("flag""fmt""log""os""path/filepath""html/template""github.com/Tabintel/static-site-generator/internal/generator""github.com/Tabintel/static-site-generator/internal/parser""github.com/Tabintel/static-site-generator/internal/watcher")funcprocessFiles(contentDirstring,gen*generator.Generator)error{returnfilepath.Walk(contentDir,func(pathstring,infoos.FileInfo,errerror)error{iferr!=nil{returnerr}iffilepath.Ext(path)!=".md"{returnnil}content,err:=os.ReadFile(path)iferr!=nil{returnerr}// Parse frontmatter and contentmeta,content,err:=parser.ParseFrontmatter(content)iferr!=nil{returnerr}// Parse markdownparsed:=parser.ParseMarkdown(content)// Generate HTMLoutputFile:=filepath.Base(path[:len(path)-3])+".html"returngen.Generate(map[string]interface{}{"Title":meta.Title,"Date":meta.Date,"Tags":meta.Tags,"Content":template.HTML(parsed.HTMLOutput),"Description":meta.Description,},outputFile)})}funcmain(){// Define flagscontentDir:=flag.String("content","content","Content directory path")templateDir:=flag.String("templates","templates","Templates directory path")outputDir:=flag.String("output","output","Output directory path")watch:=flag.Bool("watch",false,"Watch for file changes")flag.Parse()// Initialize generatorgen:=generator.NewGenerator(*templateDir,*outputDir)// Process fileserr:=processFiles(*contentDir,gen)iferr!=nil{log.Fatal(err)}if*watch{fmt.Println("Watching for changes...")err:=watcher.Watch(*contentDir,func()error{returnprocessFiles(*contentDir,gen)})iferr!=nil{log.Fatal(err)}}}
Enter fullscreen modeExit fullscreen mode

Usage

Before you run the app, create a markdown file using.md and save it in thecontent directory

markdown file

Then run the generator:

go run cmd/ssg/main.go
Enter fullscreen modeExit fullscreen mode

It converts the markdown file to an HTML file and saves it in theoutput directory

As you can see, it adds formatting to make it visually appealing :)

html

Watch for Changes

Enable the watcher:

go run cmd/ssg/main.go--watch
Enter fullscreen modeExit fullscreen mode

watcher


And that's It!

This SSG converts markdown to clean HTML, watches for changes, and keeps your content organized. Drop a comment if you build something with it - I'd love to see what you create!

Found this helpful? You canbuy me a coffee to support more Go tutorials! ☕

Happy coding! 🚀


Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Bringing technical concepts to life through clear writing. Go Software developer and Tech writer; creating, educating and inspiring.👨‍💻Learning||Building🚀
  • Location
    Europe
  • Education
    Coursera, Udemy, LinkedIn Learning, YouTube, Books, People.
  • Work
    Technical Writer | Go Backend developer
  • Joined

More fromEkemini Samuel

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp