A modern, high-performance blog built with Go, Templ templates, and Tailwind CSS. Features real-time search, GitHub-repo based content management, and automatic post updates via webhooks.
You can give the live site a spin at jgn.dev
Designed and optimized for exceptional web performance:
🏆 100 Lighthouse Score in all categories when deployed to GCP Cloud Run Service.
- Modern Go Stack: Go 1.24 + Echo v4 + Templ templates + Tailwind CSS v4
- GitHub Content Management: Posts and Cheatsheets stored as Markdown in GitHub repositories
- Real-time Search: HTMX-powered search with tag and title filtering for both posts and cheatsheets
- Webhook Auto-Updates: Automatically refreshes content when posts or cheatsheets are added to GitHub
- Responsive Design: Mobile-first design with dark/light mode support
- Syntax Highlighting: Code blocks with Tokyo Night Dark theme (consistent across light/dark modes)
- SEO Optimized: Structured data, meta tags, and semantic HTML
- Production Ready: Docker containerization for GCP Cloud Run deployment
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ GitHub Posts │ │ jgn.dev │ │ GitHub │
│ & Cheatsheets │───▶│ Application │◀───│ Webhook │
│ (Markdown) │ │ (Go + Templ) │ │ (Auto-refresh)│
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Content API │ │ GCP Cloud Run │ │ Real-time │
│ (GitHub API) │ │ (Containers) │ │ Search │
│ │ │ │ │ (HTMX) │
└─────────────────┘ └──────────────────┘ └─────────────────┘
Backend:
- Go 1.24 with Echo v4 framework
- Templ for type-safe HTML templates
- GitHub API for content management (posts and cheatsheets)
- HTMX for dynamic interactions
Frontend:
- Tailwind CSS v4 for styling
- Vanilla JavaScript for theme switching
- Highlight.js for syntax highlighting
- Responsive design with mobile navigation
Infrastructure:
- Docker for containerization
- GCP Cloud Run for hosting
- GCP Artifact Registry for image storage
- GCP Cloud Build for automated deployments
jgn.dev/
├── docs/
│ ├── gcp-deployment-guide.md # GCP Cloud Run deployment guide
│ ├── cicd-guide.md # CI/CD pipeline guide
│ ├── webhook-setup-guide.md # GitHub webhook setup
│ └── github-token-setup-guide.md # GitHub token configuration
├── internal/
│ ├── application/ # HTTP handlers and controllers
│ ├── contentmanager/ # GitHub integration and content fetching
│ ├── views/ # Templ templates and components
│ └── site/ # Site configuration and metadata
├── public/
│ ├── css/ # Stylesheets and themes
│ ├── js/ # JavaScript files
│ ├── font/ # Web fonts (Inter, JetBrains Mono)
│ ├── img/ # Images and static assets
│ └── txt/ # Text files (robots.txt)
├── scripts/
│ ├── deploy-gcp-cloud-run.sh # GCP Cloud Run deployment script
│ ├── run-dev.sh # Development environment orchestration
│ ├── templ-watch.sh # Template hot reloading
│ ├── tailwind-watch.sh # CSS hot reloading
│ └── test-webhook.sh # Webhook testing utility
├── server/
│ └── main.go # Application entry point
├── Dockerfile # Container configuration
├── package.json # Tailwind CSS dependencies
├── go.mod # Go module dependencies
└── README.md # This file
- Go 1.24+
- Docker (for deployment)
- Node.js (for Tailwind CSS)
- gcloud CLI (for GCP deployment)
- GitHub Personal Access Token (setup guide)
-
Clone the repository
git clone https://github.com/jgndev/jgn.dev.git cd jgn.dev
-
Install dependencies
go mod download go install github.com/a-h/templ/cmd/templ@latest go install github.com/cosmtrek/air@latest npm install
-
Set environment variables
export GITHUB_TOKEN=your_github_token_here # See: docs/github-token-setup-guide.md export GITHUB_WEBHOOK_SECRET=$(openssl rand -hex 32) # Optional
-
Start development environment
Option A: All-in-One Script (Recommended)
./scripts/run-dev.sh
This single command:
- ✅ Checks prerequisites and environment
- ✅ Runs initial builds
- ✅ Starts Tailwind CSS watch (background)
- ✅ Starts Templ template watch (background)
- ✅ Starts Air Go hot reload (foreground)
- ✅ Provides proper cleanup on Ctrl+C
Additional commands:
./scripts/run-dev.sh stop # Stop all processes ./scripts/run-dev.sh restart # Restart all processes ./scripts/run-dev.sh status # Show process status
Option B: Manual Setup (Advanced)
If you prefer to run each process manually in separate terminals:
Terminal 1 - Templ Watch:
./scripts/templ-watch.sh
Terminal 2 - Tailwind Watch:
./scripts/tailwind-watch.sh
Terminal 3 - Go Server with Air:
air
-
Visit http://localhost:8080
The application will automatically reload when you make changes to:
- Go files (via Air)
- Templ templates (via templ-watch.sh)
- CSS styles (via tailwind-watch.sh)
Deploy to GCP Cloud Run for cost-effective, scalable hosting:
export PROJECT_ID=your-gcp-project-id
export GITHUB_TOKEN=your_token
export GITHUB_WEBHOOK_SECRET=your_webhook_secret
./scripts/deploy-gcp-cloud-run.sh
Why Cloud Run:
- ✅ Pay-per-use pricing (can cost as little as $0-5/month for low traffic)
- ✅ Automatic scaling to zero when not in use
- ✅ Built-in SSL certificates and global load balancing
- ✅ Easy custom domain configuration
- ✅ Integrated CI/CD with Cloud Build
- ✅ Better cost efficiency compared to always-on services
- ✅ Built-in health monitoring and auto-restart
📖 Detailed Instructions: See GCP Deployment Guide for complete setup instructions and configuration options.
This project uses GitHub Actions for automated CI/CD with optimized Docker builds:
- ✅ Smart CI Pipeline: Runs comprehensive code quality checks on all branches except main
- ✅ Automated Deployment: Builds and deploys Docker images when PRs are merged to main
- ✅ Cost Optimized: Pre-built images eliminate expensive Cloud Build cycles
- ✅ Fast Deployments: Pre-built Docker images deploy 3-5x faster
- ✅ Automatic Cleanup: Maintains only the 10 most recent images
- ✅ Health Checks: Built-in deployment verification
- CI Pipeline (
.github/workflows/ci.yml
): Code formatting, linting, testing, and vulnerability scanning - Deployment Pipeline (
.github/workflows/deploy.yml
): Docker build, push to Artifact Registry, and Cloud Run deployment
📖 Setup Instructions: See DEPLOYMENT.md for complete GitHub Actions configuration and required secrets.
Enable automatic content updates when you add new blog posts:
- Generate a webhook secret:
openssl rand -hex 32
- Configure the webhook in your GitHub posts repository
- Set the webhook URL to:
https://yourdomain.com/webhook/github
📖 Detailed Instructions: See Webhook Setup Guide for step-by-step configuration.
- GitHub Integration: Posts and Cheatsheets stored as Markdown files in separate GitHub repositories
- Automatic Refresh: Webhook-triggered content updates without server restarts
- Frontmatter Support: YAML frontmatter for post and cheatsheet metadata (title, date, author, summary, tags, etc.)
- Real-time Search: HTMX-powered search across post titles and tags
- Posts Listing: Paginated view of all posts, sorted by date
- Individual Post Pages: Clean, readable post layout with syntax highlighting
- Cheatsheets Listing: Paginated view of all cheatsheets, sorted by date
- Cheatsheets Search: Search for cheatsheets by title or tag
- Individual Cheatsheet Pages: Clean, readable cheatsheet layout with syntax highlighting
- Mobile Navigation: Hamburger menu with smooth animations
- Fast Loading: Optimized Docker images and efficient Go backend
- Consistent Syntax Highlighting: Tokyo Night Dark theme in both light and dark modes
- Dark/Light Mode: Enhanced dark mode with deeper colors
- Responsive Design: Mobile-first approach with Tailwind CSS
Required:
GITHUB_TOKEN
: Personal access token for GitHub API access (setup guide)
Optional:
GITHUB_WEBHOOK_SECRET
: Secret for webhook signature verificationPORT
: Server port (default: 8080)
Edit internal/site/site.go
to configure:
- Post and cheatsheet repository owners and names
- Site metadata and branding
- Navigation links
- Create a Markdown file in your posts repository
- Add frontmatter:
--- id: unique-post-id title: "Your Post Title" date: 2024-01-15T00:00:00Z author: "Jeremy Novak" tags: ["go", "web-development", "gcp"] slug: your-post-slug published: true summary: "A short summary of the post." ---
- Write your content in Markdown
- Commit and push - the site will automatically update via webhook
💡 Check out the posts repository at github.com/jgndev/posts for examples.
- Create a Markdown file in your cheatsheets repository (github.com/jgndev/cheatsheets)
- Add frontmatter:
--- id: unique-cheatsheet-id title: "Go Slices Cheatsheet" date: 2024-01-20T00:00:00Z author: "Jeremy Novak" tags: ["go", "slices", "reference"] slug: go-slices published: true summary: "Quick reference for Go slices syntax and operations." ---
- Write your cheatsheet content in Markdown
- Commit and push - the site will automatically update via webhook
💡 See github.com/jgndev/cheatsheets for examples.
id
: Unique identifier for the post or cheatsheettitle
: Title (required)date
: Publication date in RFC3339 formatauthor
: Author namesummary
: Short summary for cards and SEOtags
: Array of tags for categorizationslug
: URL slug (auto-generated if not provided)published
: Boolean to control visibility
- Posts:
/posts
(browse, search, and filter posts) - Cheatsheets:
/cheatsheets
(browse, search, and filter cheatsheets) - Search:
/search
(posts),/cheatsheets/search
(cheatsheets) - Individual Pages:
/posts/:slug
,/cheatsheets/:slug
This project uses a comprehensive GitHub Actions workflow for every push and pull request:
- Formatting:
go fmt
andgoimports
for code and import style - Static Analysis:
go vet
,staticcheck
, andgolangci-lint
(includes ineffassign, misspell, errcheck, gosec, gocyclo, and more) - Vulnerability Scanning:
govulncheck
for dependency security - Templ Generation: Ensures all Templ files are generated before analysis
- Build: Verifies the application builds
- Tests: Runs all Go tests with race detection and coverage
- Coverage: Uploads coverage to Codecov
See .github/workflows/ci.yml
for the full workflow.
docker build -t jgn-dev .
docker run -p 8080:8080 \
-e GITHUB_TOKEN=your_token \
-e GITHUB_WEBHOOK_SECRET=your_secret \
jgn-dev
export GITHUB_WEBHOOK_SECRET=your_secret
./scripts/test-webhook.sh
go test ./...
-
Templ generation fails
- Install templ CLI:
go install github.com/a-h/templ/cmd/templ@latest
- Run
templ generate
before building
- Install templ CLI:
-
Tailwind styles not loading
- Build CSS:
npx tailwindcss -i ./public/css/style.css -o ./public/css/site.css --minify
- Check file paths in templates
- Build CSS:
-
GitHub API rate limiting
- Set
GITHUB_TOKEN
environment variable (setup guide) - Verify token has repository read permissions
- Set
-
Webhook not working
- Check webhook secret matches environment variable
- Verify webhook URL is publicly accessible
- Check server logs for error messages
-
GCP deployment issues
- Verify gcloud authentication:
gcloud auth list
- Check project permissions and enabled APIs
- Review Cloud Run service logs in GCP Console
- Verify gcloud authentication:
-
Font files not loading (404 errors)
- Ensure fonts are copied in Dockerfile:
COPY --from=go-builder /app/public/font/ ./public/font/
- Rebuild and redeploy the container image
- Ensure fonts are copied in Dockerfile:
GCP Cloud Run pricing is usage-based, making it very cost-effective:
- CPU: $0.00002400 per vCPU-second
- Memory: $0.00000250 per GiB-second
- Requests: $0.40 per million requests
- Networking: Egress charges apply
Estimated costs for a personal blog:
- Low traffic (1K visits/month): $0-2/month
- Medium traffic (10K visits/month): $2-8/month
- High traffic (100K visits/month): $15-30/month
- Deployment Setup: GitHub Actions CI/CD setup, required secrets, and GCP configuration
- Project Overview: Comprehensive project architecture and feature overview
- GCP Deployment Guide: Complete GCP Cloud Run deployment instructions
- CI/CD Guide: CI/CD pipeline configuration and setup
- GitHub Token Setup Guide: Step-by-step guide to create and configure GitHub Personal Access Tokens
- Webhook Setup Guide: GitHub webhook configuration for automatic updates
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature
- Commit changes:
git commit -m 'Add amazing feature'
- Push to branch:
git push origin feature/amazing-feature
- Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Documentation: Check the guides in the
docs/
folder - Issues: Open a GitHub issue for bugs or feature requests
- Contact: Open an issue for support
Built with 🤓 using Go, Templ, Tailwind CSS, and deployed on GCP Cloud Run