A modern, sleek, dark-mode-native blog built with Rust. Drop Markdown files and they automatically become pages.
- Rust Backend: Axum + Tokio
- Server-Side Rendering: Manual HTML templates
- Hot Reload: Drop a .md file, see it instantly
- Dark Mode Native: Respects
prefers-color-scheme - View Transitions: Smooth page navigation
- Accessibility: Focus states, skip link, ARIA landmarks
- Reduced Motion: Respects
prefers-reduced-motion - SEO Ready: RSS feed, sitemap, robots.txt, OG/Twitter cards
- Tag Support: Clickable tags and tag index pages
- Docker & Docker Compose
- (Optional) Rust 1.88+ for local development
# Build and run container
docker compose up --build
# Or via make
make build runAccess at http://localhost:8080
Drop Markdown files into the content/ directory:
content/posts/my-post.md -> /posts/my-post
content/pages/about.md -> /about
---
title: My Post Title
date: 2024-01-15T10:00:00Z
tags: [tag1, tag2]
draft: false
description: Optional description
---
Your content here...Note: Date must be in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ).
- First H1 is automatic: The post title from frontmatter is rendered as H1. Don't add another H1 at the start of your content - it will be automatically stripped.
- Use H2 (
##) for sections within posts.
matrix/
├── server/ # Rust project
│ ├── src/
│ │ ├── main.rs # Entry point
│ │ ├── lib.rs # Library root, logging init
│ │ ├── app.rs # Router setup
│ │ ├── routes/ # HTTP handlers
│ │ │ ├── index.rs # Home page
│ │ │ ├── posts.rs # Post pages
│ │ │ ├── pages.rs # Static pages
│ │ │ ├── seo.rs # robots.txt, sitemap.xml, feed.xml
│ │ │ └── tags.rs # Tag index and tag pages
│ │ ├── content/ # Markdown parsing, caching, loader
│ │ ├── templates/# HTML rendering (manual string building)
│ │ └── watcher.rs# File system monitoring (hot reload)
│ └── Cargo.toml
├── content/
│ ├── posts/ # Blog posts (.md)
│ └── pages/ # Pages (.md)
├── static/ # CSS, JS, assets
├── docker-compose.yml
├── Dockerfile
├── DEPLOYMENT.md
└── .github/
└── workflows/
└── publish.yml
| Path | Handler |
|---|---|
/ |
List all posts |
/posts/{slug} |
Single post |
/about |
About page |
/tags |
All tags |
/tags/{tag} |
Posts by tag |
/feed.xml |
RSS feed (HTML page) |
/atom.xml |
RSS feed (XML for subscriptions) |
/sitemap.xml |
XML sitemap |
/robots.txt |
Robots.txt |
/static/* |
Static assets |
# Run unit tests
cargo test --manifest-path server/Cargo.toml
# Or via make
make test
# Check formatting
cargo fmt --manifest-path server/Cargo.toml -- --check
# Run clippy lints
cargo clippy --manifest-path server/Cargo.toml -- -D warningsProduction now uses a modular registry-based flow:
- Push to
main - GitHub Actions runs formatting, clippy, and tests
- GitHub Actions builds and pushes
ghcr.io/opusnano/matrix - GitHub Actions triggers a Coolify deploy webhook
- Coolify pulls the prebuilt image and deploys it to
matrix.hexnode.online
The published image is public, so Coolify can pull it without registry credentials.
See DEPLOYMENT.md for the full setup, required secrets, Coolify configuration, and rollback steps.
Logs use structured logging via tracing:
# View logs
docker compose logs -fEdit static/css/style.css to customize colors, spacing, etc.
Edit server/src/templates/mod.rs to change page layouts.
MIT