7b4e05482d0b98b59e71cfebfba127d4d423ccbb
Blogging CMS
A lightweight, self-hosted blogging platform built with Go, HTML/CSS/JS, and MariaDB. Designed for digital sovereignty and easy Coolify deployment.
Features
- ✍️ Markdown Support – Write posts in Markdown with live preview
- 📝 Two Post Types – Full blog posts or quick micro-posts
- 🏷️ Tagging & Categories – Organize content flexibly
- 🔍 Full-Text Search – Quick post discovery
- 📡 RSS Feed – Auto-generated feed for subscribers
- 👤 User Management – Multiple authors with role-based access
- 💬 Comments – Moderated comment system
- 🎨 Material Design 3 – Modern, responsive UI
- 🔒 Session-Based Auth – Secure user authentication
- 📱 Mobile Responsive – Works on all devices
- 🐳 Docker Ready – One-command deployment on Coolify
Architecture
blogging-cms/
├── main.go # Go backend with HTTP handlers & DB
├── go.mod / go.sum # Go dependencies
├── Dockerfile # Multi-stage Docker build
├── docker-compose.yml # Full stack (app + MariaDB)
├── .env.example # Configuration template
├── README.md # This file
├── .gitignore # Git configuration
├── templates/ # HTML templates
│ ├── home.html # Homepage
│ ├── post.html # Single post view
│ ├── category.html # Category listing
│ └── dashboard.html # Admin dashboard
├── static/ # Frontend assets
│ ├── css/
│ │ └── material.css # Material Design 3 stylesheet
│ └── js/
│ └── app.js # Frontend logic & API client
└── .github/
└── workflows/ # CI/CD (optional)
Quick Start
Prerequisites
- Docker & Docker Compose
- Or: Go 1.21+, MariaDB 11.0+
With Docker (Recommended)
- Clone the repository:
git clone https://github.com/kalvin0x8d0/blogging-cms.git
cd blogging-cms
- Configure environment:
cp .env.example .env
# Edit .env with your settings
nano .env
- Start the stack:
docker-compose up -d
- Access the application:
- Homepage:
http://localhost:8080 - Dashboard:
http://localhost:8080/dashboard
Without Docker
- Install dependencies:
go mod download
- Configure MariaDB:
# Create database and user
mysql -u root -p
CREATE DATABASE blogging_cms;
CREATE USER 'cms_user'@'localhost' IDENTIFIED BY 'secure_password';
GRANT ALL PRIVILEGES ON blogging_cms.* TO 'cms_user'@'localhost';
FLUSH PRIVILEGES;
- Set environment variables:
export DB_HOST=localhost
export DB_USER=cms_user
export DB_PASSWORD=secure_password
export DB_NAME=blogging_cms
export PORT=8080
export SITE_URL=http://localhost:8080
export SESSION_KEY=generate-random-key-here
- Run the application:
go run main.go
Deployment on Coolify
Prerequisites
- Coolify instance running
- Git repository (GitHub, GitLab, Gitea, etc.)
- Domain name (optional but recommended)
Steps
-
Create Coolify Project
- New Project → Select "Docker Compose"
-
Connect Repository
- Link your Git repository with the blogging-cms code
- Point to the root directory
-
Configure Environment
- Add environment variables from
.env.example:DB_HOST=mariadb DB_USER=cms_user DB_PASSWORD=your_secure_password DB_NAME=blogging_cms SITE_URL=https://your-domain.com SESSION_KEY=generate-random-key
- Add environment variables from
-
Deploy
- Coolify automatically picks up
docker-compose.yml - Sets up MariaDB and Go application
- Configure reverse proxy (Caddy) in Coolify settings
- Coolify automatically picks up
-
Health Checks
- Coolify monitors
/endpoint for health - Application includes built-in healthcheck
- Coolify monitors
API Reference
Authentication
POST /auth/register
{
"username": "author",
"email": "author@example.com",
"password": "secure_password"
}
POST /auth/login
{
"email": "author@example.com",
"password": "secure_password"
}
Posts
GET /api/posts?page=1
- Get paginated list of published posts
GET /api/posts/{id}
- Get single post by ID
POST /api/posts
- Create new post (requires auth)
{
"title": "Post Title",
"content": "# Markdown content",
"excerpt": "Brief summary",
"type": "post",
"category": "Technology",
"tags": ["go", "blogging"],
"published": false
}
PUT /api/posts/{id}
- Update post (requires ownership)
DELETE /api/posts/{id}
- Delete post (requires ownership)
Comments
POST /api/comments
{
"post_id": "post-uuid",
"content": "Comment text"
}
Search
GET /api/search?q=query
- Full-text search across posts
Feeds
GET /feed
- RSS feed of all published posts
Configuration
Environment Variables
| Variable | Description | Default |
|---|---|---|
DB_HOST |
Database hostname | mariadb |
DB_PORT |
Database port | 3306 |
DB_USER |
Database user | cms_user |
DB_PASSWORD |
Database password | Required |
DB_NAME |
Database name | blogging_cms |
PORT |
Application port | 8080 |
SITE_URL |
Public site URL | http://localhost:8080 |
SESSION_KEY |
Session encryption key | dev-session-key |
Development
Local Development
# Install Go
brew install go # macOS
# or download from golang.org
# Clone repository
git clone <repo-url>
cd blogging-cms
# Install dependencies
go mod tidy
# Start MariaDB (Docker)
docker run -d \
-e MYSQL_ROOT_PASSWORD=root \
-e MYSQL_DATABASE=blogging_cms \
-p 3306:3306 \
mariadb:11.0
# Run application
go run main.go
Building Docker Image
docker build -t blogging-cms:latest .
Testing
# Unit tests (not yet implemented)
go test ./...
# Integration tests with docker-compose
docker-compose -f docker-compose.test.yml up
Markdown Syntax
Supported Markdown features:
- Headers:
# H1,## H2, etc. - Bold:
**text** - Italic:
*text* - Code:
`inline`or code blocks with triple backticks - Lists:
- itemor1. item - Links:
[text](url) - Images:
 - Blockquotes:
> quote
Security Considerations
- Passwords are hashed (consider using bcrypt in production)
- Session tokens are encrypted
- CSRF protection via sessions
- SQL injection protection via prepared statements
- XSS protection via template escaping
- Comments are moderated before publication
Hardening for Production
- Use HTTPS – Configure in reverse proxy (Caddy)
- Change SESSION_KEY – Generate secure random key
- Use strong DB password – At least 32 characters
- Enable backups – MariaDB volume backups
- Rate limiting – Add reverse proxy rules
- Content Security Policy – Configure in Dockerfile
Performance
- Lightweight Go binary (~10MB)
- Efficient MariaDB queries with indexing
- Static asset caching
- Lazy-loaded comments
- Paginated post listings
Troubleshooting
Database Connection Error
Error: dial tcp mariadb:3306: connect: connection refused
Solution: Ensure MariaDB container is running and healthy
docker-compose logs mariadb
Posts Not Displaying
- Check
published=truein database - Verify database query with:
mysql -h mariadb -u cms_user -p
Static Files 404
- Ensure
static/andtemplates/directories exist - Check file permissions:
ls -la static/
Contributing
- Fork the repository
- Create feature branch:
git checkout -b feature/name - Commit changes:
git commit -m "Add feature" - Push:
git push origin feature/name - Create Pull Request
License
MIT License. See LICENSE file for details.
Acknowledgments
- Material Design 3 guidelines
- Go standard library
- Gorilla toolkit
- Docker community
Author
Kalvin – Civic technologist and digital sovereignty advocate.
- GitHub: @kalvin0x8d0
- Fediverse: @kalvin@social.obulou.org
- Personal site: obulou.org
Remember: This is your space. Own your content. Self-host with care. ✍️
Languages
Go
29.5%
HTML
27.7%
JavaScript
20.6%
CSS
17.1%
Makefile
3.3%
Other
1.8%