Articles

A Multi-Site Inbound Lead Engine for a One-Person Business: The Whole Series

Every article from building one lead engine across six sites: lead magnets, same-origin forms, consent and double opt-in, email, a pull-only homelab, privacy, and auditing my own sites, each in a line or two.

Read more

Cloudflare Today, Open Source When Needed: A Lead Engine Built to Swap

Why my multi-site inbound lead engine runs on Cloudflare Pages, Workers and KV, what that buys a one-person business, and the exit plan for every piece: what would replace it, and what keeps the swap cheap.

Read more

A Contact Link Instead of an Email in Every Footer

Now that every site has a contact form I can choose to answer, does the email address need to be on every page? Where I removed it, where it has to stay, and the render-blocking script it was costing.

Read more

Share Cards as Code: Rendering og:images with Playwright (JPEG, Not WebP)

One script renders the 1200×630 share cards for three sites and every ebook from HTML, with each site's own fonts. Why the cards are JPEG even though WebP is smaller, and how pages fall back to the site card.

Read more

Checking og:image Properly: Size and Format from the First Bytes

My audit said three sites had a share image. Two shared a 248×56 logo, one a 675 KB square JPEG named .png. How the audit now downloads the image and reads its real format and size from the bytes, safely.

Read more

Lazy-Loading the Cal.com Embed with IntersectionObserver

A booking calendar near the bottom of a landing page was loading about 1 MB of JavaScript on first paint. Twenty lines wrap Cal.com's snippet so it starts only when the calendar is close.

Read more

A Content Security Policy on Cloudflare Pages, Tested in a Real Browser

Adding CSP, HSTS and X-Frame-Options with a _headers file, finding every third party a site really loads, overriding the policy for one path, and catching violations with Playwright before deploy.

Read more

My LCP Was Render Delay: Self-Hosting Google Fonts with Fontsource

Lighthouse said 3.8 s LCP on mobile. The breakdown said almost all of it was render delay from render-blocking font CSS, loaded twice. Self-hosting the fonts brought it to 2.4 s.

Read more

A Missing 404 Page Hid 273 Broken Links

On Cloudflare Pages, a static site without 404.html answers every unknown URL with the homepage and a 200. Link checkers see nothing wrong. Here's how I found out, and the remark plugin that fixed the links.

Read more

I Ran My Website Audit on My Own Sites: 71 to 99

Eating my own dogfood: the free website audit on this site, the ebooks library and the consulting page. The tool had bugs first, then the sites did.

Read more

Android Signing Keys vs Bitcoin Seed Phrases

Understand how an Android PKCS#12 signing key differs from Bitcoin recovery words, passphrases, addresses, and the trust models used by web and desktop apps.

Read more

GitHub Releases and Obtainium for Android APK Updates

A practical guide to signing Android APKs in GitHub Actions and delivering repeatable updates from public GitHub Releases through Obtainium.

Read more

Building a Native Android DJI Tello Controller with Kotlin

How I moved a DJI Tello controller from a Rust desktop prototype to a native Kotlin Android app with Compose, UDP control, H.264 video, and safer flight handling.

Read more

Why a 9 MB Tauri Binary Becomes an 81 MB AppImage

A practical explanation of Rust and Tauri binary size, Cargo target folders, Linux system dependencies, and the portability cost of AppImage bundles.

Read more

A Failed Check Is Not a Bad Score

Why my website audit reports a check that couldn't run as 'not checked' instead of a low score — and the bug in my own report that taught me the difference.

Read more

A Client-Ready HTML Report Without AI

My audit tool's emailed report reads like I wrote it by hand. It's rules and a template: every sentence comes from a measured number. Here's how, and why.

Read more

Pure-Rust Face Detection Without OpenCV or ONNX Runtime

How I added CNN face detection to a Tauri application with pure Rust, compiled model weights, AVX2, and a bounded latest-frame worker.

Read more

