# Jesse Waites > Technologist & Software Architect building products across AI, web, mobile & hardware. Every blog post is available as Markdown by adding `.md` to its URL. Other pages are HTML. ## Pages - [About](https://jessewaites.com/about): About Jesse - [Portfolio](https://jessewaites.com/portfolio): Projects across web, iOS, macOS, and Android - [AI](https://jessewaites.com/boston-ai-developer): AI-powered things Jesse has built - [Contact](https://jessewaites.com/contact): How to reach Jesse ## Blog posts - [Multiplexing Coding Agents with Conductor: Bob's Garage, Cloned](https://jessewaites.com/blog/post/multiplexing-coding-agents-with-conductor.md): Running five coding agents at once is easy. Getting five pieces of code that actually fit together is the hard part. Here's how I think about git worktrees, Conductor, planner and executor agents, and building in waves. - [Attend My Upcoming AI Talks for Boston AI Week](https://jessewaites.com/blog/post/attend-my-upcoming-ai-talks-for-boston-ai-week.md): I'm speaking at two Boston AI Week events: a hands-on fine-tuning workshop and a practitioner talk on running parallel coding agents with Conductor. - [This Website Now Has Tools for AI Agents](https://jessewaites.com/blog/post/this-website-now-has-tools-for-ai-agents-webmcp.md): OpenAI just shipped WebMCP support in the ChatGPT desktop app, so I added six tools to this site. Your agent can now search my blog, check my speaking schedule, and even restyle the page while you read it. Here are prompts to try. - [Practical Context Engineering](https://jessewaites.com/blog/post/practical-context-engineering.md): Context is a finite resource, and in a web or mobile app you're the one deciding how to spend it. Here's how I think about curating context in apps people actually use. - [Introducing the World's First Generative UI Web Browser](https://jessewaites.com/blog/post/introducing-the-worlds-first-generative-ui-web-browser.md): The world's first Generative UI web browser repaints every page you visit in real time as felt, clay, carved wood, paint, or whatever material you choose. - [How to Create a Custom AI Model with Fine-Tuning](https://jessewaites.com/blog/post/how-to-create-a-custom-ai-model-with-fine-tuning.md): A start-to-finish walkthrough of fine-tuning an open-weight model on home-lab GPUs: baseline evals, synthetic data, QLoRA, quantization, and serving. - [Building WGHTLFT: A Rails + SwiftUI Weightlifting Tracker](https://jessewaites.com/blog/post/building-wghtlft-a-rails-swiftui-weightlifting-tracker.md): How WGHTLFT pairs a Rails 8 API with a native SwiftUI iOS app for lifting, programs, 3D equipment visualization, Apple Watch, and Siri shortcuts. - [What Happens When Your App Prototype Goes Viral On The Internet](https://jessewaites.com/blog/post/what-happens-when-your-app-prototype-goes-viral-on-the-internet.md): A prototype I built went viral. Here's what happened next... - [Comments Are A Very Underrated AI Coding Tool](https://jessewaites.com/blog/post/comments-are-the-ultimate-agent-coding-hack.md): When you’re coding with agents, the most reliable steering wheel is a well-placed comment in the code’s line of sight. - [Why I Choose Ruby on Rails in the AI Coding Era](https://jessewaites.com/blog/post/why-i-choose-ruby-on-rails-in-the-ai-coding-era.md): The AI coding era has changed the calculus in ways that are only starting to become clear, and Rails benefits from those changes more than almost any other framework. Convention over configuration turns out to be exactly what a language model needs. - [Introducing Agent Gateway for Ruby on Rails](https://jessewaites.com/blog/post/introducing-agent-gateway-for-ruby-on-rails.md): A small Rails engine gem that gives AI agents structured, read-only access to the data you choose to expose. - [Why Does AI Sometimes Give Inconsistent Answers?](https://jessewaites.com/blog/post/why-does-ai-sometimes-give-inconsistent-answers.md): AI doesn't work like a calculator. It predicts words based on patterns, not fixed rules. Learn why answers can vary and why you should always verify against the original source material. - [AI Agent Orchestration on Rails](https://jessewaites.com/blog/post/ai-agent-orchestration-on-rails.md): Build a multi-agent AI platform where specialized agents use real tools to perform real tasks, all orchestrated on Rails. - [RAG on Ruby on Rails](https://jessewaites.com/blog/post/rag-on-rails.md): Build a powerhouse Retrieval-Augmented Generation (RAG) system with Ruby On Rails - [Introducing the Strftime Roulette Rubygem](https://jessewaites.com/blog/post/introducing-the-strftime-roulette-rubygem.md): I'm releasing strftime_roulette, a Ruby gem that adds a strftime_roulette method to Date and Time objects. Every call returns a randomly formatted string. That's it. That's the gem. - [The Inference Pattern: Tracking AI Usage with Polymorphic Models in Rails](https://jessewaites.com/blog/post/tracking-ai-usage-in-ruby-on-rails-apps-with-polymorphism.md) - [Injecting dynamic Spotify data into my AI Voice Assistant](https://jessewaites.com/blog/post/injecting-spotify-data-into-gemini-ai-voice-agent.md): How I built a real-time voice agent using Gemini 2.0 and injected dynamic Spotify API data into its context window. - [Building macOS apps with Apple AI: A guide to integrating Apple Intelligence with macOS](https://jessewaites.com/blog/post/building-macos-apps-with-apple-ai-apple-intelligence.md): What I learned building an app that interfaces with Apple's Foundation Models AI. - [Debugging custom Bridge Components in Hotwire Native](https://jessewaites.com/blog/post/debugging-custom-bridge-components-in-hotwire-native.md): I’ve been building a Hotwire Native iOS app with a Rails backend and recently created a custom bridge component called ApproachMapBridgeComponent. The goal was simple: when users click a button in the web view, it should open a native map modal in the iOS app. But instead of a working feature, the button did absolutely... - [Liquid Glass Tab Bar for Hotwire Native Apps](https://jessewaites.com/blog/post/liquid-glass-tab-bar-for-hotwire-native-apps.md): I'm working on a Hotwire Native iOS app, and I wanted the app to have that slick new Liquid Glass tab bar, which means that is is completely transparent and the content flows under and below the bottom tab bar. Here's how I updated my existing tab bar to have the modern Liquid Glass UI... - [Beware of stringify_keys in Rails 8+!](https://jessewaites.com/blog/post/beware-of-stringify_keys-in-rails-8.md): Rails 8 introduced a subtle but significant change to the stringify_keys method in ActiveSupport. Previously, stringify_keys only converted symbol keys in a hash to strings, leaving other key types such as integers untouched. Starting with Rails 8, the method converts all keys to strings, including numeric and other non-symbol keys. While this change simplifies behavior... - [Domain Names For Sale](https://jessewaites.com/blog/post/domain-names-for-sale.md): If you ended up on this page, you are either reading my technical blog or have been forwarded here via a domain name that I own... - [Hire Ruby On Rails Developer in Boston](https://jessewaites.com/blog/post/hire-ruby-on-rails-developer-in-boston.md): As a professional Ruby on Rails developer based in Boston, I bring over a decade of professional experience building, scaling, and modernizing web and mobile applications. My work has consistently centered on solving complex technical challenges while keeping products elegant, maintainable, and fast. In my current role, I help lead the modernization of a mission-critical... - [Exploring the Builder-to-Proc Pattern in Ruby](https://jessewaites.com/blog/post/exploring-the-builder-to-proc-pattern-in-ruby.md): One of my favorite Ruby idioms is the Builder-to-Proc pattern. It takes advantage of Ruby’s ability to convert objects into callables through to_proc, letting you pass a class directly to map and have it act like a builder for each element. Imagine you are working with raw data from a third-party API in JSON or... - [How To Remove Empty Turbo Frame Space](https://jessewaites.com/blog/post/how-to-remove-empty-turbo-frame-space.md): I recently ran into an annoying layout quirk while building an ‘infinite-scroll' type interface. The page loads data lazily as you scroll through a long list of posts, which works beautifully when there is indeed data to display. But in the scenario where there are no posts, the empty Turbo Frame was still claiming space... - [Using UUIDs as primary keys in Rails apps](https://jessewaites.com/blog/post/using-uuids-as-primary-keys-in-rails-apps.md): If you are using UUIDs as primary keys in your Rails application, you may find it tedious to specify them in every single migration. Fortunately, Rails provides a clean way to set this configuration globally so that all new tables use UUIDs automatically. By adding a simple generator configuration to your config/application.rb, Rails will handle... - [I turned the Rails 8 release notes into a podcast with AI](https://jessewaites.com/blog/post/i-turned-the-rails-8-release-notes-into-a-podcast-with-ai.md): This weekend I explored NotebookLM, an AI-powered research assistant designed to work directly with your own materials. By uploading documents, PDFs, links, or videos, you can generate tailored outputs such as summaries, study guides, audio overviews, or even structured mind maps. To test it out, I chose the Rails 8 release notes, a resource that’s... - [How to Rate Limit Your Ruby On Rails Controllers](https://jessewaites.com/blog/post/how-to-rate-limit-your-ruby-on-rails-controllers.md): Rails 8 introduced a new rate_limit feature for controllers, which makes throttling requests much easier to implement and manage than that was back in the day. Instead of relying on middleware or third-party gems, you can now declare rate limits directly in your controllers and centralize how you respond when clients exceed them 🙂 A... - [Dubugging UI Hover States The Easy Way](https://jessewaites.com/blog/post/dubugging-ui-hover-states-the-easy-way.md): Inspecting hover-driven interfaces in DevTools can sometimes be very tricky. Many sites use JavaScript to control hover states, which means the usual “Force state > :hover” option doesn’t always work. The moment you move your mouse away, the element disappears, making it difficult to examine its structure or styles. A simple workaround is to briefly... - [Supporting Right-to-Left (RTL) Languages with Tailwind CSS](https://jessewaites.com/blog/post/supporting-right-to-left-rtl-languages-with-tailwind-css.md): Designing for global audiences means thinking beyond left-to-right (LTR) text. Many languages, such as Arabic and Hebrew, use right-to-left (RTL) writing. Supporting RTL is crucial if you want your app or site to feel natural to those users. The CSS direction property controls the direction of text, table layout, and even grid columns. By default, MDN recommends... - [Make non-nullable Rails migrations in the command line](https://jessewaites.com/blog/post/make-non-nullable-rails-migrations-in-the-command-line.md): Ruby On Rails developers often find themselves creating migrations with columns that need to be non-nullable, but the standard migration generator creates nullable columns by default. Instead of generating a migration and then manually editing the file to add null: false, you can specify this constraint right from the command line (thanks to this PR... - [Hotwire Native Developers rejoice: ‘Action Native Push' has been released](https://jessewaites.com/blog/post/hotwire-native-developers-rejoice-action-native-push-has-been-released.md): Today the team at Basecamp released Action Native Push. Action Native Push brings a much-needed boost to Hotwire Native developers by enabling seamless integration of push notifications directly from Rails. Previously, sending notifications involved complex infrastructure like Amazon SNS or Pinpoint, but this gem simplifies the process by connecting directly to Apple’s APNs and Google’s... - [Adding minor UI touches with Rails & Stimulus](https://jessewaites.com/blog/post/adding-minor-ui-touches-with-rails-stimulus.md): Recently, we ran into a usability issue in our app. When customers archived Widgets, the interface gave no indication that anything was happening until the process was fully complete. This caused confusion for our users, and in many cases they attempted to archive the same Widget more than once. Without any visual feedback... - [How to redact sensitive information from your Ruby on Rails application before sending it to an AI](https://jessewaites.com/blog/post/how-to-redact-sensitive-information-from-your-ruby-on-rails-application-before-sending-it-to-an-ai.md): Our friends over at thoughtbot have just released Top Secret. Top Secret is a Rubygem that redacts sensitive information from free text before that text gets sent off to an AI LLM for processing. For example: raw_text = "My SSN is 123-45-6789 and my name is Keyser Soze" filtered_text = TopSecret::Text.filter(raw_text) filtered_text.output # => "My... - [iOS Dev Tip: Save iOS Simulator Screenshots in your normal Screenshots folder](https://jessewaites.com/blog/post/ios-dev-tip-save-ios-simulator-screenshots-in-your-normal-screenshots-folder.md): If you are anything like me, you don't like screenshots cluttering your desktop. Unfortunately, the desktop is the default place to store screenshots in macOS, so this has to be changed. Our plan here is to create a screenshots folder on our Mac, then have macOS save screenshots there. Next up, we want to have... - [Supercharge Your Dev Workflow with Claude Code MCP Servers](https://jessewaites.com/blog/post/supercharge-your-dev-workflow-with-claude-code-mcp-servers.md): Model Context Protocol servers represent a significant leap forward in AI tooling. Rather than operating in isolation, Claude Code can now access your filesystem, control web browsers, analyze websites, and perform complex data processing tasks. This integration creates a seamless workflow where your AI assistant becomes an active participant in your development process rather than... - [Get notified when Claude Code finishes a task](https://jessewaites.com/blog/post/get-notified-when-claude-code-finishes-a-task.md): I've been using Claude Code lately, and I found myself wanting a simple way to know when Claude finished a task. Instead of watching the terminal, I figured a quick notification sound would do the trick. Luckily, Claude supports hooks, which are customizable actions that run when certain events occur. By editing the settings.local.json file... - [My first macOS App: Menubar Emoji Picker](https://jessewaites.com/blog/post/my-first-mac-app-menubar-emoji-picker.md): I have been unhappy with the UI of Apple's emoji selector on macOS for a long time, so in a moment of inspiration I built my own! Introducing QuackQuack!, the emoji selector that lives in your menubar! The concept is extremely simple: You click the duck in your menubar which exposes a small window with... - [A sample Claude.md file for Ruby on Rails apps](https://jessewaites.com/blog/post/a-sample-claude-md-file-for-ruby-on-rails-apps.md): Claude.md files are special Markdown files used by Claude Code, an AI-powered coding assistant by Anthropic. A Claude.md file serves as a "control panel" or "pre-flight briefing" for Claude, providing project-specific context and instructions to guide its behavior. Most projects that utilize claude code or other agentic AI tools use a version of this claude.md - [Enumerable#partition for fun & profit](https://jessewaites.com/blog/post/enumerablepartition-for-fun-profit.md): Ruby's Enumerable#partition method is one of those hidden gems that can dramatically simplify your Rails code. This method splits any enumerable collection into two arrays based on a block condition, returning both the elements that match the condition and those that don't in a single operation. Instead of filtering your data multiple times or writing... - [Free Signal Strength ViewComponent for Ruby On Rails](https://jessewaites.com/blog/post/free-signal-strength-viewcomponent-for-ruby-on-rails.md): Recently I had the need for a signal strength UI indicator in a ruby on rails app and I didn't see one anywhere so I had to make one from completely from scratch. In the spirit of giving back to the community, here is that code as a viewcomponent. It may need some tweaks to... - [Faster Ruby On Rails AI Development with Ollama](https://jessewaites.com/blog/post/faster-ruby-on-rails-ai-development-with-ollama.md): Building AI powered features into Ruby on Rails applications has become increasingly common, but the development process can quickly become expen$ive and cumbersome when you're constantly hitting external APIs during testing and iteration. Every debug session, feature experiment, and streaming test can rack up costs while you wait for network requests to complete. This is... - [Rails 8 Introduces Deprecated Associations](https://jessewaites.com/blog/post/rails-8-introduces-deprecated-associations.md): Ruby on Rails has quietly introduced one of the most practical features for maintaining large-scale applications: the ability to mark associations as deprecated. This seemingly simple addition addresses a common pain point that many Rails developers have faced when working with legacy codebases or evolving application architectures. Anyone who has worked on a mature Rails... - [How to block AI Bots from a Ruby on Rails Application](https://jessewaites.com/blog/post/how-to-block-ai-bots-from-a-ruby-on-rails-application.md): As AI models become increasingly sophisticated, many website owners such as myself are concerned about their awesome blog posts being scraped and used to train AI systems without permission. If you're running a Ruby on Rails application and want to prevent AI bots from crawling your site, implementing proper bot blocking measures is essential. The... - [ApplicationRecord vs ActiveRecord::Base](https://jessewaites.com/blog/post/applicationrecord-vs-activerecordbase.md): Recently,. there was a discussion amongst my colleagues about why some of the models in our Rails 8 app inherit from ApplicationRecord while others inherit from ActiveRecord::Base. Lets dig in to these subtle but important distinctions, shall we? ApplicationRecord is a class that inherits from ActiveRecord::Base and serves as the base class for your applications... - [Communicate across Stimulus controllers with Stimulus Outlets](https://jessewaites.com/blog/post/communicate-across-stimulus-controllers-with-stimulus-outlets.md): Outlets represent one of Stimulus's most sophisticated tools for enabling seamless communication between javascript controller instances. Rather than relying on cumbersome event dispatching or global state management, Outlets provide a clean, declarative way to establish connections between different controllers using familiar CSS style selectors. (That is a bit of an oversimplification, TBH, but that is... - [Hire Ruby on Rails Hotwire Developer](https://jessewaites.com/blog/post/hire-ruby-on-rails-hotwire-developer.md): If you are looking to hire a ruby on rails developer that specializes in the ‘Hotwire' ecosystem of Turbo, Stimulus, and View Components, do drop me a line so we can have a chat. - [Use halted_callback_hook for better Rails debugging](https://jessewaites.com/blog/post/use-halted_callback_hook-for-better-rails-debugging.md): Rails applications are full of callbacks that control the flow of your models' lifecycle events. Whether it's before_save, before_create, or any other callback, these hooks are essential for maintaining data integrity and business logic. But what happens when something goes wrong and your callbacks start throwing :abort? That's where Rails' lesser-known halted_callback_hook comes to the... - [Product Questions to Ask Before Building a New Feature in Ruby on Rails](https://jessewaites.com/blog/post/product-questions-to-ask-before-building-a-new-feature-in-ruby-on-rails.md): As Ruby on Rails developers, it can be tempting to dive straight into building as soon as a feature request appears. But taking a moment to ask the right questions before writing any code can save time, reduce complexity, and lead to much better results. Being intentional at the start of the process helps ensure... - [How to use Ruby On Rails with Generative AI](https://jessewaites.com/blog/post/how-to-use-ruby-on-rails-with-generative-ai.md): People are starting to figure out that modern Rails, specifically Hotwire and Turbo Streams, is the perfect choice for building web and mobile apps that integrate with AI models. Thanks to the hotwire tools, integrating generative AI into your Ruby on Rails application has never been easier—or more powerful. With tools like Ollama, Rails' built-in... - [Hotwire Native Developer For Hire](https://jessewaites.com/blog/post/hotwire-native-developer-for-hire.md): Want to hire a Hotwire Native Developer to turn your Ruby On Rails app into an iOS or Android app? You've come to the right place. Get in touch! - [Why choose Hotwire Native?](https://jessewaites.com/blog/post/why-choose-hotwire-native.md): In an era where mobile applications are essential for business success, companies are facing a persistent challenge: the astronomical costs of mobile development. However, a technology called Hotwire Native is rapidly changing this landscape, offering businesses a way to create high-quality mobile applications at a fraction of the traditional cost. The traditional approach to mobile... - [render in-app iOS and Android devise forms natively with this neat hotwire native trick](https://jessewaites.com/blog/post/render-devise-forms-natively-with-this-one-neat-hotwire-native-trick.md): Hello Hotwire Weekly readers, It was an honor to be included in the most recent edition of Hotwire Weekly! If you love Rails and or Hotwire, please connect with me on LinkedIn here or on the bird app here. Recently I added the standard Devise authentication library to a Rails 8 hotwire app. However, I... - [How to Migrate Your Website from WordPress to Astro](https://jessewaites.com/blog/post/how-to-migrate-your-website-from-wordpress-to-astro.md): A complete guide to migrating from WordPress to Astro, including how to export your content using the WordPress REST API, write a migration script to convert posts to Markdown, and set up redirects to preserve your SEO. Learn the step-by-step process we used to successfully migrate from a legacy WordPress installation to a modern, lightning-fast Astro static site. - [rails + tailwind dark mode Stimulus Controller that persists across page loAds](https://jessewaites.com/blog/post/use-this-stimulus-controller-for-rails-tailwind-dark-mode.md): Recently I had reason to add dark mode to a Ruby on Rails 8 app. After a few iterations, I landed on the following implementation which I thought I would share. This implementation persists the dark mode setting across page loads using local storage, so it is pretty ideal for most applications. I am making... - [Introducing the Turboframe Highlighter](https://jessewaites.com/blog/post/turboframe-highlighter.md): It occurred to me today that when working in a Rails 7+ codebase, it might occasionally be helpful to see exactly where the turboframes are on any given web page, since turboframes are invisible to the human eye. This highlighting would be a great option to have in development where only we can see it,... - [How to make Rails 7+ recognize your new Stimulus Controllers](https://jessewaites.com/blog/post/how-to-make-rails-7-recognize-your-new-stimulus-controllers.md): If you are reading this blog post, chances are that a search engine brought you here. You probably created a new stimulus controller for your Rails 7+ app, the system is not recognizing this new file, and you are searching the web for ideas on what might have went wrong. I recently went through the... - [Introducing the Boston Ipsum Rubygem](https://jessewaites.com/blog/post/introducing-the-boston-ipsum-rubygem.md): What is a RubyGem? (This blog post is a port over from a blog post on my now decommissioned previous website) A Rubygem is a bit of code that a ruby developer wrote, made available in a portable format and posted to a public server, so that bit of code can be used on other...