How to Setup Your Own Blog with Zola - Zero to Published
I wanted to start a blog. Looked at WordPress - too complicated, needs hosting, plugins, security updates. Looked at Medium - don't own your content. Looked at Substack - locked into their platform.
I kept seeing developers with clean, fast blogs. No ads, no tracking, just text and code. Asked around. Most of them used static site generators.
That seemed complicated too. Until I tried Zola.
The problem with common blogging platforms
When people think "blog," they think WordPress. Install on a server, configure MySQL, manage plugins, fight spam, update constantly to avoid security holes.
Or they think Medium. Write in their editor, publish, done. But Medium owns your content. They can paywall your posts. Your blog lives on their domain.
WordPress:
- Needs hosting (monthly cost)
- Database setup
- Plugin management
- Security updates
- Backup handling
- Slow page loads
Medium/Substack:
- Don't own your content
- Can't customize design
- Their domain, not yours
- They control monetization
- Platform lock-in
Ghost/other CMSs:
- Still need hosting
- Still need database
- Monthly fees add up
I wanted something simpler. Write markdown files, run one command, get a website. No server, no database, no monthly bills.
What makes Zola different
Zola is a static site generator. You write content in markdown files, run zola build, and get static HTML files. Upload those files anywhere - Netlify, GitHub Pages, your own server. No backend needed.
Here's what actually matters:
Single binary: Download one file, that's it. No dependencies, no Python environment, no Node.js modules. Just one executable.
Fast: Written in Rust. Builds in milliseconds, not seconds. I have 20+ blog posts, Zola builds the entire site in under 200ms.
No JavaScript required: Your site works without JavaScript. Actual HTML pages, not a SPA that needs to load before showing content.
Free hosting: Netlify free tier works perfectly. Push to GitHub, Netlify builds and deploys automatically. Zero hosting cost.
The trade-off: no admin panel. You edit markdown files in a text editor and use git. If you're comfortable with that, Zola is simple.
Installing Zola
Windows:
choco install zola
If you don't have Chocolatey, install it first or download Zola directly from their GitHub releases.
macOS:
brew install zola
Linux:
snap install --edge zola
Verify it works:
zola --version
# Should show: zola 0.18.0 or newer
Takes 30 seconds total.
Understanding the structure
Every Zola site follows the same structure. Here's mine:
my-blog/
├── config.toml # Site settings
├── content/ # Your writing (markdown)
│ └── blog/
│ └── my-post.md
├── templates/ # HTML layouts
├── sass/ # Styles
└── static/ # Images, files
content/ is where you write. Everything else sets up how it looks.
You don't need to understand templates or sass to start. Just write markdown in content/, Zola handles the rest.
Creating your first site
zola init my-blog
cd my-blog
Zola asks a few questions:
- What is the URL? (you can change later)
- Enable syntax highlighting? (yes if you post code)
- Enable search? (no for now, add later)
Creates the folder structure. That's it.
Writing your first post
Create a file: content/blog/my-first-post.md
+++
title = "My First Post"
date = 2025-12-07
+++
This is my first blog post written in markdown.
## I can use headings
And **bold text** and *italic text*.
Lists work too:
- First item
- Second item
Code blocks:
```python
def hello():
print("Hello world")
The `+++` section at the top is metadata. Title shows as the page heading. Date is used for sorting posts.
## Previewing locally
```bash
zola serve
Opens at http://127.0.0.1:1111
Change a file, save it - the page refreshes automatically. Write your entire post while seeing live updates.
When I write, I keep zola serve running in one terminal, my editor in another window. Every save updates the preview instantly.
Customizing the look
Zola uses templates. The default is functional but plain. You can:
Option 1: Use a theme from zola-themes.org
Download, put in themes/, edit config.toml to use it.
Option 2: Write your own templates
Takes longer but you control everything. I did this. My site has 200 lines of HTML total across all templates.
Option 3: Start with a theme, modify it
Good middle ground. Most themes are simple enough to understand and tweak.
For my blog, I wanted minimal black and white design. No sidebar, no widgets, just text. Wrote custom templates in about two hours.
The config file - what matters
Open config.toml. Most of it you can ignore at first. The important parts:
base_url = "https://yourdomain.com"
title = "Your Blog Name"
# Build settings
compile_sass = true
minify_html = true
# Enable tags
taxonomies = [
{name = "tags", feed = true}
]
# RSS feed
generate_feeds = true
That's 90% of what you need. Everything else is optional.
Adding tags to posts
Tags help organize posts. In your markdown frontmatter:
+++
title = "Post About Python"
date = 2025-12-07
[taxonomies]
tags = ["python", "programming", "tutorial"]
+++
Zola automatically creates:
/tags/- lists all tags/tags/python/- shows all posts with "python" tag
No code required. Just add tags to your posts.
Deploying to Netlify
This is where it gets good. Free hosting with automatic deploys.
1. Push your site to GitHub
git init
git add .
git commit -m "Initial commit"
git push origin main
2. Connect Netlify
- Go to netlify.com
- Click "Add new site"
- Choose "Import from Git"
- Select your GitHub repo
- Build command:
zola build - Publish directory:
public - Click deploy
3. Netlify builds your site
Every time you push to GitHub, Netlify:
- Pulls latest code
- Runs
zola build - Publishes the result
Takes 30 seconds from push to live.
4. Add your domain (optional)
Netlify gives you a subdomain: yoursite.netlify.app
To use your own domain:
- Buy a domain (I use Namecheap, about $10/year)
- In Netlify: Domain settings → Add custom domain
- Update DNS records (they give you instructions)
- HTTPS works automatically (Let's Encrypt)
I did this for quoc.app. Whole process took 10 minutes.
My actual workflow
Writing a new post:
# Create file
touch content/blog/new-post-title.md
# Add frontmatter
+++
title = "Post Title"
date = 2025-12-07
[taxonomies]
tags = ["tag1", "tag2"]
+++
# Write content in markdown
# Preview while writing
zola serve # Running in background
# When done
git add content/blog/new-post-title.md
git commit -m "Add new post: Post Title"
git push
Push to GitHub. Netlify builds and deploys. Post is live in 30 seconds.
No logging into WordPress. No clicking through admin panels. Just text files and git.
Handling images
Save images to static/images/
Reference in markdown:

When Zola builds, it copies everything in static/ to the output. Your image ends up at yoursite.com/images/photo.jpg
I keep images under 200KB. Run them through TinyPNG first. Smaller images = faster page loads.
What I wish I knew earlier
Drafts: Put drafts in a separate folder like content/blog/drafts/. Add to config:
ignored_content = ["*/drafts/*"]
Zola won't build anything in drafts. Move files out when ready to publish.
Date formatting: You can format dates in templates:
{{ page.date | date(format="%Y-%m-%d") }}
But I just use the default. Dates work fine as-is.
Pagination: If you'll have many posts, add to content/blog/_index.md:
+++
paginate_by = 10
sort_by = "date"
+++
Zola automatically creates /blog/page/2/, /blog/page/3/, etc.
RSS: People still use RSS. Zola generates it automatically at /rss.xml if you enable it in config. I get a few subscribers who prefer reading via RSS reader.
Syntax highlighting: Works out of the box. Just specify language:
```python
def hello():
print("world")
```
Choose a theme in config.toml:
[markdown]
highlight_theme = "base16-ocean-dark"
Preview themes at zola-themes.org
When Zola doesn't make sense
Zola is not for everyone.
Don't use Zola if you:
- Need comments (no built-in support, would need external service)
- Want a visual editor (it's markdown files only)
- Need complex user accounts or authentication
- Don't use git or don't want to learn
- Need frequent non-technical contributors
Use WordPress or Ghost instead if:
- You need a full CMS with admin panel
- Non-technical people need to edit content
- You want plugins for everything
- Comments and user accounts are essential
I tried WordPress first. Spent two days setting up, configuring plugins, tweaking themes. Then I still had to update it weekly.
With Zola, I spent two hours total on setup. Haven't touched the config since. Just write and push.
Costs breakdown
My setup:
- Domain: $12/year (quoc.app)
- Hosting: $0 (Netlify free tier)
- SSL certificate: $0 (Let's Encrypt via Netlify)
- Total: $12/year
Compared to WordPress:
- Shared hosting: $60-120/year
- Domain: $12/year
- Premium theme: $60 one-time
- Plugins: varies
- Total: $132+/year
I write 2-3 posts per month. Netlify's free tier handles thousands of visitors easily.
Common mistakes I made
Using relative paths for images:
Bad: 
Good: 
The slash at the start matters. Without it, images break on different pages.
Forgetting to add frontmatter:
Every markdown file needs the +++ section. Without it, Zola ignores the file.
Not testing locally first:
Always run zola serve and check your post before pushing. Catches markdown formatting issues and broken links.
Overcomplicating templates:
My first attempt had 15 template files. Realized I only needed 4. Start simple, add complexity if you actually need it.
Setting up from my blog
My blog is open source: github.com/quocnguyen/quoc-app
You can:
- Clone it
- Change config.toml (update base_url and title)
- Delete my posts in content/blog/
- Write your own posts
- Deploy
Takes the guesswork out of template design. Use mine as-is or modify it.
Tools I use with Zola
Writing: Obsidian for markdown editing. VS Code works too.
Images: TinyPNG for compression before uploading.
Analytics: Netlify Analytics (paid) or Plausible (privacy-focused). I don't use Google Analytics.
Version control: GitHub for code and content.
That's it. No WordPress plugins, no complicated stack.
Speed comparison
I tested page load times:
This Zola blog:
- Time to first byte: 180ms
- Full page load: 420ms
- No JavaScript needed
Average WordPress blog:
- Time to first byte: 800ms-2s
- Full page load: 3-5s
- Requires JavaScript for most features
Static HTML is just faster. No database queries, no PHP processing. Server sends HTML, browser displays it.
SEO works fine
People worry that static sites have SEO issues. Not true.
Zola generates:
- Clean URLs:
/blog/post-title/ - Proper meta tags (if you add them to templates)
- Sitemap at
/sitemap.xml - RSS feed at
/rss.xml
Google indexes my posts fine. Some rank on first page for their keywords.
The content matters more than the platform.
Bottom line
I wanted a blog without the overhead. No server to maintain, no security updates, no monthly hosting bills.
Zola gave me that. One command builds the entire site. Free hosting on Netlify. Push to publish in 30 seconds.
It's not as simple as clicking "New Post" in WordPress. You write markdown files and use git. But that trade-off means no maintenance, no costs, full control.
If you're comfortable with text files and the command line, Zola makes blogging simple. Install it, write markdown, push to deploy. That's the whole workflow.
Start here:
- Install Zola:
choco install zola(Windows) orbrew install zola(Mac) - Create site:
zola init my-blog - Write first post in
content/blog/first-post.md - Preview:
zola serve - Push to GitHub and connect Netlify
From zero to published blog in under an hour.