# 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) 1. Clone the repository: ```bash git clone https://github.com/kalvin0x8d0/blogging-cms.git cd blogging-cms ``` 2. Configure environment: ```bash cp .env.example .env # Edit .env with your settings nano .env ``` 3. Start the stack: ```bash docker-compose up -d ``` 4. Access the application: - Homepage: `http://localhost:8080` - Dashboard: `http://localhost:8080/dashboard` ### Without Docker 1. Install dependencies: ```bash go mod download ``` 2. Configure MariaDB: ```bash # 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; ``` 3. Set environment variables: ```bash 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 ``` 4. Run the application: ```bash 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` ```json { "username": "author", "email": "author@example.com", "password": "secure_password" } ``` **POST** `/auth/login` ```json { "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) ```json { "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` ```json { "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 ```bash # Install Go brew install go # macOS # or download from golang.org # Clone repository git clone 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 ```bash docker build -t blogging-cms:latest . ``` ### Testing ```bash # 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 ```bash 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. - GitHub: [@kalvin0x8d0](https://github.com/kalvin0x8d0) - Fediverse: [@kalvin@social.obulou.org](https://social.obulou.org/@kalvin) - Personal site: [obulou.org](https://obulou.org) --- **Remember**: This is your space. Own your content. Self-host with care. ✍️