Files
nutshell9247 852613586f
CI/CD Pipeline / Test & Lint (push) Waiting to run
CI/CD Pipeline / Build Docker Image (push) Blocked by required conditions
CI/CD Pipeline / Security Scan (push) Waiting to run
first commit, mate!
2026-08-08 14:43:59 +08:00

8.2 KiB
Raw Permalink Blame History

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+
  1. Clone the repository:
git clone https://github.com/kalvin0x8d0/blogging-cms.git
cd blogging-cms
  1. Configure environment:
cp .env.example .env
# Edit .env with your settings
nano .env
  1. Start the stack:
docker-compose up -d
  1. Access the application:
  • Homepage: http://localhost:8080
  • Dashboard: http://localhost:8080/dashboard

Without Docker

  1. Install dependencies:
go mod download
  1. 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;
  1. 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
  1. 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

  1. Create Coolify Project

    • New Project → Select "Docker Compose"
  2. Connect Repository

    • Link your Git repository with the blogging-cms code
    • Point to the root directory
  3. 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
      
  4. Deploy

    • Coolify automatically picks up docker-compose.yml
    • Sets up MariaDB and Go application
    • Configure reverse proxy (Caddy) in Coolify settings
  5. Health Checks

    • Coolify monitors / endpoint for health
    • Application includes built-in healthcheck

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"
}

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: - item or 1. item
  • Links: [text](url)
  • Images: ![alt](url)
  • 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

  1. Use HTTPS Configure in reverse proxy (Caddy)
  2. Change SESSION_KEY Generate secure random key
  3. Use strong DB password At least 32 characters
  4. Enable backups MariaDB volume backups
  5. Rate limiting Add reverse proxy rules
  6. 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=true in database
  • Verify database query with: mysql -h mariadb -u cms_user -p

Static Files 404

  • Ensure static/ and templates/ directories exist
  • Check file permissions: ls -la static/

Contributing

  1. Fork the repository
  2. Create feature branch: git checkout -b feature/name
  3. Commit changes: git commit -m "Add feature"
  4. Push: git push origin feature/name
  5. 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.


Remember: This is your space. Own your content. Self-host with care. ✍️