DEV Community

Magne
Magne

Posted on

Solito 5 is now web-first (but still unifies NextJS and React Native)

What is Solito?

"Navigation is the hardest piece of sharing code across platforms. Web has plain URLs for navigation state, whereas apps have complex sets of nested navigation patterns (stacks, tabs, modals, drawers). By combining the approaches into a single mental model and API, devs can build for Web and Mobile with ease. This is touched on at length in the "Methodology" and "Gradual Adoption" sections of the Solito docs.

The gap between web devs and native devs is shrinking. This stack enables you to ship native apps and websites with a single codebase. I'm the only frontend engineer at our startup, and I was able to do just that as we scaled to thousands of users (see https://beatgig.com). My goal with Solito is to 1) provide the code to let others do it, and 2) perhaps more importantly, document clear patterns to deal with platform differences.
"

-- fernandorojo @ Hacker News

With the launch of Solito v5, it drops the direct dependency on React Native for Web.

See Fernando's tweet of the release of Solito v5:

That prompts some questions...

Why use Solito on web with pure NextJS, if Solito is precisely for cross-platform development?

Grok AI’s answer to:

> What is the utility of using Solito on web with pure NextJS? Couldn’t you just not use Solito? Isn’t Solito precisely for using React Native stuff on web (and vice versa)?

—-

Background context:

  • Solito 5 introduces a web-first approach by dropping the react-native-web dependency, allowing seamless integration into any Next.js app without configuration while maintaining unchanged native functionality for iOS and Android.
  • Major updates include support for Next.js 16 and Expo SDK 54, a shift to .native.tsx files for platform-specific code, and fixes like useSearchParams() on native, simplifying monorepo setups as shown in the updated starter template.
  • Originally launched in 2022 by Fernando Rojo to enable shared navigation patterns across web and mobile, this release builds on prior iterations like Zeego, addressing bundler complexities and enabling broader adoption in production cross-platform projects.

—-

The answer:

Let’s dive into the utility of using Solito on the web with pure Next.js, especially given its roots in React Native integration, and clarify how it fits into a web-only context as of today, October 22, 2025.

Background on Solito

Solito was originally created by Fernando Rojo to bridge the gap between React Native and Next.js, enabling developers to share navigation and UI logic across web and mobile platforms. It leverages React Navigation for native apps and Next.js Router for the web, providing a unified API to manage navigation patterns (e.g., stacks, tabs, modals) that differ between the two environments. Its initial design was heavily tied to React Native, often requiring react-native-web to render React Native components on the web.

Solito 5 and the Web-First Shift

With the release of Solito 5 (announced on October 21, 2025, via the target post), a significant evolution has occurred. Solito 5 drops the react-native-web dependency from its core components, making it web-first. This means it now operates as a pure Next.js solution on the web, with platform-specific code (e.g., native features) isolated to .native.tsx files. This shift simplifies the setup for web-only projects while retaining compatibility with React Native for those who need it.

Utility of Solito on Web with Pure Next.js

Even in a web-only Next.js context, Solito offers several practical benefits:

  1. Unified Navigation Patterns:

    • Solito provides a consistent navigation API inspired by React Navigation, which can be more intuitive for developers familiar with mobile patterns. This is particularly useful if your team works across web and mobile or if you plan to extend to native later. For example, Solito’s <Link> component can serve as a drop-in replacement for Next.js’s <Link>, offering a unified experience that aligns with its cross-platform philosophy.
    • It handles complex navigation scenarios (e.g., modals, stacked screens) that go beyond Next.js’s flat, page-based routing, giving you more flexibility to mimic native-like navigation on the web.
  2. Future-Proofing and Scalability:

    • If you’re building a web app today but anticipate adding React Native support later, starting with Solito minimizes refactoring. Since Solito 5 is designed to work without react-native-web on the web, you can adopt it now and seamlessly extend to native by adding .native.tsx files and dependencies like Expo when needed.
    • The release notes highlight its compatibility with Next.js 16 and Expo SDK 54, ensuring it stays current with modern frameworks, which is a boon for long-term projects.
  3. Simplified Monorepo Setup:

    • Solito 5 includes an updated Expo 54 starter monorepo, which, while aimed at cross-platform devs, also streamlines code organization for web-focused teams. Even if you ignore the native parts, the monorepo structure can help manage shared logic (e.g., components, hooks) across different parts of a large Next.js app.
  4. Enhanced Developer Experience:

    • Solito’s web-first approach reduces bundler complexity (e.g., no more index.web.tsx files), which can lead to faster build times and fewer configuration headaches, even in a pure Next.js setup.
    • The migration guide and breaking changes (e.g., dropping TextLink defaults) encourage clean, explicit styling and props, promoting better code maintainability—a win for any web project.
  5. Community and Ecosystem Alignment:

    • Since Solito is backed by Fernando Rojo and has a growing community (evidenced by the positive reactions in the thread), it integrates well with other libraries like @expo/router or Tailwind, as seen with Zeego’s compatibility. This makes it a robust choice for web devs looking to leverage a battle-tested tool.

