Writing

Notes on Bubble.io, AI, and shipping things.

67 posts on Bubble.io, AI, n8n, and shipping production apps that hold up.

Chrome extension version-bump discipline: pre-commit + GitHub Actions: cover image

Latest

· 8 min read · chrome-extension , github-actions , pre-commit-hooks

Chrome extension version-bump discipline: pre-commit + GitHub Actions

The Chrome Web Store rejects re-uploads with the same manifest version. Catch the missed bump in pre-commit; gate it again in CI.

Read as a series

Topical clusters meant to be read in order, or jumped into anywhere.

Recent writing

View all 67 →

·9 min read · chrome-extension , manifest-v3 , supabase

How to build a Chrome extension popup with Supabase Auth (step by step)

Load Supabase JS into a Manifest V3 popup, persist sessions in chrome.storage, handle popup-reopen state recovery. Step by step.

How to build a Chrome extension popup with Supabase Auth (step by step): cover image

·12 min read · chrome-extension , manifest-v3 , chrome-web-store

Shipping a Manifest V3 Chrome extension: the gates nobody mentions

Trader verification, publisher identity, the URL slug gotcha, version-bump CI. The async gates that turn a one-day project into a three-week project.

Shipping a Manifest V3 Chrome extension: the gates nobody mentions: cover image

·9 min read · methodology , ai-assisted-development , refactoring

Phased migrations with per-phase verification gates

Big-bang rewrites of 6+ files break things you cannot predict. Phased migration with explicit gates is slower and catches the regressions early.

Phased migrations with per-phase verification gates: cover image

·10 min read · claude-code , claude-md , lovable

How I document AI-built projects: a CLAUDE.md, ISSUES.md, and prompts/ workflow

The four-part system I install on day one of every inherited Lovable, Cursor, or Claude Code project: CLAUDE.md template, ISSUES.md learning log, prompts/ folder, two-AI workflow.

How I document AI-built projects: a CLAUDE.md, ISSUES.md, and prompts/ workflow: cover image

·9 min read · react-hook-form , zod , react

How to migrate a useState form to React Hook Form and Zod (the real walkthrough)

Step-by-step migration of one form from useState plus inline validation to React Hook Form plus Zod plus shadcn Form. Code diffs and the mode choice.

How to migrate a useState form to React Hook Form and Zod (the real walkthrough): cover image

·8 min read · supabase , supabase-auth , supabase-publishable-key

Migrating to Supabase publishable keys broke my Chrome extension. Here is the fix.

Supabase's new sb_publishable_* keys return 401 when sent as raw apikey headers, and the JS SDK defaults to localStorage which a Manifest V3 Chrome extension cannot use. Here is the migration: deleting hand-rolled fetch wrappers, switching to @supabase/supabase-js, and the chrome.storage.local adapter that keeps sessions persistent.

Migrating to Supabase publishable keys broke my Chrome extension. Here is the fix.: cover image

·9 min read · lovable , lovable-security , supabase

How to audit a Lovable app after the BOLA disclosure: a 6-hour rotation playbook

Lovable's April 2026 BOLA vulnerability exposed projects created before November 2025. Here is the audit checklist I ran on a client's Supabase-backed Lovable app, the 6-hour key rotation that followed, and the Chrome-extension SDK migration nobody warned us about.

How to audit a Lovable app after the BOLA disclosure: a 6-hour rotation playbook: cover image

·8 min read · supabase , supabase-realtime , security

Realtime broadcast scope is a security boundary, not a routing convenience

Default-public Realtime broadcasts leak message bodies to every subscriber. The private-channel flag is the fix; here is when to use it.

Realtime broadcast scope is a security boundary, not a routing convenience: cover image

·7 min read · security , supabase , auth-jwt

User enumeration via password reset: the bug in default forgot-password flows

Most forgot-password endpoints leak whether an email exists. The fix is one rule: return the same response always, regardless of account status.

User enumeration via password reset: the bug in default forgot-password flows: cover image

·7 min read · security , supabase , edge-functions

Origin validation in edge functions: the open redirect you ship by default

Edge functions that trust the Origin header for redirect URLs are open-redirect vulnerable. Here's the allowlist pattern that closes the gap.

Origin validation in edge functions: the open redirect you ship by default: cover image
Browse all 67 posts in the archive

All topics