Build a Modern Hugo Website with GitHub, Cloudflare, and Resend

1. Introduction
:::info This guide shows how to build and deploy a modern static website using a fully open-source and serverless stack. :::
We will use the following tools:
- Hugo โ fast and flexible static site generator
- GitHub Pages โ free web hosting with Git-based deployment
- Cloudflare โ DNS management, CDN, and HTTPS
- Resend โ transactional email API for contact forms
โ Who is this for?
This setup is ideal for:
- Community and non-profit projects
- Personal websites and portfolios
- Lightweight, multilingual static sites
๐ก Why this stack?
- Free and easy to maintain
- Fast performance with global CDN
- No backend or database needed
- Clean separation between content and infrastructure
๐ฆ What will you learn?
This guide covers:
- Setting up a Hugo site
- Hosting it on GitHub Pages
- Securing it with Cloudflare (DNS + HTTPS)
- Adding a contact form with Resend via Cloudflare Worker
Letโs get started.
2. Setup
๐ ๏ธ Requirements
Make sure the following tools are installed:
- Go (v1.20 or later)
- Git
- Hugo Extended (v0.111 or later)
- Node.js (optional, for advanced features)
๐งฑ Create a new Hugo site
|
|
๐จ Install Hugo Blox theme
Add the Hugo Blox theme as a Git submodule:
|
|
Copy the example site content:
|
|
Install dependencies (optional):
|
|
โ๏ธ Basic configuration
Edit the following files:
config/_default/config.yaml
โ site language, base URLconfig/_default/params.yaml
โ branding, theme settingsconfig/_default/menus.yaml
โ navigation menuassets/media/
โ upload your logo and favicon
Example baseURL
(for GitHub Pages):
|
|
๐ Run local server
|
|
Visit http://localhost:1313 to preview your site.
:::tip Use GitHub Desktop or CLI to version control all changes. :::
3. Content Management
Managing content in Hugo is simple and efficient. All pages and posts are written in Markdown and organized in folders under the content/
directory.
๐๏ธ Content structure
Each language has its own folder:
|
|
Each Markdown file represents a page and includes a front matter block at the top.
Example about.md
:
|
|
โ๏ธ Creating a new page
Use the hugo new
command:
|
|
This will create a file in content/en/about.md
with a pre-filled front matter.
๐ Page types
There are two common types of content:
- Page (
type: page
) โ standalone pages like โAboutโ or โContactโ - Post (
type: post
) โ blog/news entries shown in lists
Use different layouts if needed: page
, post
, or custom layouts.
๐งญ Navigation menu
Define menus in config/_default/menus.yaml
:
|
|
To add multilingual labels, use Hugoโs built-in i18n
system:
|
|
Example en.yaml
:
|
|
๐ Multilingual setup
In config/_default/config.yaml
, define the site languages:
|
|
Use relLangURL
in templates to link between languages.
๐๏ธ Preview your content
Run the local server:
|
|
Check the site in your browser at http://localhost:1313.
Use hugo server --navigateToChanged
to auto-scroll to the last edited page.
:::tip Use clear folder structure and consistent naming. Avoid spaces and uppercase letters in filenames. :::
4. GitHub Deployment
You can deploy your Hugo site automatically to GitHub Pages using GitHub Actions. This approach works for both personal and project sites.
๐งโ๐ป 1. Create a GitHub repository
Create a new repository on GitHub.
Do not initialize it with a README or .gitignore
.
Connect your local project:
|
|
โ๏ธ 2. Add GitHub Actions workflow
Create the file .github/workflows/deploy.yml
:
|
|
๐๏ธ 3. Configure config.yaml
for deployment
In config/_default/config.yaml
, set the correct baseURL
:
|
|
Make sure this path matches your actual repository name.
๐ก๏ธ 4. Enable GitHub Pages
Go to your repository โ Settings โ Pages
Set Source to Deploy from a branch
โ choose gh-pages
branch and / (root)
directory.
GitHub will host your site at:
|
|
๐งช 5. Test the deployment
Every time you push to main
, GitHub will:
- Build your site
- Deploy it to the
gh-pages
branch - Make it available via GitHub Pages
Check the Actions tab for logs and status.
:::tip
If you’re using a custom domain, configure it later via Cloudflare and set it in config.yaml
under baseURL
.
:::
5. Cloudflare Setup
Cloudflare acts as a global CDN, DNS provider, and HTTPS enabler for your static website. It improves performance, reliability, and security.
๐ 1. Add your domain to Cloudflare
- Go to https://dash.cloudflare.com
- Click โAdd a Siteโ
- Enter your custom domain (e.g.
example.com
) - Select the Free Plan
๐งพ 2. Update your domainโs nameservers
Cloudflare will show two nameservers (e.g. sue.ns.cloudflare.com
, tim.ns.cloudflare.com
).
Update your domain registrar (e.g. Swizzonic, GoDaddy) to use these nameservers.
โ ๏ธ DNS changes may take a few hours to propagate.
๐ 3. Set DNS records
Go to DNS โ Records and add:
- Type:
CNAME
- Name:
www
- Target:
yourusername.github.io.
- Proxy status:
Proxied
Optional: add a redirect from root domain to www
using Page Rules.
๐ 4. Configure SSL/TLS
Go to SSL/TLS โ Overview and set:
- SSL Mode:
Full
orFull (Strict)
- Auto HTTPS rewrites: โ enabled
- Always Use HTTPS: โ enabled
Use
Full (Strict)
only if GitHub Pages presents a valid certificate for your domain.
๐ 5. Set custom domain in Hugo
In config/_default/config.yaml
, update:
|
|
If using multilingual setup, set baseURL
under each language.
โ๏ธ 6. Optional: Configure additional features
Cloudflare offers many extras:
- Caching rules
- WAF and security level
- Custom error pages
- Analytics and bot protection
You can manage these via the Cloudflare dashboard as needed.
:::tip
If you’re using www.example.com
, GitHub Pages should serve from gh-pages
branch, and Cloudflare will handle HTTPS and DNS.
:::
6. Resend Contact Form Integration
You can send emails from a static site by using a contact form that submits to a Cloudflare Worker, which then forwards the data via the Resend API.
๐ฌ 1. Create a Resend account and API key
- Go to https://resend.com
- Sign up and verify your email
- Add your domain (e.g.
allegra-march.ch
) - Set up DNS records (SPF, DKIM, DMARC)
- Create an API key under API โ Create API Key
๐งฐ 2. Create a Cloudflare Worker
Install Wrangler (CLI for Cloudflare Workers):
|
|
Login to your Cloudflare account:
|
|
Generate a new Worker:
|
|
Edit src/index.ts
(or index.js
if using JS) with the following:
|
|
Replace YOUR_RESEND_API_KEY
and email addresses.
๐ 3. Set your Resend key as a secret
|
|
In your code, replace the key with:
|
|
๐ 4. Deploy the Worker
|
|
Note the deployed URL (e.g. https://contact-worker.yourname.workers.dev
)
๐ 5. Add the contact form to your Hugo site
|
|
Style with CSS as needed.
๐งช 6. Test your form
- Fill out the form on your site
- Check your inbox
- Monitor delivery in the Resend dashboard
:::tip To prevent abuse, consider adding a simple honeypot field or reCAPTCHA. You can also validate requests in the Worker. :::
7. Security & Spam Protection
To prevent abuse of your contact form, it’s important to implement basic security and anti-spam measures. Static sites have no backend, so the protection must happen inside the Cloudflare Worker.
๐ 1. Enforce request method and content type
Make sure your Worker only accepts POST
requests with JSON payload:
|
|
๐งช 2. Validate user input
Always sanitize and validate user input in the Worker:
|
|
๐งฑ 3. Honeypot field (invisible trap)
Add a hidden field in your HTML form:
|
|
In the Worker, check if it’s filled:
|
|
Bots will likely fill hidden fields; real users wonโt.
โฑ 4. Rate limiting (basic)
Cloudflare Workers donโt provide built-in rate limiting, but you can add logic using IP address + KV:
- Track timestamp of last submission per IP
- Block repeated requests within N seconds
- Example: use Cloudflare KV or durable objects (advanced)
๐งฉ 5. reCAPTCHA (optional)
You can integrate Google reCAPTCHA v2/v3:
- Add a reCAPTCHA widget to the form
- Get the token on submit
- Send the token to the Worker
- Verify token via Google API inside the Worker
Requires server-side verification and is more complex to implement.
โ๏ธ 6. Email protections via Resend
In your Resend dashboard:
- Enable SPF, DKIM, and DMARC on your domain
- Monitor bounce/spam reports
- Use a verified
from:
address to avoid spam filters
:::tip Start simple with a honeypot and basic validation. Add rate-limiting or CAPTCHA only if spam becomes a problem. :::
8. Conclusion & Resources
By following this guide, youโve built a modern, fast, and secure static website using:
- Hugo for content generation
- GitHub Pages for hosting
- Cloudflare for DNS, CDN, and HTTPS
- Resend for handling contact form emails via API
This stack is fully serverless, free to use, and easy to maintain. Itโs suitable for personal projects, non-profits, and multilingual community websites.
โ Summary of key benefits
- Fast and optimized delivery via CDN
- No backend or database required
- Secure contact form with spam protection
- Easy to version, update, and collaborate via Git
- Zero hosting cost (if using free tiers)
๐ Useful resources
- Hugo Documentation: https://gohugo.io/documentation/
- Hugo Blox Theme: https://docs.hugoblox.com/
- GitHub Pages: https://pages.github.com/
- Cloudflare Docs: https://developers.cloudflare.com/
- Resend API: https://resend.com/docs
- Wrangler CLI: https://developers.cloudflare.com/workers/wrangler/
๐ Final note
You now have a powerful foundation for your website โ one that is fast, scalable, and privacy-respecting.
Extend it further with:
- Hugo shortcodes, partials, and custom layouts
- Cloudflare KV for storing form submissions
- Resend Webhooks for tracking delivery status
- GitHub Actions for content automation
:::info This guide is maintained by [Your Name] and used in real-world non-profit and volunteer projects. :::