Isn’t Solito for React Native Stuff?

You’re right to question this—Solito’s origins are indeed tied to React Native. Historically, its primary value was enabling React Native developers to share code with Next.js apps, using react-native-web to render native components on the web. However, Solito 5 redefines its scope. By dropping react-native-web as a dependency, it’s no longer reliant on React Native rendering on the web. Instead, it positions itself as a versatile framework that:

  • Works standalone on Next.js for web apps.
  • Remains compatible with React Native for native apps, but only if you opt into that ecosystem.

This dual nature means Solito isn’t just for React Native anymore—it’s a tool for unifying development workflows, whether you stay web-only or expand to mobile. The web-first design ensures it doesn’t force React Native paradigms (like View or Text components) onto your Next.js app unless you choose to.

Practical Example

Imagine you’re building a Next.js e-commerce site. With Solito 5, you could use its <Link> component for navigation, benefiting from its ability to handle modal overlays (e.g., a cart popup) in a way that feels native-like. If your business later decides to launch an iOS app, you can extend the same navigation logic to React Native with minimal changes, leveraging Solito’s .native.tsx files. Without Solito, you’d need to rewrite navigation for mobile, potentially duplicating effort.

Caveats

  • Overhead for Web-Only: If you’re strictly web-focused and happy with Next.js’s built-in routing, Solito might add unnecessary complexity. Its value shines when you need advanced navigation or plan for cross-platform growth.
  • Learning Curve: The shift to web-first requires understanding its new conventions (e.g., no default styles on TextLink), as outlined in the migration guide.
  • Dependency: While react-native-web is dropped, some third-party React Native libraries you might use alongside Solito could still require it, so check your stack.

Conclusion

Using Solito on the web with pure Next.js is about leveraging a unified, future-proof navigation system that aligns with modern cross-platform trends, even if you start web-only. It’s not just for React Native anymore—it’s a strategic choice for developers who value flexibility, scalability, and a consistent API across potential future expansions. If your project is unlikely to go native and you’re satisfied with Next.js’s default routing, you might not need it. But for anyone eyeing a hybrid future or craving more navigation power, Solito 5’s web-first approach makes it a compelling tool.

—-

> Can you use web stuff on native by using solito?

Your question seems to be asking whether you can use web-specific features or components on the native (React Native) side by using Solito, or perhaps vice versa—using native features on the web. Based on the context of Solito 5 (released on October 21, 2025, as per the target post) and the ongoing discussion, I’ll interpret this as: Can Solito enable the use of web-specific ("web stuff") functionality or components in a native React Native environment, or allow native features to work on the web? Let’s break this down step by step, considering the current state of Solito 5 as of 04:06 PM CEST on Wednesday, October 22, 2025.

Solito 5 Overview

Solito 5, as introduced by Fernando Rojo, is now a web-first framework that drops the react-native-web dependency from its core components. This means it operates natively on Next.js for the web without relying on React Native rendering, while still supporting React Native for iOS and Android via platform-specific files (e.g., .native.tsx). The goal is to simplify cross-platform development by allowing shared logic and navigation, with clear separation between web and native implementations.

Can You Use Web Stuff on Native with Solito?

The short answer is no, not directly, but let’s explore why and how you can approach this.

