The stack
Elixir and Phoenix on the server. Fly.io
for hosting. No database — every post, page, and FAQ entry lives in a single
priv/content/site_content.json file that ships with each deploy. There is
no admin UI. Publishing a post means committing JSON, opening a pull request,
and merging. The whole thing fits in a single Fly machine and costs less than
a coffee a month at current traffic.
Why no CMS — because the editorial bottleneck on this site is writing, not operating a content database. Every layer that exists has to earn its complexity. A CMS for fifty-two posts authored by one person doesn't.
Performance
The site is server-rendered HTML. No SPA, no hydration, no client-side router. The only
JavaScript shipped to readers is the consent banner, the contact form handler, the
analytics shim, and code-block syntax highlighting on post pages. CSS and JS are
fingerprinted and gzipped at build time via mix phx.digest.
The hero image on each post carries fetchpriority="high" and
decoding="async" so it doesn't fight the LCP budget. Prism (syntax highlighting)
is loaded only on pages with code blocks — everywhere else it's dead weight that
never ships.
What I haven't done yet — fonts still come from Google's CDN, and Prism is loaded from jsdelivr. Self-hosting both is on the list. The honest tradeoff is that the current setup is fast enough that the work hasn't been the highest-leverage thing on the queue.
Security
The response headers on every HTML page:
-
Strict-Transport-Securitywith a one-yearmax-ageandincludeSubDomains— HSTS is preloaded. -
Content-Security-Policy-Report-Only— the policy is enumerated and violations are reported but not enforced yet, while the inline-script footprint (consent gate, GTM bootstrap, JSON-LD) is being audited. -
Referrer-Policy: strict-origin-when-cross-origin— third-party referrers see only the origin, not the path. -
Permissions-Policy— disables camera, microphone, geolocation, USB, payment, and a handful of other surfaces this site has no business asking for. -
The defaults Phoenix already sets:
X-Frame-Options,X-Content-Type-Options, and the rest.
Cookies — there is one session cookie used to protect the contact form from CSRF, and one localStorage entry remembering whether you've accepted analytics. Nothing else lands on your machine without consent.
For coordinated disclosure — there's a security.txt at
/.well-known/security.txt.
Email me with anything you find.
Privacy & analytics
Google Analytics 4 with Google Consent Mode v2 — analytics fire only after explicit accept, and gtag loads in a denied state by default. No ad tracking, no third-party data sharing, no remarketing pixels. The full breakdown is on the privacy page.
Accessibility
Target is WCAG 2.2 AA. Body text meets 4.5:1 contrast against the
background; the red accent (#e0112b) is verified safe against
deuteranopia and protanopia, and used as accent rather than as the only signal
for state. prefers-reduced-motion is respected on the consent banner
and any subsequent transitions. Form fields have explicit labels — never
placeholder-only — and errors are tied to fields via aria-invalid and
data-error-for. Keyboard navigation works through every primary flow.
SEO & LLM discovery
Per-page application/ld+json schema (Person, Organization, BlogPosting,
BreadcrumbList, ProfessionalService, FAQPage, CollectionPage, HowTo) is emitted from
a single SublimeCodingWeb.Schema module so the entity graph is
consistent across pages. RSS lives at
/rss.xml; the sitemap at
/sitemap.xml; and an
llms.txt
guide for LLM crawlers at
/llms.txt with a long-form companion at
/llms-full.txt.
New URLs are submitted to Bing and Yandex via IndexNow on publish — there's a background poller that diffs the sitemap and pings the IndexNow API for any added or modified entries.
Source
The whole thing is open to inspection — every file referenced above is in a single Phoenix application I maintain. If you want to see how a specific piece works (the schema generator, the consent gate, the IndexNow submitter), the easiest path is to get in touch and I'll send a pointer.