Skip to content
Tech News
← Back to articles

Building a framework-agnostic Ruby gem (and making sure it doesn't break)

read original get Ruby on Rails Testing Kit → more articles
Why This Matters

This article highlights the importance of creating a framework-agnostic Ruby gem that seamlessly supports multiple front-end frameworks like ERB, React, and Vue. By focusing on HTML-based signal elements and maintaining consistent APIs tailored to each framework’s conventions, developers can ensure a scalable and maintainable integration that prevents regressions across updates. This approach benefits both the tech industry and consumers by enabling flexible, reliable, and user-friendly interfaces.

Key Takeaways

Ruby Native needs to work with ERB, React, and Vue. That’s three frameworks, three sets of conventions, and three ways developers expect an API to feel. And every new feature needs to ship across all of them without breaking the others.

This week I added a native navbar, and it was the first real test of whether this approach scales. Here’s what I’ve learned about keeping an API clean across frameworks, and how I’m catching regressions.

It’s HTML all the way down

When I started Ruby Native, it was ERB-only. The tab bar, push notifications, and forms all used the same pattern: render a hidden HTML element with data-native-* attributes. The native app detects these “signal elements” via a MutationObserver and translates them into real native UI.

For example, the native navbar is just this:

<div data-native-navbar="Account" hidden> <div data-native-button data-native-icon="ellipsis.circle"> <div data-native-menu-item data-native-title="Edit profile" data-native-href="/account/edit" data-native-icon="pencil"> </div> <div data-native-menu-item data-native-title="Sign out" data-native-click="#sign-out" data-native-icon="rectangle.portrait"> </div> </div> </div>

Hidden divs, that’s it! The native app doesn’t know what generated them. It just reads the DOM.

This turned out to be the most important decision in the entire project. Because when it came time to support React and Vue, I didn’t have to change anything on the native side. I just needed new ways to produce the same HTML.

Each framework’s API should feel good

ERB developers expect blocks and builders. React developers expect components and props. If you force one framework’s patterns onto another, the API feels wrong even if it works.

... continue reading