Advanced Mode (BETA)

Advanced Mode replaces web navigation with native screen transitions. Pages push and pop with the same animations users expect from any native app, complete with a native navigation bar, back button, and swipe-to-go-back gesture. It builds on Normal Mode, so everything you already have keeps working.

Please note that Advanced Mode is currently in BETA. There might be some rough edges or bugs and the API might change. If you run into any issues then please email joe.

#What you get

  • Native screen transitions with push/pop animations and swipe-to-go-back
  • Native navigation bar with a system back button on every pushed screen
  • All Normal Mode signal helpers keep working unchanged, from tabs and navbar buttons to toasts, menus, and the floating action button

Going Advanced means hiding your web navbar and letting the native navigation bar handle those actions instead.

#Setup

Set your app mode to advanced in config/ruby_native.yml:

app:
  mode: advanced

Hide your web navbar for native users so the native navigation bar takes over:

<%= render "navbar" unless native_app? %>

That's it. No additional JavaScript dependencies, no Stimulus setup, no separate imports. The same native_* helpers you use in Normal Mode drive both the web and native experiences.

One requirement: every page must load Turbo. Advanced Mode drives native navigation with it, so a page that doesn't load turbo.js shows a configuration error instead of rendering. A stock Rails app with turbo-rails installed is already covered; just make sure no layout or page opts out.

#Clear the native navigation bar

The native navigation bar in Advanced Mode is translucent, so once you hide your web navbar your page content scrolls underneath it. Add the native-inset-top class to the element that should start below the bar, usually your main content wrapper:

<main class="native-inset-top">
  <%= yield %>
</main>

The class ships in the gem stylesheet, so make sure your layout includes it:

<%= stylesheet_link_tag :ruby_native %>

The inset is exactly the height of the system area above your content, so you never guess a value. On iOS it resolves to env(safe-area-inset-top), which spans the status bar and the navigation bar together, so one class clears both. On Android, where the WebView doesn't populate env(safe-area-inset-*) from system bars, the native shell measures the real bar height and feeds it in, so you get the same result without any per-device tweaking.

Two companion classes cover the rest of the screen:

  • native-inset-bottom clears the home indicator or gesture bar at the bottom.
  • native-inset clears both the top and bottom at once.

#Helpers

Advanced Mode uses the same signal helpers as Normal Mode. See the individual guides for the full API:

#Migrating from Normal to Advanced

If your app already uses Normal Mode, flipping to Advanced is a two-line change:

  1. Set mode: advanced in your config/ruby_native.yml (see setup above).
  2. Hide your web navbar with native_app? so the native navigation bar takes over.

That's it. Every native_* helper you're already using — tabs, navbar, buttons, menus, submit buttons, badges, haptics — keeps working identically in Advanced Mode. The difference is that new pages now push onto a native navigation stack instead of loading in place.