Emailing a Full Website Report: Confirm First, Then Crawl

How my audit tool emails a deep report: a signed start link proves the address, a background queue crawls the site, and the report link lives 7 days.

Read more

From Five Lead Silos to One Lead Hub: Before and After

How six sites went from KV, formsubmit, Formbricks, Cal.com and PocketBase to one lead hub — what I gained, what I gave up, and exactly what I capture now.

Read more

A Bind-Mounted Repo Turns Runtime Files Into Git Files

My audit tool's production container mounted the git repo, so live leads were written into a tracked CSV. How I moved runtime data out and pulled safely.

Read more

Debugging a Pasted Secret: The Key Was 65 Characters

A server-to-server call kept failing with 403. A probe that prints only the key's length and hash prefix showed one extra character from a paste.

Read more

Building a DJI Tello Desktop Controller with Rust and Tauri

How I built a working DJI Tello desktop controller with Rust, Tauri, Vue, UDP telemetry, H.264 video, recording, and flight-safety boundaries.

Read more

Server-to-Server Leads: A Key for Kinds Only the Backend May Send

My audit tool's backend posts leads to the same forms Worker as my browser forms. Why that one kind needs a shared key, and how the forward stays best-effort.

Read more

One Checkbox, Two Problems: Unbundling Consent on a Lead-Magnet Form

My website-audit form had one required checkbox that bundled marketing consent and promised an email that never existed. How I split it and made the code match.

Read more

Cloudflare Email Obfuscation Fooled My Deploy Check

My curl-and-grep check found zero email addresses on a page that had them. Cloudflare had rewritten them; here's how to decode data-cfemail and check properly.

Read more

Cal.com Bookings Into My Own Pipeline: a Signed Webhook and a PAID BOOKING Alert

Verifying Cal.com's webhook signature in a Cloudflare Worker, storing only scheduling facts, and getting an urgent phone alert the first time someone pays.

Read more

Replacing a Formbricks Qualifier with My Own Form

Why I moved my consulting qualifier from a hosted Formbricks survey to a same-origin form that lands in the same list as every other lead.

Read more

Deploy a Direct-Upload Cloudflare Pages Site from a Git Worktree

Two direct-upload Pages sites, months-old deploys and untracked drafts in the folder: how a git worktree and npm ci made sure only committed code went live.

Read more

A Weekly ntfy Digest With Counts Only

One low-priority notification a week from my homelab: new leads, confirmed subscribers, drips, suppressions and spam filtered — numbers only, never an address.

Read more

A Mailjet Event Webhook That Only Suppresses Permanent Failures

Feeding Mailjet bounces, spam complaints and blocks into a hashed do-not-send list from a Cloudflare Worker: what to suppress, what to ignore, how to authenticate.

Read more

Writing the Privacy Page Found a Retention Bug

Updating my privacy pages for double opt-in exposed newsletter sign-ups with no expiry. Fixing it meant retention that depends on subscription status.

Read more

A Spam Blocklist That Stores Instead of Drops — and Why I Deferred Turnstile

Scripted sales pitches slipped past my form honeypot. A sender blocklist in the Worker stopped them with zero visitor friction; Turnstile can wait.

Read more

Cloudflare Error 1010 Silently Blocked My Own Homelab Alerts

My homelab's failure alerts never arrived: Cloudflare blocked Python urllib's default User-Agent with error 1010 before the request reached my ntfy server.

Read more

Validate Mermaid Diagrams Before You Push Them

Extract Mermaid blocks from Markdown, check them with mermaid-cli, render PNGs to judge the layout, and the fixes that turned a tangled diagram readable.

Read more

Shell Traps While Watching Logs: grep Buffering and pkill -f Killing Itself

Two shell traps that cost me a test run: a log file that stayed empty because grep buffers, and pkill -f matching its own shell. Causes and reliable fixes.

Read more

