惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
雷峰网
雷峰网
J
Java Code Geeks
G
Google Developers Blog
博客园 - 司徒正美
The GitHub Blog
The GitHub Blog
L
LangChain Blog
人人都是产品经理
人人都是产品经理
GbyAI
GbyAI
Vercel News
Vercel News
S
SegmentFault 最新的问题
Engineering at Meta
Engineering at Meta
H
Hackread – Cybersecurity News, Data Breaches, AI and More
云风的 BLOG
云风的 BLOG
F
Fortinet All Blogs
Y
Y Combinator Blog
博客园_首页
Last Week in AI
Last Week in AI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
罗磊的独立博客
A
About on SuperTechFans
B
Blog
Microsoft Security Blog
Microsoft Security Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
I Built a Blazing Fast Website for $0/Month — Here's the ...
LaserEngrave · 2026-05-03 · via DEV Community

Page Speed Insights

Page Speed Insights
I was running a WordPress site on shared hosting. $15/month, a plugin that needed updating every other Tuesday, and a Time to First Byte that made me want to apologize to every visitor.

You know the feeling. You install a caching plugin to fix your slow WordPress site. The caching plugin needs a configuration plugin. The configuration plugin conflicts with your SEO plugin. Now you have three plugins doing one job badly and your Core Web Vitals score looks like a participation trophy.

I got fed up and rebuilt everything from scratch. The result is laserengraverexpert.com — a laser engraver review site running on Hugo 0.147.0, hosted on Cloudflare Pages, deploying in ~25 seconds, and costing me exactly $0/month to host.

This article is the full technical breakdown. Stack, config, reasoning, trade-offs, and the one thing I got wrong at first that added two days of debugging. If you're building a content site, affiliate site, documentation, or anything that doesn't need a database — this stack deserves serious consideration.

The Full Stack at a Glance

| Layer | Tool / Cost |
|---|---|
| Static Site Generator | Hugo 0.147.0 — Free |
| Hosting + CDN | Cloudflare Pages free tier — $0/month |
| Analytics | Cloudflare Web Analytics — $0/month |
| Build Config | `wrangler.toml` |
| Images | WebP (converted from source) — Free |
| Domain | Namecheap — ~$10/year |
| Database | None |
| Server runtime | None |

Enter fullscreen mode Exit fullscreen mode

Total infrastructure cost: ~$10/year. That's the domain. Everything else is free.

Why Hugo Over Eleventy, Next.js, or Gatsby

This is the question I spent the most time on before building. Let me give you the honest version, not the 'all tools are great for different use cases' non-answer.

  • Next.js — I considered it. The ecosystem is excellent and I know React. But Next.js is built for apps. Static export works, but you're fighting the framework every time you want pure static output. The build output is heavier than it needs to be for a content site, and Vercel's free tier has bandwidth caps that start to matter if you get traffic.

  • *Gatsby *— It was the right answer in 2019. The GraphQL data layer is powerful but it's overhead I don't need. Build times got notoriously slow on larger sites, and the ecosystem has fragmented. I didn't want to bet a production site on it.

  • Eleventy (11ty) — This was the closest competitor. Eleventy is genuinely excellent. It's JavaScript all the way down, zero opinions, highly composable. If you're already deep in the Node ecosystem and want maximum flexibility, Eleventy is your pick. I came close to using it.

  • Why Hugo won: Speed. Not website speed — build speed. Hugo builds are measured in milliseconds. My current site with all its content builds in under 400ms. With Eleventy I was looking at 3-5 seconds for a comparable site. When you're iterating on layouts and templates, that difference matters a lot during development.

  • Hugo is also a single binary. No node_modules. No package.json. No dependency hell. You install one binary and you're running. On Cloudflare Pages this means the build environment is clean, reproducible, and fast.

  • The trade-off: Go templating. Hugo's template syntax has sharp edges — the pipe syntax, .context scoping, and partial rendering model trip people up. I'm not going to pretend the learning curve doesn't exist. It does. But it pays off.
    ────────────────────────────────────────────────────────────────────────

Cloudflare Pages Setup

Sign up for a Cloudflare account if you don't have one. Connect your GitHub repo. That's the core of it — but there are a few specifics worth knowing.
In the Cloudflare Pages dashboard:
• Click 'Create a project' → 'Connect to Git'
• Select your repo
• Set build command: hugo --minify
• Set build output directory: public
• Add environment variable: HUGO_VERSION = 0.147.0
📌 If you don't pin your Hugo version, Cloudflare uses an old default. My local build was fine, Cloudflare's build was failing because it ran Hugo 0.92 against templates written for 0.147. Two days of confusion. Set the version explicitly.

Free tier gives you 500 builds per month. For a content site with a reasonable publishing cadence you'll never hit that. I've never exceeded 30 in a month.

Every push to main triggers a build and deploy. Every pull request gets a preview deployment with its own URL — great for reviewing changes before merging.
────────────────────────────────────────────────────────────────────────

The wrangler.toml Config — Full Breakdown

This file controls everything about how Cloudflare builds and serves your site.

[build]
  command = "hugo --minify"
  publish = "public"

[build.environment]
  HUGO_VERSION = "0.147.0"