Why Not Directly?

  • Platform Separation: Solito 5 enforces a clear distinction between web and native. Web-specific features (e.g., Next.js Server Components, useSearchParams(), or browser APIs like window) are designed to work in a Next.js environment, which relies on a DOM. React Native, however, uses a different rendering engine (e.g., Yoga for layout, native UI components) and lacks a DOM, making web-specific APIs incompatible without additional layers like react-native-web.
  • Dropped react-native-web: Previously, Solito relied on react-native-web to render React Native components on the web. With Solito 5 dropping this dependency, the web side no longer uses React Native’s rendering pipeline. Conversely, the native side doesn’t inherit web capabilities unless explicitly bridged.
  • File-Based Isolation: Solito 5 uses file extensions like .native.tsx for platform-specific code. Web-specific logic (e.g., in .web.tsx or default .tsx files) is ignored on native, and native-specific code is ignored on web. This prevents direct use of web "stuff" (e.g., Next.js hooks or components) on native.

Workarounds to Use Web-Like Features on Native

While you can’t use web-specific APIs or components directly on native, Solito’s design allows you to share logic and abstract functionality in a way that mimics web behavior on native where possible:

  1. Shared Utility Logic:

    • Write platform-agnostic code (e.g., in a shared .ts or .tsx file) that adapts to the environment using runtime checks. For example:
     import { Platform } from 'react-native';
    
     const getParam = (key: string) => {
       if (Platform.OS === 'web') {
         return new URLSearchParams(window.location.search).get(key);
       }
       // Fallback for native (e.g., use React Navigation params)
       return null;
     };
    
  • This allows you to simulate web-like behavior (e.g., query params) on native, though you’d need to implement native equivalents (e.g., via React Navigation’s route params).
  1. Custom Components with Conditional Rendering:

    • Create a shared component that uses conditional logic to render web-specific JSX on the web and native-compatible alternatives on mobile. For instance:
     import { Platform } from 'react-native';
    
     const MyLink = ({ href, children }) => {
       if (Platform.OS === 'web') {
         return <a href={href}>{children}</a>; // Web-specific
       }
       return <Text onPress={() => {/* native navigation */}}>{children}</Text>; // Native equivalent
     };
    
  • Solito’s navigation API (e.g., <Link> or <Stack.Screen>) can help unify this, but you’d need to handle platform-specific navigation logic.
  1. Leveraging Expo or Third-Party Libraries:

    • Expo SDK 54 (supported by Solito 5) provides web-like features for React Native, such as Web APIs (e.g., localStorage via expo-secure-store analogs). You could use these to approximate web functionality on native, though they’re not identical to browser-native implementations.
  2. Monorepo Shared Code:

    • In a Solito monorepo, you can place web-specific code in a web/ directory and native-specific code in a native/ directory. Use a shared layer (e.g., shared/) to export utilities or components that adapt to both platforms, reducing the need to duplicate effort.

Limitations

  • Incompatible APIs: Web-only features like Server-Side Rendering (SSR) with Next.js or browser events (e.g., onWheel) won’t work on native without significant polyfills or workarounds, which may not be worth the effort.
  • Performance: Emulating web behavior on native can introduce overhead or inconsistent UX, as native apps are optimized for touch/gesture interactions rather than mouse/keyboard events.
  • Complexity: Adding web-like functionality to native requires careful abstraction, which might negate some of Solito’s simplification benefits.

Can You Use Native Stuff on Web with Solito?

The reverse—using native "stuff" (e.g., React Native components like View, Text, or native modules) on the web—is also not directly supported in Solito 5 due to the dropped react-native-web dependency. However:

  • Historical Context: Earlier Solito versions relied on react-native-web to render native components on the web, allowing you to use View, Text, etc., with some styling adjustments. Solito 5 removes this, so native components no longer render on the web by default.
  • Workaround: You could reintroduce react-native-web as a project dependency and configure it manually, but this contradicts Solito 5’s web-first philosophy and adds complexity. Alternatively, use a library like react-native-web-lite or rewrite native components as HTML/CSS equivalents for the web.

Solito’s Intended Use