Testing Form States with Playwright Route Mocking (Without Sending a Single Email)

How I test every message a form can show, success, check your inbox and the no-JS return, by mocking the forms endpoint in Playwright against a static build.

Read more

From Form to First Drip: Testing an Email Pipeline on Production

How I tested double opt-in and a drip sequence end to end on live sites without emailing real visitors: an allow-list, the checks at each hop, and surprises.

Read more

One Sender Adapter, Two Providers: Switching Mailtrap and Mailjet Without Code Changes

How my Worker and Python hub send through Mailtrap or Mailjet behind one switch, and the provider quirks: auth, success checks, tracking and headers.

Read more

Mailjet Held My Emails: Validating a Sending Subdomain with Cloudflare DNS

SPF and DKIM were right, yet Mailjet held every email. The missing piece was a domain ownership TXT record, placed one level too high by Cloudflare.

Read more

GDPR-Friendly Lead Capture for a Small EU Business

How I capture leads across three sites under GDPR and Polish law: site profiles, recorded consent, double opt-in, retention, erasure and what I keep off the site.

Read more

Architecture Decision Records for a One-Person Business

Why I keep ADRs and learning notes as a solo developer, the format I use, three real examples, and how honest checklists stop me building the wrong thing.

Read more

Debugging Notes from a Week on Cloudflare (and Docker)

Fourteen real Cloudflare Pages, Workers, wrangler, Docker and Python gotchas, each as symptom, cause and fix, collected while shipping lead capture.

Read more

One Canonical Address Per Site: Apex vs www and pages.dev Redirects on Cloudflare

A Cloudflare Pages site answers on apex, www and pages.dev. How I made one host canonical with custom domains, Redirect Rules, Bulk Redirects and a curl check.

Read more

Publish Future-Dated Posts on Cloudflare Pages With a Cron Worker

Static sites only publish posts dated in the past at build time, and Pages only builds on push. A tiny cron Worker and deploy hooks fix scheduled posts.

Read more

A Pull-Only Homelab: Mirroring Cloudflare KV to SQLite Without a Tunnel

How I back up a Cloudflare Workers KV lead inbox into SQLite on a homelab with outbound-only HTTPS, a read-only token, retention rules and a safety brake.

Read more

Mailpit vs Mailtrap vs listmonk: What Each One Is Actually For

A decision record for a small business email stack: test capture with Mailpit, delivery via Mailtrap, why not listmonk, and a sending subdomain with SPF, DKIM and DMARC.

Read more

The Python Email Header Bug That Silently Breaks One-Click Unsubscribe

Python's email package folds a long List-Unsubscribe URL into an RFC 2047 encoded-word that mail clients can't use. How I found it in Mailpit and fixed it.

Read more

A Drip Email Engine in Standard-Library Python

Sequences as TOML files, a send ledger that never emails twice, last-moment suppression checks and a swappable SMTP/Mailtrap sender, with no dependencies.

Read more

A Do-Not-Send List That Stores No Email Addresses

How to build an email suppression list keyed by SHA-256 hashes in Cloudflare KV: written by unsubscribes, checked before every send, kept after erasure.

Read more

Double Opt-In on Cloudflare Workers with Stateless Signed Links

Build double opt-in and one-click unsubscribe in a Cloudflare Worker with HMAC-signed links, no token table, and pages that mail scanners can't trigger.

Read more

Self-Hosting ntfy Behind a Cloudflare Tunnel, Locked Down

Run ntfy on a homelab behind a Cloudflare Tunnel with deny-all access, an admin user for your phone and a write-only publisher token for your sites.

Read more

Retention as a KV TTL: Let the Platform Enforce Your Privacy Policy

Set Cloudflare KV expiration per form kind so your privacy policy's retention periods are enforced by the platform, not by a cleanup job you'll forget.

Read more

One Forms Worker for Every Site: Same-Origin Routes over Cloudflare Pages

