# rsdlt.dev > Personal blog of Rodrigo Santiago, a product leader with nearly 15 years in fintech and telecom (Fiserv, Nextel México) and the co-founder and CEO of Foambyte, a production-management platform for craft brewers that he designed and built. He writes about full-stack TypeScript architecture (React, Hono, Cloudflare Workers, PostgreSQL), building production software with AI coding agents such as Claude Code, and Rust. Every post is first-hand: it documents a decision made on a real codebase, the alternatives considered and the trade-offs. A single file with the full text of every post is at https://rsdlt.dev/llms-full.txt. ## About - [About Rodrigo Santiago](https://rsdlt.dev/): Bio, experience and links - [Foambyte engineering series](https://rsdlt.dev/foambyte/): 15 posts on the architecture behind Foambyte, oldest first - [Building levi](https://rsdlt.dev/levi/): 10 posts on building levi, a Rust git diff viewer, with Claude Code ## Foambyte engineering - [Vite+ 1.0 Is Out: Should Foambyte Trade Its Toolchain for One Command?](https://rsdlt.dev/posts/vite-plus-1-0-unified-toolchain-foambyte-evaluation/): What VoidZero shipped in Vite+ 1.0, a unified vp command for Vite, Vitest, Oxlint, Oxfmt, tsdown and caching tasks, and the pros and cons we're weighing for Foambyte. - [How I Use Claude Code on a Production SaaS Without Vibe Coding](https://rsdlt.dev/posts/claude-code-production-saas-ai-coding-guardrails/): The guard rails behind AI-assisted development at Foambyte: CLAUDE.md as a contract, pinned skills, permission denies, diff review, audits and deploy gates. - [Integration Testing a Cloudflare Workers API Against Real Postgres with PGlite](https://rsdlt.dev/posts/integration-testing-cloudflare-workers-postgres-pglite-vitest/): How Foambyte runs 330+ Vitest integration tests against an in-process Postgres 18 with PGlite in about 10 seconds, including multi-tenant isolation tests. - [Migrating from SQLite to PlanetScale Postgres 18 and TimescaleDB on Cloudflare Workers](https://rsdlt.dev/posts/planetscale-postgres-timescaledb-cloudflare-hyperdrive-migration/): Why Foambyte moved from SQLite to PlanetScale Postgres 18 with TimescaleDB through Cloudflare Hyperdrive, and the playbook for a short, verifiable cutover. - [Hono on Cloudflare Workers: Leaving a Docker VPS and Getting the Middleware Order Right](https://rsdlt.dev/posts/hono-cloudflare-workers-middleware-security-rate-limiting/): Why I moved Foambyte's API from Docker Swarm to Hono on Cloudflare Workers, and the middleware chain for rate limiting, CAPTCHA, sessions and plan gating. - [End-to-End Type Safety Without tRPC: A Shared Hono + Zod OpenAPI Contract](https://rsdlt.dev/posts/end-to-end-type-safety-hono-zod-openapi-monorepo/): How Foambyte's React frontend and Hono API share one type-checked contract in a Turborepo monorepo: Drizzle, drizzle-zod, zod-openapi and shared route paths. - [One React Codebase for Web, iOS and Android: Vite, TanStack and Capacitor](https://rsdlt.dev/posts/react-capacitor-tanstack-one-codebase-web-ios-android/): Why I built Foambyte as a React 19 SPA packaged with Capacitor instead of React Native or Next.js, and the TanStack Query pattern that keeps it maintainable. - [Building a Recipe Calculation Engine in TypeScript: IBU, SRM, Fermentability and FG](https://rsdlt.dev/posts/recipe-calculation-engine-typescript-ibu-srm-fermentability/): Designing Foambyte's brewing recipe engine: an ordered chain from volumes to OG, IBU, attenuation, FG, ABV and SRM, built as pure TypeScript functions. - [Self-Hosting a Turborepo App with Docker, Bun, nginx and Traefik](https://rsdlt.dev/posts/self-hosting-turborepo-docker-bun-traefik-swarm/): How Foambyte's React SPA and Hono API ran on a VPS: multi-stage Docker builds for a Turborepo monorepo, a Bun runtime, nginx, Traefik and Docker Swarm. - [From Path Aliases to a Real Package: Lessons from a pnpm + Turborepo Monorepo](https://rsdlt.dev/posts/pnpm-turborepo-monorepo-shared-package-lessons/): How Foambyte's React app and Hono API share code in a pnpm + Turborepo monorepo, why path aliases broke Docker builds, and the setup that works. - [Offline-First Editing with TanStack Query Persistence and Last-Write-Wins Patches](https://rsdlt.dev/posts/offline-first-tanstack-query-persistence-last-write-wins/): How Foambyte kept recipe edits working offline: a persisted TanStack Query cache, a last-write-wins patch queue, and one merge function shared with the server. - [Testing Brewing Math: Unit Tests for IBU, Color and Carbonation Calculators](https://rsdlt.dev/posts/unit-testing-brewing-calculators-vitest-ibu-srm-carbonation/): How I test Foambyte's brewing calculators with Vitest and Zod: reference values, round trips, behavior checks and 330+ tests for IBU, SRM and CO2. - [ArkType vs Zod: Why I Standardized on Zod Across Forms, API and Database](https://rsdlt.dev/posts/arktype-vs-zod-validation-drizzle-openapi-tanstack-form/): I started Foambyte with ArkType and switched to Zod. The deciding factor wasn't speed or syntax but integrations: drizzle-zod, zod-openapi and TanStack Form. - [Choosing Authentication for a Web + Mobile SaaS: Why better-auth](https://rsdlt.dev/posts/better-auth-hono-drizzle-capacitor-web-mobile-authentication/): Why Foambyte uses better-auth with Hono and Drizzle instead of Clerk, Auth0 or Supabase Auth, and how cookie sessions work across the web and Capacitor apps. - [Adopting the React Compiler Early in a React 19 + Vite App](https://rsdlt.dev/posts/react-compiler-vite-react-19-production-app/): Why I turned on the React Compiler (RC) in Foambyte's React 19 + Vite app, how to set it up with Babel and ESLint, and the rules I follow so it can do its job. ## Building levi - [Building levi, Nine Days Later: A Neovim Plugin That Hands Your Coding Agent a Commit](https://rsdlt.dev/posts/levi-neovim-plugin-floating-window-send-commit-to-coding-agent-terminal/): levi's Neovim plugin: :Levi opens the git log in a floating window, and :LeviSend types a commit, file and lines into your agent's Neovim terminal, unsent. - [Building levi, Wednesday: Telling Any Coding Agent What You Have Open, With levi --focus and tmux](https://rsdlt.dev/posts/levi-focus-tell-coding-agent-what-you-see-tmux-plugin-rust-tui/): levi 0.20: levi --focus prints what an open levi shows, so any agent can look at your screen, and a tmux plugin types a commit reference into an agent's pane. - [Building levi, Tuesday: Watching an Agent's Uncommitted Changes Without Touching the Index](https://rsdlt.dev/posts/levi-uncommitted-changes-git-working-tree-without-writing-index/): levi 0.19: uncommitted changes as a row on top of the log, live as an agent edits, read with git plumbing so levi never writes to .git. - [Building levi, Monday: Keeping Up With Commits From Another Terminal, and Panes You Can Drag](https://rsdlt.dev/posts/levi-live-refresh-git-repository-watcher-resizable-panes-rust-tui/): levi 0.17 and 0.18: a watcher that asks git every two seconds what changed, loads only new commits, and panes you resize by dragging their borders. - [Building levi, Sunday Morning: Syntax Colors, a Logo, and a Pick That Lands in Your Agent's Input](https://rsdlt.dev/posts/levi-syntax-highlighting-terminal-tints-herdr-coding-agent-plugin/): levi 0.15 and 0.16: syntax colors that follow your terminal's theme, tints mixed from its background, a measured README, and a herdr plugin that hands a commit to a coding agent. - [Building levi, Saturday Evening: Getting a Find Out to Your Clipboard, Your Editor and Your Agent](https://rsdlt.dev/posts/levi-clipboard-osc-52-filter-mode-open-in-editor-rust-tui/): levi 0.13 to 0.14.1: copying over SSH with OSC 52, drag to copy, levi --filter for scripts and coding agents, and Ctrl-O to open a file at the line you're reading. - [Building levi, Day Two: The Polish That Makes a Terminal UI Usable](https://rsdlt.dev/posts/levi-day-two-rust-tui-polish-mouse-no-color-release-binaries/): Ten levi releases of polish: changed-word diffs, mouse support, narrow terminals, NO_COLOR, a demo GIF, a crate name clash and release binaries for every platform. - [Building levi, After Midnight: A 55-Second Code Search Down to 0.16 Seconds](https://rsdlt.dev/posts/levi-code-search-git-log-parallel-55-seconds-to-016/): How levi's /c code search over git history went from 55 seconds to 0.16 on git.git: parallel git log -G, loading history on every core, and searching only what the query matches. - [Building levi, Night One: From First Commit to 0.1.0 in 90 Minutes](https://rsdlt.dev/posts/levi-night-one-rust-tui-git-log-parser-fuzzy-search/): The first session of building levi with Claude Code: parsing git log as a stream, a three-pane TUI on stderr, background loading, fuzzy search on every core, and CI. - [Building levi: A Small, Fast Git Diff Viewer in Rust, Written with Claude Code](https://rsdlt.dev/posts/building-levi-rust-git-diff-viewer-claude-code/): Why I built levi, a terminal git diff viewer with fzf-style search, the design decisions behind it, and how I built it with Claude Code from a written plan. ## Other posts - [Weekly Roundup: The Binance Heist, a Trojanized Claude Code Extension, a Poisoned Monitoring Script and PHP2Shell](https://rsdlt.dev/posts/weekly-roundup-binance-hack-claude-code-extension-polymarket-php2shell/): A $6.3B theft that started on an engineer's laptop, a fake Claude Code update that planted SSH backdoors, a third-party script that drained Polymarket traders, and PHP bugs exploited before disclosure. - [Weekly Roundup: TypeScript in Rust, Agent Skills Goes Neutral, a 68% Cheaper Code Reviewer, and Claude Duet](https://rsdlt.dev/posts/weekly-roundup-tsrs-typescript-rust-agent-skills-ai-code-review-claude-duet/): tsrs ports TypeScript to Rust, Agent Skills moves to the Linux Foundation, Cloudflare cuts AI code review costs 68%, and Anthropic previews Claude Duet. - [Four Things This Week for Solo Builders: Cloudflare Void, Gemini 4 Argon, Meta Muse Wonder and Workers Flamegraphs](https://rsdlt.dev/posts/weekly-roundup-cloudflare-void-gemini-4-argon-meta-muse-wonder-flamegraphs/): A builder's notes on this week's AI and web dev news: Cloudflare open-sources Void, Gemini 4 Argon hits the API, Meta ships Muse Wonder, and Workers gets on-demand CPU and memory profiling. - [Building a Real-Time Web Cipher with Rust, Sycamore and Trunk](https://rsdlt.dev/posts/rust-sycamore-trunk-wasm-iterators-vigenere-cipher/): Building a real-time Vigenère cipher web app in Rust with Sycamore, Trunk and WebAssembly, without writing a single line of JavaScript. - [Implementing the Display Trait on a Generic Array using Newtype Pattern](https://rsdlt.dev/posts/rust-use-newtype-pattern-display-trait-array-generics/): How to implement the Display trait on a generic array in Rust, working around the orphan rule with the newtype pattern and const generics. - [How to Use Rust Traits, Generics and Bounds](https://rsdlt.dev/posts/rust-trait-super-generic-polymorphism-subtrait-supertrait-bounds/): Refactoring Ruxel's vector and point types with generics, supertraits, subtraits and trait bounds to make the code more idiomatic and extensible. - [Ruxel - Building a Ray Tracer with Rust Part 1](https://rsdlt.dev/posts/ruxel-part-1-rust-ray-tracer-renderer-3d-development/): Part 1 of building Ruxel, a ray tracer in Rust: high-level architecture, project scaffolding, and the vector and point types. - [Rust and Neovim - A Thorough Guide and Walkthrough](https://rsdlt.dev/posts/rust-nvim-ide-guide-walkthrough-development-debug/): A detailed walkthrough of how I set up my Rust development environment in Neovim, with rust-analyzer, rust-tools, Tree-sitter and Vimspector debugging. - [Ruxel - Building a Ray Tracer with Rust (Prelude)](https://rsdlt.dev/posts/ruxel-ray-tracer-project-first-update-rust-programming-development/): Introducing Ruxel, a ray tracer and 3D renderer I'm building from scratch in Rust, why I chose it as a project, and my goals for version 0.1.0. - [Basic Operator Overloading with Traits](https://rsdlt.dev/posts/welcome-blog-rust-technology-development-programming-language/): How Rust lets you overload arithmetic operators on your own user-defined types by implementing traits, using vector addition as the running example. ## Optional - [RSS feed](https://rsdlt.dev/rss.xml) - [Sitemap](https://rsdlt.dev/sitemap-index.xml) - [github](https://github.com/rsdlt) - [linkedin](https://www.linkedin.com/in/rsdlt)