Solito 5 is designed to unify development experience and navigation logic across web and native, not to make web and native environments interchangeable. The utility lies in:

  • Sharing code (e.g., business logic, styles, navigation structure) between platforms.
  • Allowing a smooth transition from web-only to cross-platform with minimal refactoring.
  • Providing a consistent API (e.g., <Link>, <Stack>) that abstracts platform differences.

If your goal is to use web-specific features on native or vice versa, Solito facilitates this indirectly through shared abstractions rather than direct feature porting.

Practical Example

Suppose you want to use Next.js’s useSearchParams() on native:

  • On web, it works out of the box with Solito 5’s web-first setup.
  • On native, you’d need to replicate this with React Navigation’s route.params or Expo’s routing system. Solito’s monorepo structure lets you define a custom hook like:
  import { useRoute } from '@react-navigation/native';

  export const useCustomParams = () => {
    const route = useRoute();
    return route.params || {};
  };
Enter fullscreen mode Exit fullscreen mode
  • Use this hook in both web and native contexts, with web falling back to useSearchParams() via a conditional import.

Conclusion

With Solito 5, you cannot directly use web "stuff" (e.g., Next.js APIs, DOM features) on native or native "stuff" (e.g., React Native components) on web without additional configuration or polyfills, as it prioritizes platform separation over feature unification.

The answer:

However, you can share logic and create platform-adapted implementations using Solito’s file-based structure and navigation API. This makes it ideal for projects where you want to start web-only with Next.js and later add native support, rather than forcing web-native interoperability.

Top comments (1)

Collapse
 
redbar0n profile image
Magne

> but Expo allows some HTML components now doesn’t it?

You’ve raised an excellent point! Let’s explore whether Expo allows the use of HTML components in React Native apps, especially in the context of Solito 5 (released October 21, 2025), and how this might relate to your question about using "web stuff" on native with Solito. Given the current date and time—04:11 PM CEST on Wednesday, October 22, 2025—I’ll incorporate the latest developments based on available documentation and the X posts provided.

Expo and HTML Components: The Current State

Expo has indeed introduced capabilities that allow some level of HTML or web-like behavior in React Native apps, particularly with recent updates to its SDK (e.g., SDK 52 and later, with Solito 5 supporting Expo SDK 54). Let’s break this down:

Expo’s use dom Directive

  • Introduction: As noted in the Expo Documentation (e.g., Using React DOM in Expo native apps), Expo introduced the use dom directive starting with SDK 52. This allows developers to render React DOM components (e.g., <div>, <p>, <img>) within a native app by leveraging a novel approach to integrate web code.
  • How It Works: The use dom directive enables incremental migration of web components into a React Native app. DOM components are rendered as regular components within a native context, often using a WebView or similar mechanism to pass raw HTML. However, this is not a full DOM environment—web content is passed directly through (not wrapped in an iframe), and the behavior is experimental and flakey, with potential deprecation in future React versions.
  • Limitations:
    • Native primitives like <View>, <Image>, and <Text> are recommended over DOM elements for performance and consistency.
    • Web-specific APIs (e.g., window, browser events) are not natively supported unless polyfilled.
    • The system shares similarities with React Server Components but is not a complete replacement for web rendering.

Expo SDK 54 and Solito 5

  • The target post for Solito 5 mentions support for Expo SDK 54, which builds on these advancements. However, Solito 5’s web-first approach and the drop of react-native-web as a dependency suggest it prioritizes native compatibility without forcing web rendering on native.
  • The release notes (post 1980785627936543142) don’t explicitly mention use dom or HTML components, focusing instead on navigation, file structure changes (e.g., .native.tsx), and breaking changes like dropping TextLink defaults. This indicates Solito 5 is not designed to leverage Expo’s HTML capabilities directly.

WebView as a Fallback

  • Expo supports the WebView component (via expo-webview), allowing you to render HTML content within a native app. This is a traditional approach to embed web "stuff" (e.g., a webpage or custom HTML) on native, but it’s isolated from the React Native component tree and doesn’t integrate seamlessly with Solito’s navigation or shared logic.

Can You Use Web Stuff on Native with Solito Using Expo’s HTML Support?

Let’s connect this to your original question about using Solito to bring web stuff to native:

Direct Use with Solito 5

  • No Built-In Support: Solito 5 does not natively integrate Expo’s use dom or WebView to render HTML components on native. Its design focuses on sharing navigation and logic, with platform-specific files (e.g., .native.tsx) handling native implementations. The web-first shift means web logic (e.g., Next.js components) is isolated to the web, and native logic is isolated to React Native.
  • File Separation: As per the breaking changes (post 1980785627936543142), Solito 5 uses .native.tsx for native code, which won’t include web-specific HTML or DOM elements unless you manually bridge them.

Workarounds Using Expo’s Capabilities

You can leverage Expo’s HTML support alongside Solito, but it requires explicit integration:

  1. Using use dom with Solito:

    • You could experiment with the use dom directive in a Solito project by adding it to a shared component. For example:
     // shared/MyComponent.tsx
     /** @jsxImportSource react */
     export const MyComponent = () => {
       if (process.env.EXPO_USE_DOM) {
         return <div style={{ color: 'red' }}>Web Stuff!</div>;
       }
       return <Text style={{ color: 'red' }}>Native Stuff!</Text>;
     };
    
  • This requires enabling use dom in your Expo config and testing its behavior, but it’s not a core part of Solito’s workflow. The flakiness noted in Expo docs suggests caution.
  1. Embedding WebView:

    • Use expo-webview to render HTML within a Solito native screen:
     // app/native/screens/WebScreen.native.tsx
     import { WebView } from 'expo-webview';
     import { View } from 'react-native';
    
     export default function WebScreen() {
       return (
         <View style={{ flex: 1 }}>
           <WebView source={{ html: '<h1>Hello from Web!</h1>' }} />
         </View>
       );
     }
    
  • This isolates the web content and doesn’t integrate with Solito’s navigation API (e.g., <Link> or <Stack>), so you’d need custom bridging.
  1. Shared Logic with Conditional Fallbacks:

    • Abstract web and native rendering in a Solito component:
     import { Platform } from 'react-native';
     import { WebView } from 'expo-webview';
    
     export const HybridComponent = ({ htmlContent }) => {
       if (Platform.OS === 'web') {
         return <div dangerouslySetInnerHTML={{ __html: htmlContent }} />;
       }
       return <WebView source={{ html: htmlContent }} style={{ flex: 1 }} />;
     };
    
  • Use this in both web and native contexts within a Solito app, though performance and interactivity may differ.

Challenges

  • Inconsistency: Expo’s HTML support is not a full DOM implementation, so complex web features (e.g., CSS animations, JavaScript events) may not translate well to native.
  • Maintenance: Manually integrating use dom or WebView with Solito adds complexity, potentially conflicting with its goal of simplifying cross-platform development.
  • Solito’s Philosophy: The web-first shift in Solito 5 suggests a move away from forcing web rendering on native, aligning with Expo’s recommendation to use native primitives (View, Text) for optimal performance.

Comparison to Traditional React Native

Traditionally, React Native (and by extension Expo) does not support HTML or CSS natively, as noted in the FAQ from Expo Documentation: "React Native does not support HTML or CSS. Instead of using the DOM, React Native uses native components" (e.g., <View> instead of <div>). The use dom feature is an exception, but it’s an experimental bridge, not a replacement for native components.

Practical Implications with Solito 5

  • Web to Native: If you want to use web "stuff" (e.g., HTML components) on native with Solito, you’d need to rely on use dom or WebView outside Solito’s core framework. Solito facilitates sharing navigation and logic, but the rendering of HTML would be a separate implementation.
  • Native to Web: Conversely, Solito 5 drops react-native-web, so native components (e.g., View, Text) won’t render on the web unless you reintroduce that dependency, which isn’t recommended.

Conclusion

Yes, Expo now allows some HTML components via the use dom directive (SDK 52+) or WebView, but this is not a core feature of Solito 5. You can use these Expo capabilities alongside Solito to bring web-like behavior to native, but it requires manual integration and workarounds (e.g., conditional rendering, WebView embedding). Solito itself is designed to unify development experience and navigation, not to enable direct web-to-native or native-to-web component rendering. For optimal use, stick to native primitives on native and web standards on web, using Solito to bridge the logic gap.