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