Zero to running blog in under 5 minutes.
Download a release from GitHub Releases, or build from source:
git clone https://github.com/1mb-dev/markgo.git && cd markgo
make buildThe binary lands at ./build/markgo.
markgo init --quickThis creates a .env config and an articles/ directory with sample content (an article, a thought, and a link post). Templates and static assets are embedded in the binary — no web/ directory needed.
markgo serveVisit http://localhost:3000. Your blog is live.
MarkGo has three content types. You never pick one — the system infers it from what you write.
# Article — has a title, intended for long-form
markgo new --title "How I Built This" --tags "golang,blogging"
# Thought — no title needed, short-form
markgo new --type thought
# Link — sharing a URL with commentary
markgo new --type linkArticles are markdown files in articles/ with YAML frontmatter:
---
title: "How I Built This"
description: "A walkthrough of the architecture"
tags: ["golang", "blogging"]
category: "engineering"
date: 2026-02-12T00:00:00Z
---
Your content here, in standard markdown.If you configure admin credentials in .env:
ADMIN_USERNAME=you
ADMIN_PASSWORD=something-strongThen restart the server. You'll see a Compose link in the nav and a floating action button (FAB) on mobile. The compose form puts the cursor in the content field — not the title, not a category picker. Write first, categorize never.
Quick capture: Tap the FAB, type a thought, hit Publish. Under 5 seconds.
Full compose: Navigate to /compose for the full form with title, tags, markdown preview, and image upload.
Edit: Any published post can be edited at /compose/edit/:slug.
You don't choose a type. MarkGo figures it out:
| What you write | What it becomes |
|---|---|
| No title, under 100 words | Thought |
Has a link_url in frontmatter |
Link |
| Everything else | Article |
You can override this by setting type: thought, type: link, or type: article in the frontmatter.
Edit .env. The essential settings:
# Your blog
BLOG_TITLE=My Blog
BLOG_AUTHOR=Your Name
BASE_URL=http://localhost:3000
# For production
ENVIRONMENT=production
BASE_URL=https://yourdomain.comSee configuration.md for every option.
The MarkGo binary embeds all web assets (templates, CSS, JS, images). When you run markgo init, it only creates articles/ and .env — no web/ directory needed.
Filesystem overrides: If you create web/templates/ or web/static/ directories, they take precedence over the embedded assets. This lets you customize the look without forking.
Content-only structure: Your blog is just markdown files and a config file. To move to a new server, copy articles/ and .env, then run the binary.
Download the new binary, replace the old one, restart:
# Stop the server
# Replace the binary
cp markgo-new /usr/local/bin/markgo
# Start the server
markgo serveYour content (articles/) and configuration (.env) are untouched. Embedded assets update automatically with the binary.
make dev # Live reload server at :3000 (requires air)
make build # Build binary
make test # Run tests
make lint # Run linterDocker:
docker compose up -dManual:
make build
scp build/markgo server:/usr/local/bin/See deployment.md for reverse proxy setup, systemd, and production configuration.
- SPA navigation — Instant page transitions, no full reloads
- PWA — Installable, works offline, caches pages for offline reading
- Quick capture — FAB on mobile, Cmd/Ctrl+N on desktop
- Offline compose — Write when disconnected, auto-syncs when back online
- Search — Full-text search across all content
- Feeds — RSS (
/feed.xml), JSON Feed (/feed.json), sitemap (/sitemap.xml) - SEO — Open Graph, Twitter Cards, Schema.org, canonical URLs
- Themes — Light/Dark/Auto mode, 5 color presets, 3 style themes
- Contact form — SMTP email delivery with rate limiting
- Admin panel — Stats, draft management, cache controls
All of this works without JavaScript for core reading. JS enhances, it doesn't gate.
- Configuration — All environment variables
- Architecture — How the system works
- API — Every HTTP endpoint
- Deployment — Production setup
- Design Language — The principles behind the decisions