Home > Backend Development > Golang > How to Create a Static Site Generator with Go

How to Create a Static Site Generator with Go

Susan Sarandon
Release: 2024-12-16 04:51:13
Original
279 people have browsed it

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 a Static Site Generator (SSG) in Go, 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/
Copy after login
Copy after login

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

go mod init
Copy after login
Copy after login

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.git
cd static-site-generator
Copy after login
Copy after login

How to Create a Static Site Generator with Go Tabintel / static-site-generator

Static Site Generator

A fast and simple static site generator written in Go.




View on GitHub


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

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/
Copy after login
Copy after login

✨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

go mod init
Copy after login
Copy after login

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


4. HTML Generator

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

internal/generator/html.go

git clone https://github.com/Tabintel/static-site-generator.git
cd static-site-generator
Copy after login
Copy after login

? Generates HTML files from templates and parsed Markdown content.


5. File Watcher

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

This is built using https://github.com/fsnotify/fsnotify

internal/watcher/watcher.go

package parser

import (
    "github.com/gomarkdown/markdown"
    "github.com/gomarkdown/markdown/parser"
)

type MarkdownContent struct {
    Content    string
    Title      string
    Date       string
    Tags       []string
    HTMLOutput string
}

func ParseMarkdown(content []byte) *MarkdownContent {
    extensions := parser.CommonExtensions | parser.AutoHeadingIDs
    parser := parser.NewWithExtensions(extensions)
    html := markdown.ToHTML(content, parser, nil)

    return &MarkdownContent{
        Content:    string(content),
        HTMLOutput: string(html),
    }
}
Copy after login

? 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

package parser

import (
    "bytes"
    "gopkg.in/yaml.v2"
)

type Frontmatter struct {
    Title       string   `yaml:"title"`
    Date        string   `yaml:"date"`
    Tags        []string `yaml:"tags"`
    Description string   `yaml:"description"`
}

func ParseFrontmatter(content []byte) (*Frontmatter, []byte, error) {
    parts := bytes.Split(content, []byte("---"))
    if len(parts) < 3 {
        return nil, content, nil
    }

    var meta Frontmatter
    err := yaml.Unmarshal(parts[1], &meta)
    if err != nil {
        return nil, content, err
    }

    return &meta, bytes.Join(parts[2:], []byte("---")), nil
}
Copy after login

Usage

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

How to Create a Static Site Generator with Go

Then run the generator:

package generator

import (
    "html/template"
    "os"
    "path/filepath"
)

type Generator struct {
    TemplateDir string
    OutputDir   string
}

func NewGenerator(templateDir, outputDir string) *Generator {
    return &Generator{
        TemplateDir: templateDir,
        OutputDir:   outputDir,
    }
}

func (g *Generator) Generate(data interface{}, outputFile string) error {
    if err := os.MkdirAll(g.OutputDir, 0755); err != nil {
        return err
    }

    tmpl, err := template.ParseFiles(filepath.Join(g.TemplateDir, "default.html"))
    if err != nil {
        return err
    }

    out, err := os.Create(filepath.Join(g.OutputDir, outputFile))
    if err != nil {
        return err
    }
    defer out.Close()

    return tmpl.Execute(out, data)
}
Copy after login

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

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

How to Create a Static Site Generator with Go

Watch for Changes

Enable the watcher:

package watcher

import (
    "fmt"
    "github.com/fsnotify/fsnotify"
    "log"
    "os"
    "path/filepath"
)

type ProcessFn func() error

func Watch(dir string, process ProcessFn) error {
    watcher, err := fsnotify.NewWatcher()
    if err != nil {
        return err
    }
    defer watcher.Close()

    done := make(chan bool)
    go func() {
        for {
            select {
            case event, ok := <-watcher.Events:
                if !ok {
                    return
                }
                if event.Op&fsnotify.Write == fsnotify.Write {
                    fmt.Printf("Modified file: %s\n", event.Name)
                    if err := process(); err != nil {
                        log.Printf("Error processing: %v\n", err)
                    }
                }
            case err, ok := <-watcher.Errors:
                if !ok {
                    return
                }
                log.Printf("Error: %v\n", err)
            }
        }
    }()

    err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        if info.IsDir() {
            return watcher.Add(path)
        }
        return nil
    })
    if err != nil {
        return err
    }

    <-done
    return nil
}
Copy after login

How to Create a Static Site Generator with Go


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 can buy me a coffee to support more Go tutorials! ☕

Happy coding! ?

How to Create a Static Site Generator with Go Tabintel / static-site-generator

Static Site Generator

A fast and simple static site generator written in Go.




View on GitHub


The above is the detailed content of How to Create a Static Site Generator with Go. For more information, please follow other related articles on the PHP Chinese website!

source:dev.to
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template