A lightweight Go web application for hosting your website with blog posts and static pages, all written in Markdown.
Clean, responsive design with dark/light theme toggle
Blog posts with excerpts, tags, and reading time estimates
Individual blog post with syntax highlighting and share buttons
Mobile-responsive design with touch-friendly navigation
- 🚀 Built with Go and the Gin web framework
- 📝 Write blog posts in Markdown
- 📄 Create static pages in Markdown
- 🔄 Automatic navigation generation - new static pages automatically appear in the menu
- 🎨 Clean, responsive design with dark/light theme toggle
- ❌ Custom error pages with helpful 404 and 500 error handling
- ⚡ Fast and lightweight with HTTP caching, lazy-loaded images, and asset minification
- �️ Image optimization with automatic resizing and quality optimization
- �🔧 Cross-platform system service support (Windows, macOS, Linux)
- 🏷️ Tags support for blog posts with automatic filtering
- 💻 Syntax highlighting for code blocks (140+ languages via highlight.js)
- 📅 Date timestamps for blog posts with newest-first sorting
- ⭐ Featured posts - Pin important posts to the top of the blog list
- 📆 Post scheduling - Publish posts automatically at future dates/times
- 📄 Draft support - hide posts and pages until ready to publish
- 🔖 Post excerpts on list pages with configurable length
- ⏱️ Reading time estimates for blog posts
- 📱 Mobile-responsive design with touch-friendly navigation
- 🖨️ Print-friendly CSS for clean article printing
- 📡 RSS/Atom feed for blog subscribers
- 🗺️ Sitemap.xml with automatic post/page indexing
- 📄 Pagination for long post lists
- 🔗 Share buttons for social media (Twitter, LinkedIn, Facebook, Reddit)
- 📋 Copy code button for easy code snippet copying
- 🌐 Social media icons in footer (Twitter, Bluesky, LinkedIn, GitHub, Reddit, Facebook)
- 📊 Umami analytics support for privacy-focused website tracking
- ⚙️ YAML configuration for easy customization
- 🔥 Config hot reload - Configuration changes apply instantly without restart
- 🔄 Hot reload in development mode for faster iteration
podium/
├── main.go # Main application with service support
├── go.mod # Go module file
├── go.sum # Go dependencies checksums
├── Makefile # Build and service management commands
├── build.sh # Build script for Linux/macOS
├── build.bat # Build script for Windows
├── README.md # This file
├── SERVICE.md # Detailed service documentation
├── SERVICE-FEATURES.md # Service features overview
├── QUICKREF.md # Quick reference guide
├── .gitignore # Git ignore file
│
├── install-service.sh # Linux/macOS service installer
├── uninstall-service.sh # Linux/macOS service uninstaller
├── install-service.bat # Windows service installer
├── uninstall-service.bat # Windows service uninstaller
│
├── bin/ # Build output directory
│ └── .gitkeep # Keeps directory in git
│
├── posts/ # Blog posts (Markdown files)
│ ├── first-post.md
│ └── golang-web-dev.md
│
├── static/ # Static pages (Markdown files)
│ ├── about.md
│ └── contact.md
│
├── templates/ # HTML templates
│ ├── index.html # Home page
│ ├── page.html # Static page template
│ ├── posts.html # Blog posts list
│ ├── post.html # Individual post template
│ └── error.html # Error page
│
└── assets/ # Static assets (CSS, images, etc.)
├── style.css # Main stylesheet
├── theme-toggle.js # Theme switching functionality
├── share-buttons.js # Social share functionality
└── favicon.svg # Site icon
- Go 1.16 or higher
- Clone or navigate to the repository
- Install dependencies:
go mod downloadPodium uses a config.yaml file to configure your site. Create a config.yaml file in the root directory with the following settings:
# Site Settings
site_title: "Podium"
site_description: "A simple and elegant blogging platform"
site_author: "Morten Johansen"
site_author_url: "https://johansen.foo"
site_url: "http://localhost:8080"
home_intro: "Podium is a lightweight web application built with Go and the Gin framework. It supports markdown-based blog posts and static pages that automatically appear in the navigation when added."
show_quick_links: true
disable_landing_page: false
# Server Settings
port: 8080
# Pagination
posts_per_page: 10
# RSS Feed
feed_items: 20
# Excerpts
excerpt_length: 200
# Social Media Links
show_social_links: true
social_twitter: ""
social_bluesky: ""
social_linkedin: ""
social_github: ""
social_reddit: ""
social_facebook: ""
# Analytics
umami_script_url: "" # e.g., "https://analytics.yourdomain.com/script.js"
umami_website_id: "" # Your Umami website ID
# Paths (relative to application root)
posts_folder: "posts"
static_folder: "static"
templates_folder: "templates"
assets_folder: "assets"Configuration Options:
site_title- The name of your website (appears in navigation and page titles)site_description- A brief description of your site (used in meta tags and homepage)site_author- Your name (appears in footer)site_author_url- Optional URL to link your name in the footer (e.g., personal website)site_url- Full URL of your site (used in RSS feed and sitemap)home_intro- Introduction text displayed on the homepage (appears in the About section)show_quick_links- Toggle Quick Links section on homepage (true/false, default: true)disable_landing_page- If true, shows blog list directly on index instead of landing page and hides "Posts" menu link (true/false, default: false)port- The port number the server will run on (default: 8080)posts_per_page- Number of posts to show per page (default: 10)feed_items- Number of items to include in RSS feed (default: 20)excerpt_length- Maximum characters for post excerpts (default: 200)show_social_links- Toggle social media icons in footer (true/false, default: false)social_twitter- Twitter/X profile URL (e.g., "https://twitter.com/yourusername")social_bluesky- Bluesky profile URL (e.g., "https://bsky.app/profile/yourusername")social_linkedin- LinkedIn profile URL (e.g., "https://linkedin.com/in/yourusername")social_github- GitHub profile URL (e.g., "https://github.com/yourusername")social_reddit- Reddit profile URL (e.g., "https://reddit.com/user/yourusername")social_facebook- Facebook profile URL (e.g., "https://facebook.com/yourusername")umami_script_url- Umami analytics script URL (e.g., "https://analytics.yourdomain.com/script.js")umami_website_id- Your Umami website ID for trackingposts_folder- Directory containing blog posts (default: "posts")static_folder- Directory containing static pages (default: "static")templates_folder- Directory containing HTML templates (default: "templates")assets_folder- Directory containing CSS/images/etc (default: "assets")
Note: If config.yaml is not found, Podium will use default values. Only social media icons with configured URLs will be displayed.
Start the server:
# Production mode
go run main.go
# Development mode with hot reload
go run main.go -devThe application will start on http://localhost:8080
Development Mode Features:
- Hot reload - Automatically reloads templates and config when files change
- Debug logging - More verbose output for troubleshooting
- No caching - Fresh content on every request for easier development
Configuration Hot Reload:
In both development and production modes, Podium watches config.yaml for changes. When you update the configuration file (e.g., add a new social media link, change site title, etc.), the changes are automatically applied within ~500ms without requiring a server restart. This works even when running as a system service!
You can run Podium in two ways: directly from the terminal or as a system service.
Perfect for development, testing, or quick usage:
Option 1: Run with Go (Development)
# Production mode
go run main.go
# Development mode with hot reload (recommended for development)
go run main.go -dev
# Or use make
make runOption 2: Run the compiled binary
# Build first
make build
# Run in foreground (see logs, stop with Ctrl+C)
bin/podium
# Run in background
bin/podium &
# Run with nohup (survives terminal close)
nohup bin/podium > podium.log 2>&1 &When running directly:
- ✅ No installation needed
- ✅ See logs in terminal
- ✅ Easy to start/stop
- ✅ No admin/sudo required
⚠️ Stops when terminal closes (unless using nohup/background)⚠️ Doesn't start automatically on boot
For production use, auto-start on boot, and background operation:
See the System Service Installation section below.
When running as a service:
- ✅ Starts automatically on boot
- ✅ Runs in background always
- ✅ Managed by OS (systemd/launchd/Windows Service)
- ✅ Auto-restart on failure (OS-dependent)
⚠️ Requires installation step⚠️ May need admin/sudo (Linux)
Podium includes build scripts and Makefile for easy compilation across platforms.
Using Makefile (Recommended):
# Build for current platform
make build
# Build for all platforms
make build-all
# Build for specific platforms
make build-linux
make build-macos
make build-windowsUsing build scripts:
Linux/macOS:
./build.sh # Build for current platform
./build.sh all # Build for all platforms
./build.sh linux macos # Build for specific platforms
./build.sh clean # Clean build artifactsWindows:
build.bat REM Build for current platform
build.bat all REM Build for all platforms
build.bat clean REM Clean build artifactsAll binaries are placed in the bin/ directory:
bin/
├── podium # Current platform binary
├── podium-linux-amd64 # Linux 64-bit
├── podium-linux-arm64 # Linux ARM64
├── podium-darwin-amd64 # macOS Intel
├── podium-darwin-arm64 # macOS Apple Silicon
└── podium-windows-amd64.exe # Windows 64-bit
The build script supports the following options:
current- Build for current platform only (default)all- Build for all supported platformslinux- Build for Linux (amd64 and arm64)macosordarwin- Build for macOS (amd64 and arm64)windows- Build for Windows (amd64)clean- Remove all build artifacts
You can also build manually with Go:
# Current platform
go build -o bin/podium .
# Cross-compile for specific platform
GOOS=linux GOARCH=amd64 go build -o bin/podium-linux-amd64 .
GOOS=windows GOARCH=amd64 go build -o bin/podium-windows-amd64.exe .
GOOS=darwin GOARCH=arm64 go build -o bin/podium-darwin-arm64 .- Create a new
.mdfile in theposts/directory - Optionally add front matter at the top:
Tags: tag1, tag2, tag3- Add tags for categorizationDate: 2025-11-03- Publication date (YYYY-MM-DD format)PublishDate: 2025-12-01 09:00- Schedule post for future publicationFeatured: true- Pin post to top of blog list with special badgeDraft: true- Mark as draft to hide from public view
- Start your content with a heading (e.g.,
# My Post Title) - Write your content using Markdown syntax
- The post will automatically appear in the blog posts list (unless it's a draft or scheduled for future)
Example:
Tags: golang, tutorial, webdev
Date: 2025-11-03
Featured: true
# My Awesome Post
This is my blog post content with **bold** and _italic_ text.
## Code Example
\`\`\`go
func main() {
fmt.Println("Hello, Podium!")
}
\`\`\`Features:
- Tags: Automatically extracted and displayed on posts. Click a tag to filter posts.
- Dates: Posts are sorted by date (newest first) and show publication date and reading time.
- Featured Posts: Add
Featured: trueto pin posts to the top of the list with a ⭐ badge and special styling. Perfect for announcements or popular content. - Post Scheduling: Add
PublishDate: 2025-12-01 09:00to schedule a post for future publication. Format isYYYY-MM-DD HH:MM(24-hour time). Posts remain hidden until the publish date/time arrives. - Drafts: Add
Draft: trueto hide a post until you're ready to publish. - Excerpts: The first 200 characters (configurable) appear on the posts list page.
- Reading Time: Automatically calculated based on word count (~225 words/minute).
Tags: announcement
Date: 2025-11-05
PublishDate: 2025-12-01 09:00
# Future Announcement
This post will automatically become visible on December 1st, 2025 at 9:00 AM.
No server restart needed!- Create a new
.mdfile in thestatic/directory - Optionally add
Draft: trueat the top to hide the page - Start your file with a heading (e.g.,
# Page Title) - Write your content using Markdown syntax
- The page will automatically appear in the navigation menu (unless it's a draft)
Example:
# About
This is my about page...Note: Static pages don't have dates or tags - they're timeless content like About, Contact, etc.
- Headings (H1-H6)
- Bold and italic text
- Lists (ordered and unordered)
- Code blocks with syntax highlighting (powered by highlight.js)
- Inline code
- Blockquotes
- Links and images
- Tags for blog posts
- And more!
/- Home page (or redirects to/postsifdisable_landing_pageis true)/posts- List of all blog posts (with pagination)/posts/:slug- Individual blog post (with share buttons)/page/:slug- Static page/tags/:tag- Filter posts by tag (with pagination)/feed.xml- RSS/Atom feed for blog subscribers/sitemap.xml- XML sitemap for search engines/assets/*- Static assets (CSS, JS, images, etc.)404- Custom error page for not found resources500- Custom error page for server errors
Podium includes a dark/light theme toggle in the navigation. The theme preference is saved to the user's browser localStorage and persists across sessions.
Edit assets/style.css to customize the look and feel of your website. The CSS uses CSS variables for easy theming:
- Light theme colors in
:root - Dark theme colors in
[data-theme="dark"] - Responsive breakpoints at 768px and 480px
- Print-friendly styles in
@media print
Modify the HTML templates in the templates/ directory to change the layout and structure.
Individual blog posts include share buttons for:
- Twitter (X)
- Copy link to clipboard
These are automatically included on all blog posts.
- Gin v1.11.0 - Web framework
- Blackfriday v2.1.0 - Markdown parser
- Service - Cross-platform service management
- YAML - YAML configuration parser
- fsnotify v1.9.0 - File system notifications for hot reload
- tdewolff/minify v2 - CSS/JS minification
- imaging v1.6.2 - Image optimization and resizing
- Highlight.js v11.9.0 (CDN) - Syntax highlighting
Podium can be installed as a system service on Windows, macOS, and Linux, allowing it to run automatically on system startup.
# Build the binary
make build
# Install as service (requires sudo)
sudo ./podium -service install
# Start the service
sudo ./podium -service start
# Enable on boot (systemd)
sudo systemctl enable PodiumOr use the provided script:
sudo ./install-service.sh# Build the binary
make build
# Install as service (user-level, no sudo needed)
./podium -service install
# Start the service
./podium -service startOr use the provided script:
./install-service.shNote: On macOS, the service installs as a user-level LaunchAgent. For system-wide installation (LaunchDaemon), you would need to run with sudo, but user-level is recommended for most use cases.
Open Command Prompt or PowerShell as Administrator:
REM Build the binary
go build -o podium.exe
REM Install as service
podium.exe -service install
REM Start the service
podium.exe -service startOr run the provided batch file as Administrator:
install-service.batAll platforms support the following commands:
# Install the service
./podium -service install
# Start the service
./podium -service start
# Stop the service
./podium -service stop
# Restart the service
./podium -service restart
# Uninstall the service
./podium -service uninstallNote: On Linux, you need to use sudo for all service commands.
After installation, you can also use systemctl:
sudo systemctl start Podium
sudo systemctl stop Podium
sudo systemctl restart Podium
sudo systemctl status Podium
sudo systemctl enable Podium # Start on boot
sudo systemctl disable Podium # Don't start on bootService logs can be viewed with:
sudo journalctl -u Podium -fAfter installation, the service is managed by launchd. You can also use:
# Start service
sudo launchctl load ~/Library/LaunchAgents/Podium.plist
# Stop service
sudo launchctl unload ~/Library/LaunchAgents/Podium.plist
# View logs
tail -f ~/Library/Logs/Podium.err.logAfter installation, you can manage the service through:
-
Services Manager (GUI):
- Press
Win+R, typeservices.msc, press Enter - Find "Podium Web Server" in the list
- Right-click to Start/Stop/Restart
- Press
-
Command Line:
sc start Podium sc stop Podium sc query Podium
-
PowerShell:
Start-Service Podium Stop-Service Podium Restart-Service Podium Get-Service Podium
View logs in Event Viewer (Application logs).
The service is configured with the following settings:
- Name: Podium
- Display Name: Podium Web Server
- Description: A lightweight web server for hosting markdown-based websites and blogs
- Port: 8080
- Working Directory: The directory where Podium is installed
Service won't start:
- Ensure port 8080 is not already in use
- Check that the working directory contains the required folders (posts, static, templates, assets)
- On Linux/macOS, verify file permissions
- On Windows, ensure you ran the installation as Administrator
Cannot access the website:
- Verify the service is running
- Check firewall settings to ensure port 8080 is allowed
- Try accessing http://localhost:8080 from the server itself
Service crashes on startup:
- Check system logs for error messages
- Ensure all dependencies are present (templates, assets, etc.)
- Verify the Go binary is compatible with your system architecture
Podium includes several performance optimizations to ensure fast page loads:
CSS and JavaScript files are automatically minified in production mode:
- Reduces file sizes by 30-60%
- Faster page load times
- Automatic in production, disabled in dev mode for easier debugging
Images can be dynamically optimized and resized:
<!-- Original image -->
<img src="/assets/image.jpg" alt="Original" />
<!-- Resized by width (maintains aspect ratio) -->
<img src="/assets/image.jpg?w=800" alt="Resized" />
<!-- Resized by width and height -->
<img src="/assets/image.jpg?w=800&h=600" alt="Exact size" />
<!-- Optimized quality (reduced file size) -->
<img src="/assets/image.jpg?optimize=true" alt="Optimized" />Features:
- On-demand image resizing
- Quality optimization for JPEG and PNG
- Automatic max-width limiting (1920px)
- Lazy loading enabled by default
Smart caching headers are automatically set:
- CSS/JS: 7 days
- Images: 30 days
- Fonts: 1 year
- HTML: 5 minutes with revalidation
- ETag support for 304 Not Modified responses
Podium automatically generates a sitemap at /sitemap.xml including:
- Homepage and blog posts page
- All published blog posts with lastmod dates
- All static pages
- RSS feed
- Proper priority and changefreq values
To run Podium in development mode (not as a service):
# Run directly
go run main.go
# Or use make
make runThis is useful for development and testing, as you'll see output directly in the terminal.
Use the Makefile to build for specific platforms:
# Build for current platform
make build
# Build for Linux
make build-linux
# Build for Windows
make build-windows
# Build for macOS
make build-macos
# Build for all platforms
make build-allThis project is open source and available under the MIT License.