Field note
How This Website Works: Hugo + GitHub Actions + Cloudflare Architecture
This website is built using a modern static site architecture that combines Hugo, GitHub Actions, and Cloudflare to deliver fast, secure, and automated deployments. Here’s how everything works together.
Tech Stack Overview
Static Site Generator: Hugo (Extended version) Source Control: GitHub (github.com/akaJedi/f12) CI/CD: GitHub Actions Hosting: GitHub Pages CDN/DNS: Cloudflare Domain: www.f12.biz
Architecture Diagram
┌─────────────────┐
│ Local Machine │
│ (Hugo Dev) │
└────────┬────────┘
│ git push
▼
┌─────────────────┐
│ GitHub Repo │
│ (main branch) │
└────────┬────────┘
│ triggers
▼
┌─────────────────┐
│ GitHub Actions │
│ - Build Hugo │
│ - Minify │
│ - Deploy │
└────────┬────────┘
│ publishes to
▼
┌─────────────────┐
│ GitHub Pages │
│ (gh-pages) │
└────────┬────────┘
│ served via
▼
┌─────────────────┐
│ Cloudflare │
│ CDN + DNS │
└────────┬────────┘
│
▼
┌─────────────────┐
│ www.f12.biz │
│ (visitors) │
└─────────────────┘The contact form and website chat are the dynamic parts of the site. They call a Cloudflare Worker, which persists chat leads in D1 and exchanges owner messages through the Telegram Bot API.
┌─────────────────┐
│ Contact Form │
│ www.f12.biz │
└────────┬────────┘
│ POST JSON
▼
┌─────────────────┐
│ Cloudflare │
│ Worker │
└────────┬────────┘
│ Telegram Bot API
▼
┌─────────────────┐
│ Telegram Chat │
└─────────────────┘Deployment Workflow
1. Local Development
I develop and preview the site locally using Hugo’s built-in server:
hugo serverThis runs a live-reloading dev server at http://localhost:1313
2. Git Push to Main Branch
When I’m ready to publish changes, I commit and push to the main branch:
git add .
git commit -m "Add new blog post"
git push origin main3. GitHub Actions Automation
The push triggers a GitHub Actions workflow (.github/workflows/deploy.yml):
name: Deploy Hugo site to GitHub Pages
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Setup Hugo (Extended)
uses: peaceiris/actions-hugo@v2
with:
hugo-version: 'latest'
extended: true
- name: Build site
run: hugo --minify
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public
publish_branch: gh-pagesWhat happens here:
- Checks out the repository code
- Installs Hugo Extended (required for SCSS processing)
- Builds the site with
hugo --minify(optimizes HTML/CSS/JS) - Deploys the generated
/publicfolder to thegh-pagesbranch
4. GitHub Pages Hosting
The gh-pages branch contains the fully built static site. GitHub Pages serves these files automatically.
5. Cloudflare Layer
Cloudflare sits in front of GitHub Pages providing:
- DNS Management: Routes
www.f12.bizto GitHub Pages - CDN: Caches static assets globally for faster load times
- SSL/TLS: Provides HTTPS encryption
- DDoS Protection: Shields the site from attacks
- Performance: Minification, compression, and optimization
Contact Form Worker
The contact and chat backends are intentionally kept separate from the static website. The Hugo site contains only the public Worker URL and frontend JavaScript. The Telegram credentials are stored in Cloudflare Worker secrets/variables, not in this public repository.
Required Cloudflare Worker configuration:
TELEGRAM_BOT_TOKEN: Telegram bot token from BotFatherTELEGRAM_ADMIN_CHAT_ID: destination Telegram chat id
Operational notes:
- Create or rotate the bot token in BotFather.
- Open the bot in Telegram and send
/startbefore testing. - Use
https://api.telegram.org/bot<token>/getUpdatesto verify the chat id. - Store the values in Cloudflare Worker settings as secrets/variables.
- Do not commit token values or chat ids to the public website repository.
If the Worker returns 401 Unauthorized, the bot token is invalid or missing. If it returns 400 Bad Request: chat not found, the token works but the bot cannot access the configured chat yet.
Contact Form Health Check
A scheduled GitHub Actions workflow (.github/workflows/contact-form-healthcheck.yml) sends a test payload to the production Worker once per day. This is an end-to-end production check: it verifies the Worker URL, CORS handling, Telegram token, chat id, and Telegram delivery path.
The workflow does not store Telegram secrets. It uses only the public Worker URL and a harmless test message. A successful run requires an HTTP 200 response with {"success": true}.
Resume Automation Workflow
I also have a secondary workflow (.github/workflows/update-resumes.yml) that automatically updates resume metadata:
name: Update Resume Metadata
on:
push:
paths:
- "static/DenisTolochko_*"
branches:
- main
workflow_dispatch:
jobs:
update:
runs-on: ubuntu-latest
steps:
- name: Run Bash generator
run: bash scripts/resume-list-generator.sh
- name: Enrich with VirusTotal
run: python scripts/vt_update.py
env:
VT_API_KEY: ${{ secrets.VT_API_KEY }}
- name: Commit changes
run: |
git add data/resumes.yaml
git commit -m "Update resumes.yaml with VT links"
git pushWhat this does:
- Triggers when resume files are updated
- Generates resume metadata
- Enriches with VirusTotal scan links for security verification
- Commits the updated
data/resumes.yamlback to the repo
Hugo Configuration
The site uses Hugo modules to load the theme:
baseURL = "https://www.f12.biz"
relativeURLs = true
canonifyURLs = true
[module]
[[module.imports]]
path = "github.com/zetxek/adritian-free-hugo-theme"Benefits of This Architecture
Fully Automated: Push to main = instant deployment Version Controlled: Every change is tracked in Git Fast: Static files + CDN = millisecond load times Secure: No server-side code, HTTPS by default Cost-Effective: GitHub Pages is free, Cloudflare free tier is generous Scalable: Can handle traffic spikes without breaking Developer-Friendly: Edit in any text editor, preview locally
Deployment Time
From git push to live site: ~1-2 minutes
The entire build and deployment process is automated, tested, and reliable.
This infrastructure represents years of iteration to find the right balance between simplicity, performance, and maintainability. Static sites with automated deployments are my preferred approach for content-focused websites.
No databases to maintain, no servers to patch, no security vulnerabilities to worry about. Just content, version control, and CI/CD.