How a single Cloudflare Worker serves the contact forms of several Astro and Hugo sites same-origin, using zone routes that take precedence over Pages.

Read more

Contact Forms with Cloudflare Workers KV and Self-Hosted ntfy Alerts

A form backend in about a hundred lines: store each lead in Workers KV first, then push a privacy-friendly ntfy alert to my phone without slowing the visitor.

Read more

app.domain or domain/app? Where to Put a Lead-Magnet PWA (and What It Means for SEO)

Why my Pyodide solver lives on app.multibodysystemsdynamics.com while static Astro pages do the ranking, and how deep links connect the two.

Read more

Ship a Python Library as an Installable Web App with Pyodide

How I run an open-source Python solver in the browser with Pyodide: a pinned, hash-checked wheel, a Web Worker, an atomic service worker and Cloudflare Pages.

Read more

Selfhosted Connectivity: Wi-Fi, LAN Inventory, TR-181, and EasyMesh

A structured homelab connectivity note: Wi-Fi measurements, LAN discovery, TR-471 throughput, TR-181 observability, OpenWrt, and EasyMesh.

Read more

Shipping Custom Sites: The Practices I Keep Across Every Project

The best parts of six real sites, in one checklist: static first, legal pages as Markdown, forms without third parties, security headers, quality gates and more.

Read more

Checking HTTPS Like a Visitor: Certificates, Redirects and TLS Versions in Node

How my website audit checks HTTPS with Node's tls module: certificate validity and expiry, TLS version, the http-to-https redirect, and never penalising what it couldn't see.

Read more

Expiring Report Links: Why My Audit Reports Don't Live Forever

How the website audit tool shares full reports through random, 24-hour tokens instead of guessable IDs, and deletes run files after a week.

Read more

From Scores to Sentences: How My Website Audit Writes a Plain-English Diagnosis

How the audit tool turns Lighthouse JSON, HTML checks and security reports into one readable diagnosis line and a severity-sorted list of the top issues to fix.

Read more

Running Strangers' URLs Safely: The Guards in My Website Audit Tool

A public audit tool fetches whatever URL a stranger types. The guards I use: SSRF checks with DNS, redirect limits, rate limits, a concurrency cap and execFile.

Read more

What My Website Audit Checks and How the Score Is Computed

Every check in my free website audit — Lighthouse, technical SEO, HTTPS and headers, links, latency — and how the weighted grade is built, limits included.

Read more

How My Website Audit Tool Works: Astro, Express and Parallel Shell Audits

The architecture behind a free website audit tool: an Astro front end, an Express API, shell audit phases running in parallel and a tokenized report link.

Read more

Why should you care about DuckDB?

People call DuckDB the 'opposite of Redshift' not because they do different things,

Read more

Rill Architecture Documentation

A deep dive into the Rill BI-as-code platform architecture, technology stack,

Read more

Mastering Healthcare Analytics

Dive into the advanced AI tools within DataNova that automatically detect patterns.

Read more

Consumer Insights Analytics

How to create a Consumer Insights Analytics with AI Powered ChatBot

Read more

Mastering AI-Powered Insights with DataNova’s Smart Analysis Tools

Dive into the advanced AI tools within DataNova that automatically detect

Read more

Advanced Data Cleaning Techniques in Excel

Learn how to clean and prep your data for analysis using DataNova’s intuitive

Read more

Integrating DataNova with Google Sheets for Seamless Collaboration

Discover how to use DataNova’s cloud integration to bring your Excel analytics

Read more

Marketing Analytics Insights

How to use data to optimize marketing campaigns and ROI.

Read more

Customer Segmentation for Real Estate

How to create a Real Estate Customer Segmentation with AI Powered ChatBot

Read more

Shopify Analytics Insights

How to leverage Shopify data for better business decisions and growth.

Read more

Interesting Telecom Concepts

Exploring the fundamental concepts of telecommunications, from cable modems

Read more