I wanted to start a blog where I could talk through technical topics while collaborating with an AI assistant. The key requirements were:
Both tools are standalone binaries, which makes deployment simple:
# Install Hugo extended binary
curl -sL https://github.com/gohugoio/hugo/releases/download/v0.165.0/hugo_extended_0.165.0_linux-amd64.tar.gz | tar xz -C ~/bin/
# Install Forgejo
curl -sL https://codeberg.org/forgejo/forgejo/releases/download/v16.0.2/forgejo-16.0.2-linux-amd64 -o ~/bin/forgejo
chmod +x ~/bin/forgejo
cd ~/Blog && hugo new site . --force
git init
git submodule add https://github.com/yihui/hugo-theme-console.git themes/hugo-theme-console
The hugo-theme-console theme gives us a clean, console/terminal-inspired layout with responsive design that works well on both desktop and mobile devices.
Key files created:
hugo.toml - Site configuration (theme, relative URLs for Tailscale compatibility)assets/css/custom.css - Custom CSS for mobile optimizations and theme stylingMakefile - Build automation with commands like make dev, make serve, make push.gitignore - Excludes .env, public/, and build artifactsThe existing Forgejo instance at http://forgejo-1:3000/ was already running on our tailnet. We created the repository and pushed content:
git remote add origin http://forgejo-1:3000/elyons/blog.git
git push -u origin main
This was where we hit our first snag. The correct syntax for exposing the Hugo server is:
# First, enable tailscale serve without sudo (one-time setup)
sudo tailscale set --operator=$USER
# Then expose the blog over HTTPS on your tailnet
cd ~/Blog && make serve
The make serve command runs both hugo build and starts Tailscale serve to expose port 1313. Your blog becomes accessible at:
https://fwai01.<your-tailnet>.ts.net (private, tailnet-only)Now that everything is set up, the workflow is simple:
content/posts/ with YAML frontmattermake build generates static HTML to public/make dev starts live-reload server at http://localhost:1313make serve exposes site over HTTPS on tailnetmake push commits and pushes to Forgejotailscale serve 1313 (just the port number), not URL-based formatsassets/css/custom.css fixes theme coloring on mobile devicesbaseURL = "/" and relativeURLs = true in hugo.toml ensures links work both locally and via TailscaleThis is just the beginning. Future posts will cover:
The beauty of this setup is that content is just markdown files - we can migrate to Cloudflare Pages, Netlify, or any VPS with nginx later without changing the content workflow.
This post was written collaboratively with an AI assistant using Hugo and the hugo-theme-console theme.