Starting with the original problem
This site replaced a WordPress installation. The previous setup was a minimal theme with placeholder content, running on shared hosting with a single MySQL database. It worked, in the sense that pages loaded and the server didn’t catch fire. But it was also carrying security debt that isn’t obvious until you start counting.
Shared hosting plus WordPress plus a database means: WordPress core, a theme, potentially several plugins, PHP itself, MySQL, and the hosting control panel — all of which need to be kept current, all of which have CVE histories, and all of which are interconnected in ways that make “just update the plugin” more complicated than it sounds.
That’s not a criticism of WordPress specifically. It’s a description of the attack surface that comes with any server-side, database-backed CMS.
What static output changes
The rebuilt site uses Astro, configured for purely static output. The build process runs locally: Astro compiles Markdown content and Astro components into plain HTML files, which are then uploaded to the same shared hosting over FTP. The server delivers those files. That’s the entirety of the runtime.
There’s no PHP executing on the server. There’s no database accepting queries. There’s no plugin architecture, no WordPress login endpoint, no admin panel exposed to the internet. The attack surface on the hosting side is reduced to “file server that speaks HTTP.”
This doesn’t mean a static site can’t be compromised — you can still host malicious content in static files, and the build machine and deployment pipeline are part of the attack surface. But those are a much smaller and more controlled set of concerns than a live server-side application.
Self-hosted fonts, zero third-party requests
The original site pulled fonts and scripts from external CDNs. Every external request is a dependency: on the CDN’s availability, on the CDN’s privacy policies, and potentially on the CDN’s integrity if they’re ever compromised.
The rebuilt site loads fonts via @fontsource — self-hosted NPM packages that bundle the font files directly into the build output. There are no Google Fonts requests, no third-party script tags, no external domains in the <head>. A user loading this page is connecting only to this server.
This is a small thing, but it’s consistent with the principle that data which never leaves your infrastructure can’t be logged somewhere else.
Zero JavaScript by default
Astro’s default behavior is to ship zero client-side JavaScript unless explicitly added. This site doesn’t add any. Every page is inert HTML and CSS.
This matters because JavaScript is the primary vector for client-side attacks: XSS, supply-chain compromises via npm packages, and any number of third-party snippet vulnerabilities. If there’s no script to inject into, that class of attack doesn’t apply.
The only dynamic interaction on this site is the contact form, which submits to Web3Forms — a static-friendly service that handles email delivery without requiring server-side code here. That’s one external dependency, scoped to one user action, with a clear data flow.
The maintenance argument
Security posture isn’t just about the initial setup — it’s about what happens over the next three years when you’re not actively thinking about it.
A static site doesn’t have plugin update prompts, PHP version EOL notices, or database credentials that need rotating. The hosting is essentially maintenance-free from a security standpoint. Uploading updated HTML files when content changes is the whole deployment process.
That simplicity is a security property. Systems that are easy to understand are easier to reason about, and systems that require no ongoing intervention don’t accumulate deferred maintenance debt.
The trade-off
This approach isn’t right for every site. Dynamic content, user accounts, e-commerce, and real-time features all require server-side logic, and “use a static site” isn’t a universal recommendation.
But for a consulting site whose content changes infrequently and whose needs amount to “pages, a blog, and a contact form,” the dynamic stack is overhead without benefit. Removing that overhead is a legitimate security improvement, not just a developer preference.
The simpler the system, the smaller the surface.