A modern, fast blog engine written in Go - a complete rewrite of the C program cosxom, which itself was a rewrite of the Perl program blosxom.
- Filesystem-based: No database required - your blog entries are just text files
- Fast & Lightweight: Built with Go for excellent performance
- Simple Configuration: YAML-based configuration with sensible defaults
- Template System: Uses Go's powerful
html/templatefor customization - HTTP Server: Built-in web server replaces traditional CGI setup
- Semantic Versioning: Automatic build metadata and version management
- Testing Friendly: Admin endpoints for easy testing and deployment
# Clone the repository
git clone https://github.com/maloquacious/quoha.git
cd quoha
# Build the binary
make localhost# Start the server
./dist/localhost/quoha
# Or with custom configuration
./dist/localhost/quoha -config myconfig.yaml
# Check version
./dist/localhost/quoha -version
# Get full build info
./dist/localhost/quoha -version-build-
Copy the example:
cp -r examples/basic/ myblog/ cd myblog/ -
Edit configuration:
# Edit config.yaml to match your preferences vim config.yaml -
Create your first post:
# Create a new .md file in data/ echo "My First Post Author: Your Name Category: Personal Welcome to my new blog powered by Quoha!" > data/my-first-post.md
-
Start blogging:
quoha -config config.yaml
Quoha uses YAML configuration files. Here's a complete example:
server:
addr: ":8080" # Server address and port
read_timeout: "30s" # HTTP read timeout
write_timeout: "30s" # HTTP write timeout
blog:
data_dir: "./data" # Directory containing blog entries
extension: ".md" # File extension for blog entries
template_dir: "./templates" # Template directory
template: "default" # Template subdirectory to use
mime_type: "text/html" # Content-Type header for responses
date_format: "Monday, January 2, 2006" # Go time format for dates
cache_file: ".datecache" # File modification time cacheBlog entries are simple text files with optional metadata:
My Amazing Blog Post
Author: Your Name
Category: Technology
Tags: golang, web, blog
Status: published
This is the content of your blog post.
You can use any formatting you like - the content
is passed directly to your templates.
## Subheadings work too
- Lists
- Are
- SupportedFormat Rules:
- First non-empty line = title
- Lines with
key: value= metadata - Everything else = body content
- Files sorted by modification time (newest first)
Quoha uses Go's html/template system. Templates have access to these functions:
{{postTitle .}}- Entry title{{postDate .}}- Formatted date{{postBody .}}- Entry content (as HTML){{postPath .}}- URL path for the entry
Example template:
<!DOCTYPE html>
<html>
<head><title>My Blog</title></head>
<body>
<h1>My Blog</h1>
{{range .Entries}}
<article>
<h2>{{postTitle .}}</h2>
<time>{{postDate .}}</time>
<div>{{postBody .}}</div>
</article>
{{end}}
</body>
</html>quoha [OPTIONS]
Options:
-config string Configuration file path (default "config.yaml")
-host string Override host address
-port string Override port number
-timeout duration Auto-shutdown timeout (e.g., 30s, 5m)
-version Show version information
-version-build Show version with build informationQuoha includes several built-in endpoints:
GET /- Main blog pageGET /api/ping- Health check endpointPOST /admin/shutdown- Graceful server shutdown
# Build for local development
make localhost
# Build for Linux production
make linux
# Build both
make dist
# Clean build artifacts
make clean# Run tests
make test
# Start test server (auto-shuts down after 30s)
make test-run
# Format code
make fmtquoha/
├── main.go # Application entry point
├── internal/ # Internal packages
│ ├── config/ # Configuration handling
│ ├── blog/ # Entry scanning and parsing
│ └── server/ # HTTP server and routing
├── examples/ # User-facing examples
│ └── basic/ # Complete basic setup
├── testdata/ # Test data (Go convention)
├── dist/ # Build outputs (gitignored)
│ ├── localhost/ # Local development builds
│ └── linux/ # Production builds
└── Makefile # Build automation
make run# Build Linux binary
make linux
# Copy to server
scp -r dist/linux/* user@server:/opt/quoha/
# Run on server
./quoha -config config.yaml[Unit]
Description=Quoha Blog Engine
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/quoha
ExecStart=/opt/quoha/quoha -config config.yaml
Restart=always
[Install]
WantedBy=multi-user.targetQuoha is the third generation of this concept:
- blosxom (Perl) - Original filesystem-based blog engine
- cosxom (C) - Performance rewrite, but abandoned in alpha
- quoha (Go) - Modern rewrite with proper testing and maintenance
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add tests for new functionality
- Run tests (
make test) - Commit your changes (
git commit -am 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- blosxom by Rael Dornfest - The original inspiration
- cosxom by Keith Beckman - The C implementation that Quoha builds upon
- The Go community for excellent tooling and libraries