[[headers]]
  for = "/*"
  [headers.values]
    X-Content-Type-Options = "nosniff"
    X-Frame-Options = "DENY"
    Referrer-Policy = "strict-origin-when-cross-origin"
    Permissions-Policy = "camera=(), microphone=(), geolocation=()"
    Strict-Transport-Security = "max-age=31536000; includeSubDomains; preload"
    Content-Security-Policy = "default-src 'self'; script-src 'self' 'unsafe-inline' static.cloudflareinsights.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self' cloudflareinsights.com; frame-ancestors 'none';"

[[headers]]
  for = "/css/*"
  [headers.values]
    Cache-Control = "public, max-age=31536000, immutable"

[[headers]]
  for = "/js/*"
  [headers.values]
    Cache-Control = "public, max-age=31536000, immutable"

[[headers]]
  for = "/img/*"
  [headers.values]
    Cache-Control = "public, max-age=31536000, immutable"

Enter fullscreen mode Exit fullscreen mode

────────────────────────────────────────────────────────────────────────

Cache Strategy — Why Immutable Caching Is a Game Changer

max-age=31536000 means browsers cache files for one year. immutable tells the browser not to even bother revalidating — if the file is in cache, use it without a network round trip.

The obvious question: what if you update your CSS? You use content-addressed filenames. Hugo's asset pipeline fingerprints files — adds a hash of the contents to the filename.

{{ $css := resources.Get "css/main.css" | minify | fingerprint }}

When the file changes, the hash changes, the filename changes, and the browser treats it as a new file. A user who visited yesterday loads your page today without downloading a single CSS or JS byte.
────────────────────────────────────────────────────────────────────────

The WebP Image Pipeline

WebP files are 60–80% smaller than JPEG at equivalent visual quality. A 400KB product JPEG becomes a 90KB WebP. Multiply across 30 images and you've saved several megabytes per visit.
cwebp -q 82 source-image.jpg -o converted-image.webp
Quality 82 is the sweet spot for product photography — visually indistinguishable from the source, dramatically smaller. For critical above-the-fold images add loading="eager" and fetchpriority="high". Everything else gets loading="lazy".
────────────────────────────────────────────────────────────────────────

The Build Pipeline

Full flow from git push to live site updating:
• git push origin main — pushes to GitHub
• GitHub webhook fires to Cloudflare Pages (~1 second)
• Cloudflare spins up a build container
• Container installs Hugo 0.147.0 (pinned via env variable)
• Runs hugo --minify (~300–400ms for my site)
• Cloudflare receives the public/ directory output
• Files propagate to Cloudflare's edge network globally
• Live site updated

Total time: approximately 25 seconds end to end.
The JSON output is worth setting up even if you don't use it immediately:
[outputs]
home = ["HTML", "RSS", "JSON"]

This generates an index.json at root — ready for client-side search (Fuse.js, Pagefind) without any future build changes.
────────────────────────────────────────────────────────────────────────

Performance — What to Expect

With this exact stack you get:
• No render-blocking resources
• No JavaScript on most pages (analytics beacon is deferred)
• WebP images with lazy loading
• Immutable cache on all static assets
• HTTP/2 and HTTP/3 via Cloudflare (free, automatic)
• Brotli compression on all responses (free, Cloudflare handles it)

A site built this way should score 95–100 on Lighthouse Performance consistently. TTFB under 200ms globally. FCP under 0.8 seconds on a decent connection.
The only thing that tanks performance on a site like this is unoptimized images. The WebP pipeline is the work you have to do. Everything else the stack handles for you.
────────────────────────────────────────────────────────────────────────

Cost Breakdown

Service Free Limit / Cost
Cloudflare Pages hosting Unlimited bandwidth — $0/month
Cloudflare Pages builds 500 builds/month — $0/month
Cloudflare Web Analytics Unlimited — $0/month
GitHub Public/private repos — $0/month
Domain (Namecheap) ~$10/year

Total: ~$10/year. Cloudflare Pages has no bandwidth cap — unlike Netlify/Vercel free tiers. High-traffic days cost $0.
────────────────────────────────────────────────────────────────────────

The Honest Trade-offs — What This Stack Cannot Do

• No dynamic content — Hugo outputs the same HTML for every visitor.
• No user accounts — Login, saved preferences, personalization require a separate backend.
• No comments — Need Giscus, Disqus, or a serverless function.
• No server-side search — Must use client-side (Fuse.js, Pagefind) or a third party.
• Content updates require a build — No CMS dashboard. Pair with Forestry/CloudCannon for non-technical editors.
────────────────────────────────────────────────────────────────────────

Conclusion

The site is live at laserengraverexpert.com — including the laser engraver comparison guides. Run it through PageSpeed Insights if you want to see what this stack produces in practice.
Cloudflare delivers it from an edge node near your visitor. The browser caches your assets for a year. You pay $10/year for the domain and nothing else.
This isn't the right stack for everything. But for content sites where long-term success depends on fast load times, low overhead, and not paying more as you scale — it's the most honest setup I've found..

Marcus Webb writes about laser engravers and the tools he uses to build around them at laserengraverexpert.com