The playbook behind the portfolio
The conventions that let fifteen sites ship in a summer. Nothing here is clever — it's the same handful of decisions, made once, applied everywhere.
The deploy stack
Every site in the index ships the same way:
- Static first. Plain HTML, CSS and vanilla JavaScript, published straight from the repo root — no bundler, no build pipeline. A framework (Next.js) only when a site genuinely needs app behaviour.
- Netlify everywhere. One host, one CLI, one
netlify.tomlshape per site. - Serverless only on demand. Functions exist where a feature demands them — form pipelines, news ingestion — and nowhere else.
The standard netlify.toml starts here:
[build]
publish = "."
command = ""
[[headers]]
for = "/*"
[headers.values]
X-Frame-Options = "SAMEORIGIN"
X-Content-Type-Options = "nosniff"
Referrer-Policy = "strict-origin-when-cross-origin"
# Assets change often while iterating — revalidate each load
# (cheap 304 via ETag) so fixes go live immediately.
[[headers]]
for = "/assets/*"
[headers.values]
Cache-Control = "public, max-age=0, must-revalidate"
The launch checklist
SEO plumbing goes in on day one — it takes ten minutes and never has to be retrofitted:
- Real
<title>and meta description on every page sitemap.xmllisting every canonical URLrobots.txtpointing at the sitemap- Canonical link tags and Open Graph basics
- Favicon (even a simple one)
- Security headers in
netlify.toml - Verify the live URL returns 200 — never assume a deploy worked
Launching dark, going public
A site running on sample data can be live without being findable. The pattern:
- Ship with
X-Robots-Tag: noindex, nofollowin the headers and a disallow-allrobots.txt. - When the sample data is replaced (or the decision is made deliberately), flip both in one deploy: allow-all robots pointing at a sitemap, header removed.
- Verify the flip from outside — request the live headers, don't trust the config.
Two hard-won cautions that belong in every deploy review:
- CLI deploys ignore
.gitignore. If a file is in the publish directory, it ships. Internal docs belong outside the publish tree — or deploy from a sanitized staging copy. - Netlify redirect splats only match at the end of a path.
A rule like
/*.mdquietly does nothing; per-file rules withforce = trueare what actually shadow uploaded files.
DNS patterns
Two patterns cover the whole portfolio:
- Netlify DNS (most sites): point the registrar's nameservers at the four Netlify assigns. Everything else is automatic.
- Registrar DNS: keep DNS at the registrar with an
apex
Arecord to75.2.60.5and awwwCNAME to<site>.netlify.app.
Either way, HTTPS provisions itself once DNS propagates. Verify with a real request, not the dashboard.
How progress gets captured
Every site in the index has a status page with a timestamped snapshot of its current state, the paths on the table, and a requirements checklist. The data behind those pages lives in one JSON file in the repo. When recommendations get adopted, the review runs again: completed requirements move to the done list, a new dated snapshot lands in the progress log, and the pages regenerate. The index is a build log, not a museum.