Garlic: Fast and Simple Static Site Generator in Go
By Shreyas Kaundinya
Table of Contents
- 0. Contact Me
- 1. Intro & Installation
- 2. Running the project
- 3. Folder Structure
- 4. Architecture
- 5. Deployment
- 6. TODO & Limitations
0. Contact Me
If you have any questions, feel free to drop an DM on X (Formerly Twitter)
Checkout my website here built using Garlic SSG.
1. Intro & Installation
1.1 Features
- Classic Static Site Generator with some opinionated features
- Converts markdown content into HTML which can be served as a static website.
- HTML components using JSX like syntax (with limited support as of now)
- Templates for content
- Tags using frontmatter
- Hot reloading support for development (reloads when content is changed)
1.2 Installation / Build Instructions
NOTE: Since I currently don't have a release, you'll have to build the project yourself.
Step 1: Clone the repository
Step 2: Run the following commands
1go mod tidy
2
3# windows
4go build -o garlic.exe main.go
5
6# linux
7go build -o garlic main.go
8
9# macos
10go build -o garlic main.go
2. Running the project
2.1 Command Line Arguments
--src-folder: The source folder of the project--dest-folder: The destination folder of the project--serve: Whether to serve the project [serves the project athttp://localhost:8084]. This also enables hot reloading support for when the content is changed.--seed-files: Whether to seed the project [adds the default files to your source folder]
2.2 Examples
1.\garlic.exe --src-folder "S:\src" --dest-folder "S:\dest" --serve --seed-files
1./garlic --src-folder ./src --dest-folder ./dest --serve --seed-files
NOTE: dont add a trailing slash to the source or destination folder paths.
3. Folder Structure
The folder structure is fixed, the base folders that are required in the source folder are :
We will dive deeper into what each folder signifies in the next section.
Don't worry about the boilerplate code, it will be seeded for you if you use the
--seed-filesflag.
3.1 Tree
1src/
2├── content/
3 ├── index.md
4├── templates/
5 ├── index.html
6 ├── _tags.html
7 ├── _individual_tag.html
8├── components/
9 ├── Footerbar.html
10 ├── Navbar.html
11 ├── Tags.html
12├── assets/
13 ├── styles/
14 ├── global.css
15└── dest/
16 ├── assets/
17 ├── styles/
18 ├── global.css
19 ├── index.html
20 ├── tags/
21 ├── index.html
22 ├── tag-on-index-page/
23 ├── index.html
3.2 Content Folder : src/content
The content folder is where you put your markdown files. The routing of the website is based on the file structure inside this folder.
So if you want to create a page at /about, you can create a file at src/content/about/index.md.
The rendered HTML will be in dest/about/index.html.
Each markdown file will contain something called as frontmatter. This is a way to add metadata to the markdown file. It is written between --- lines. Follows the YAML syntax.
Content Example
1---
2title: "Home"
3publish: true
4template: index
5date: 2025-10-21
6author: author
7tags:
8 - tag-on-index-page
9---
10
11<!-- rest of the content of the page -->
12
13# Home
title: The title of the page, this can be used in the templatepublish: Whether to publish the page, if false, the page will not be renderedtemplate: The template to use for the page, this is the template that will be used to render the pagedate: The date of the page.author: The author of the page.tags: The tags of the page. Atleast one tag is required per page.
NOTE: currently there is no support for
dateandauthorin the templates.
3.3 Templates Folder : src/templates
Each markdown file in the src/content folder will be rendered into an HTML file in the dest folder.
Templates contain HTML that will wrap around the markdown content.
NOTE : Currently only supports flat file structure in this folder.
Content of the template is injected into the {{ $content }} placeholder.
1<main>{{ $content }}</main>
For the above example, the rendered HTML will be:
1<main>
2 <h1>Home</h1>
3</main>
Title of the template from the frontmatter is injected into the {{ $title }} placeholder.
1<title>{{ $title }}</title>
For the above example, the rendered HTML will be:
1<title>Home</title>
Some special templates required for internal purposes are:
NOTE: working actively to make these templates more flexible and powerful. A default template will be provided during
seeding
_tags.html: This is the template where all the tags will be listed with their count.{{ $content }}will be replaced with<ul>...</ul>tag with each tag as a<li>. Each<li>tag will have a<a>tag with the tag name and the count of number of pages that have that tag. The<a>tag will have the href to the individual tag page where all the pages with that tag will be listed.
_individual_tag.html: This is the template where a single tag and all the pages with that tag will be listed.{{ $content }}will be replaced with the list of pages with that tag.
3.4 Assets Folder : src/assets
Contains all the static assets of the website. This folder will be directly copy pasted into your destination folder. The files can be accessed using the /assets/ prefix.
For example, if you want to access the global.css file, you can do it by using the /assets/styles/global.css path.
1<link rel="stylesheet" href="/assets/styles/global.css" />
3.5 Components Folder : src/components
You can add smaller HTML components here. These will be injected into the templates.
NOTE : Currently only supports flat file structure in this folder.
WARN: The components cannot have the same name as a native html element such as
div,span,a,img, etc.
Let's say we create a component called Navbar.html
To use it in a template, the syntax is as follows:
1<Navbar></Navbar>
Limitations (which could later be supported):
- Self closing tags are not supported.
- No support for conditional rendering.
- No support for loops
- No support for props for components
4. Architecture
This section is a work in progress.
Garlic is a static site generator that is built in Go. It is designed to be fast and simple to use.
Markdown files written in the src/content folder are parsed and rendered into HTML, this is then injected into the templates.
Components are small HTML files that can be injected into the templates based on the file name, similar to JSX.
src/components/Navbar.html
1<nav>
2 <a href="/">Home</a>
3</nav>
src/templates/index.html
1<!DOCTYPE html>
2<html lang="en">
3 <head>
4 <meta charset="utf-8" />
5 <meta name="viewport" content="width=device-width, initial-scale=1" />
6 <title>{{ $title }}</title>
7 <link rel="stylesheet" href="/assets/styles/global.css" />
8 </head>
9 <style></style>
10 <body>
11 <Navbar></Navbar>
12 <main>{{ $content }}</main>
13 </body>
14</html>
src/content/index.md
1---
2title: "Home"
3publish: true
4template: index
5author: author
6tags:
7 - tags
8---
9
10# Home
11
12This is the home page.
The rendered HTML will be:
dest/index.html
1<!DOCTYPE html>
2<html lang="en">
3 <head>
4 <meta charset="utf-8" />
5 <meta name="viewport" content="width=device-width, initial-scale=1" />
6 <title>Home</title>
7 <link rel="stylesheet" href="/assets/styles/global.css" />
8 </head>
9 <body>
10 <nav>
11 <a href="/">Home</a>
12 </nav>
13
14 <main>
15 <h1>Home</h1>
16 <p>This is the home page.</p>
17 </main>
18 </body>
19</html>
5. Deployment
Once you follow these steps and run Garlic on your content, you have freshly baked static website 🧄🥖 ready to be deployed.
These are some ways you can deploy your website:
- simply copying the
destfolder to your web server. - pushing to a Github repository and deploying using Github Pages
- pushing to a git repository and deploying using Vercel, Netlify, etc which provide you with a free domain and a way to do continuous deployment.
6. TODO & Limitations
- Not require atleast one tag per page
- Add concurrency support to rendering
- Deleting unused files from destination folder
- Being able to use author from frontmatter in templates
- Being able to iterate over posts and tags in templates
- Being able to use date from frontmatter in templates
- RSS feed generation
- Components
- No support for self closing tags
- No support for conditional rendering
- No support for loops
- No support for props for components