Case studies, not a tech stack list.
Selected work with the problem, approach, and outcome behind it.
// loading projects...
Selected work with the problem, approach, and outcome behind it.
// loading projects...
Chrome Extension + CRM Dashboard for content creator agencies. Manages subscriber communication, automates messaging, and tracks revenue performance across multiple creators.
Creator agencies were messaging subscribers manually inside platform-native inboxes, with no shared history, no automation, and no visibility into which messages actually drove revenue.
The extension had to feel invisible, agencies were not going to change their workflow to adopt a new tool. So the CRM layer was built around their existing inbox, not instead of it. Automation rules were kept simple and inspectable so agency staff could trust and adjust them.
Adopted by hundreds of agencies globally, with measurable revenue lift attributed directly to the automated messaging flows.
Context: The dashboard prototype had grown into a large application on the same build setup as the browser extension, and slow rebuilds were costing real development time as the feature set expanded.
Decision: Migrated the dashboard to Vite as part of the rewrite, while leaving the browser extension on its original build tool, where it was already stable and not the bottleneck.
Consequence: Local dev feedback loops dropped from seconds to near-instant, letting the team ship new automation features noticeably faster during the product's highest-growth period.
Context: The dashboard's feature surface was growing fast (automations, billing, team accounts), and silent type mismatches were becoming a real source of production bugs. The browser extension's codebase was smaller and already stable.
Decision: Added TypeScript to the new dashboard as part of the rewrite, and left the extension on plain JavaScript rather than retrofitting types onto working code for marginal benefit.
Consequence: The growing dashboard caught a meaningful share of bugs at build time instead of in production, while engineering time didn't get spent adding type coverage where it wouldn't have paid off.
Context: The original dashboard leaned on a heavier, opinionated UI library, and every visual tweak meant fighting its defaults or waiting on its release cycle.
Decision: Rebuilt the UI on shadcn/ui, owned component code rather than an installed package, on top of Tailwind.
Consequence: Design changes that used to require workarounds became direct edits to code the team already owned, and the dashboard's look could evolve on the product's own timeline instead of a dependency's.