npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-brownfield-playground

v1.1.2

Published

Brownfield React Native SDK (RN 0.86+, New Architecture) — present/dismiss UI and session APIs for React Native, Android, and iOS hosts

Readme

react-native-brownfield-playground

Embed React Native screens into existing React Native, Android, and iOS apps. Your native UI stays native — RN opens only when you call present.

| | | |---|---| | Install | npm install react-native-brownfield-playground | | Setup | npx react-native-brownfield-playground init --android / --ios | | Screens | "welcome" · "profile" | | React Native | 0.86.2 (peers: react ^19.2.3, react-native ^0.86.0) | | New Architecture | Required |

Public APIs

| Action | React Native | Android (Kotlin) | iOS (Swift) | |--------|--------------|------------------|---------------| | Present UI | EasySdk.present('welcome') | EasySdk.present(activity, "welcome") | EasySdk.shared.present(...) | | Dismiss | EasySdk.dismiss() | EasySdk.dismiss() | EasySdk.shared.dismiss() | | Get session | await EasySdk.getSession() | EasySdk.getSession(ctx) | EasySdk.shared.getSession() | | Clear session | EasySdk.clearSession() | EasySdk.clearSession(ctx) | EasySdk.shared.clearSession() | | Logged in? | EasySdk.isLoggedIn() | EasySdk.isLoggedIn(ctx) | EasySdk.shared.isLoggedIn() |

Docs live on the npm package page (this README). After install you can also open:

node_modules/react-native-brownfield-playground/README.md

Contents

  1. Prerequisites
  2. Install
  3. React Native apps
  4. Native Android apps
  5. Native iOS apps
  6. Verify setup
  7. Breaking changes in 1.1.0
  8. Troubleshooting

What’s new in 1.1.2

  • Docs are npm-only (no private GitHub links); full guide lives in this README
  • SwiftUI host snippets: AppDelegate.SwiftUI.snippet, ContentView.SwiftUI.snippet
  • iOS troubleshooting: User Script Sandboxing / embed frameworks fix
  • Podspec sources the public npm tarball (not a private git repo)

What’s new in 1.1.1

  • init --android auto-fixes Android Studio gotchas: PREFER_SETTINGS, coreKtx = 1.16.0, root force(androidx.core), Java 17
  • New snippets: android-root-build.gradle*, android-libs.versions.toml.snippet
  • Docs/checklist for MavenRepo + AAR metadata (core:1.19.0) failures

Prerequisites

| Tool | Version | |------|---------| | Node.js | 20+ | | React | 19.2.3 | | React Native | 0.86.2 | | JDK | 17 (Android) | | Android minSdk | 24+ | | Xcode | 16+ recommended | | iOS deployment target | 15.1+ | | New Architecture | ON |


Install

From your app root (the folder that contains android/ and/or ios/):

npm init -y   # if needed
npm install [email protected] [email protected] react-native-brownfield-playground

Autolinking picks up android/ and EasySdk.podspec from the package. No manual linking.


React Native apps

npm install react-native-brownfield-playground [email protected] [email protected]
npx pod-install   # iOS only

Wrap the app once with <EasySdkProvider>, then call EasySdk.present(...):

import React from 'react';
import {Button, View} from 'react-native';
import {EasySdk, EasySdkProvider} from 'react-native-brownfield-playground';

export default function App() {
  return (
    <EasySdkProvider>
      <View style={{flex: 1, justifyContent: 'center', gap: 12, padding: 24}}>
        <Button
          title="Open Welcome"
          onPress={() =>
            EasySdk.present('welcome', {
              props: {userId: 'rn_user_001'},
              onResult: result => console.log(result),
            })
          }
        />
        <Button title="Open Profile" onPress={() => EasySdk.present('profile')} />
        <Button
          title="Log session"
          onPress={async () => console.log(await EasySdk.getSession())}
        />
        <Button title="Clear session" onPress={() => EasySdk.clearSession()} />
      </View>
    </EasySdkProvider>
  );
}

Native Android apps

Keep your existing Android UI. React Native screens open only via EasySdk.present.

Expected layout

YourNativeApp/                 ← run all npm commands here
├── android/                   ← your existing Android app
├── package.json
├── index.js                   ← Metro entry (registers EasySdkRoot)
├── metro.config.js
├── babel.config.js
├── react-native.config.js
└── node_modules/

Step 1 — Install + init

cd /path/to/YourNativeApp

npm init -y
npm install [email protected] [email protected] react-native-brownfield-playground

npx react-native-brownfield-playground init --android
npm install   # if init added dependencies
npx react-native-brownfield-playground doctor

init will (when files are found):

  1. Create JS host files (index.js, Metro/Babel configs) if missing
  2. Enable Hermes + New Architecture in gradle.properties
  3. Fix repositoriesModePREFER_SETTINGS (avoids MavenRepo / RN plugin failure)
  4. Patch settings.gradle / app/build.gradle for RN autolinking
  5. Force androidx.core 1.16.0 at root + pin coreKtx in Version Catalogs
  6. Set Java / Kotlin JVM target to 17
  7. Write EasyHostApplication.kt when no Application class is set, and wire it in the manifest
  8. Copy reference snippets to templates-generated/

Backups of patched files are saved as *.bak.

Android Studio checklist (verify after init)

| Item | Must be | |------|---------| | repositoriesMode | PREFER_SETTINGS | | coreKtx in libs.versions.toml | 1.16.0 (not 1.19.0) | | Root Gradle force(androidx.core…) | present | | compileSdk | 36 | | AGP | 8.x (do not upgrade to 9.1 for core 1.19) | | Java / jvmTarget | 17 | | newArchEnabled / hermesEnabled | true |

Snippets: templates/android-*.snippet (also copied to templates-generated/).

Step 2 — Application must expose reactHost

Your Application must implement ReactApplication and provide a New Architecture ReactHost:

class EasyHostApplication : Application(), ReactApplication {
  override val reactHost: ReactHost by lazy {
    getDefaultReactHost(
      context = applicationContext,
      packageList = PackageList(this).packages,
      jsMainModulePath = "index",
    )
  }

  override fun onCreate() {
    super.onCreate()
    loadReactNative(this)
  }
}

Point the manifest at it:

<application android:name=".EasyHostApplication" ...>

If you already have an Application class, merge the reactHost + loadReactNative pieces into it (see templates/EasyHostApplication.kt or templates-generated/ after init).

Step 3 — Call from your Activity

import com.demo.easysdk.EasySdk

EasySdk.present(this, "welcome", mapOf("userId" to "u1")) { status, payload ->
  val session = EasySdk.getSession(this)
}

EasySdk.present(this, "profile")
EasySdk.getSession(this)
EasySdk.clearSession(this)
EasySdk.isLoggedIn(this)

Full sample: examples/android-MainActivity.kt.

Step 4 — Run (debug)

# Terminal 1 — Metro must be running
npm start

# Terminal 2
adb reverse tcp:8081 tcp:8081   # physical device / some emulators
cd android && ./gradlew installDebug

Release (no Metro)

npx react-native bundle --platform android --dev false --entry-file index.js \
  --bundle-output android/app/src/main/assets/index.android.bundle \
  --assets-dest android/app/src/main/res

cd android && ./gradlew assembleRelease

Native iOS apps

Keep your existing native UI (UIKit or SwiftUI). React Native screens open only via EasySdk.shared.present.

Expected layout

YourNativeApp/
├── ios/                       ← your existing Xcode project
├── package.json
├── index.js
├── metro.config.js
├── babel.config.js
├── react-native.config.js
└── node_modules/

Step 1 — Install + init

cd /path/to/YourNativeApp

npm init -y
npm install [email protected] [email protected] react-native-brownfield-playground

npx react-native-brownfield-playground init --ios
npm install
cd ios && pod install
cd ..
npx react-native-brownfield-playground doctor

Always open ios/*.xcworkspace, not the .xcodeproj.

Step 2 — Bind EasySdk (pick your app style)

A) SwiftUI host (Xcode “App” template — @main on *App.swift)

This is the common new Xcode template. Do not paste the UIKit @main AppDelegate as-is (two @main entries will fail).

  1. Use templates/AppDelegate.SwiftUI.snippet (no @main, no UIWindow).
  2. Attach it from your App:
@main
struct HostIOSApp: App {
  @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

  var body: some Scene {
    WindowGroup { ContentView() }
  }
}
  1. Call present from SwiftUI by resolving a UIViewController (see templates/ContentView.SwiftUI.snippet):
EasySdk.shared.present(from: topViewController(), screen: "welcome", props: ["userId": "ios_user"]) { _, _ in }

B) UIKit host (AppDelegate is @main)

Use templates/AppDelegate.swift.snippet: create RCTReactNativeFactory, call EasySdk.shared.bind(factory:), keep a native root VC.

EasySdk.shared.bind(factory: factory) // once in AppDelegate
EasySdk.shared.present(from: self, screen: "welcome", props: ["userId": "ios_user"]) { status, payload in }
EasySdk.shared.present(from: self, screen: "profile")

ObjC alternative: templates/AppDelegate.mm.snippet.
Breaking vs 1.0.x: do not pass RCTBridge into present.

Step 3 — Run (debug)

# Terminal 1
npm start

# Terminal 2
open ios/*.xcworkspace
# Product → Run (Simulator is easiest for Metro/localhost)

Release (no Metro)

npx react-native bundle --platform ios --dev false --entry-file index.js \
  --bundle-output ios/main.jsbundle --assets-dest ios

Ensure release bundleURL points at that file (see AppDelegate snippet).


Verify setup

npx react-native-brownfield-playground doctor

Breaking changes in 1.1.0

| Old (≤1.0.x) | New (1.1.0) | |--------------|-------------| | ReactInstanceManager / legacy root view | ReactHost + ReactDelegate | | iOS present(..., bridge: RCTBridge, ...) | EasySdk.shared.bind(factory:) then present(...) | | RN 0.76 / React 18 | RN 0.86.2 / React 19.2.3 | | Optional New Arch | New Arch required |


Troubleshooting

| Problem | Fix | |---------|-----| | Red screen / Metro HTTP 500 | Start Metro from the app root; ensure index.js has require('react-native-brownfield-playground') | | reactHost is null | Implement ReactApplication.reactHost with getDefaultReactHost | | EasySdk.bind / present crash on iOS | Call EasySdk.shared.bind(factory:) in AppDelegate before any present | | Blank RN screen | Metro not reachable — npm start + adb reverse tcp:8081 tcp:8081 | | MavenRepo was added by plugin 'com.facebook.react' | In android/settings.gradle(.kts) change FAIL_ON_PROJECT_REPOSPREFER_SETTINGS | | AAR metadata: androidx.core:core:1.19.0 needs compileSdk 37 / AGP 9.1 | Do not jump to AGP 9. Set coreKtx = "1.16.0" in android/gradle/libs.versions.toml, and force("androidx.core:core:1.16.0") in the root build.gradle(.kts). Soft constraints alone lose to a Version Catalog pin. Re-run init --android. | | Java 11 compile / desugar issues | Set Java / Kotlin jvmTarget to 17 | | Autolink / Gradle errors | Re-run init --android, compare with templates/android-*.snippet | | Pods missing EasySdk | cd ios && pod install, open .xcworkspace | | iOS [CP] Embed Pods Frameworks / rsync Operation not permitted | In Xcode → Build Settings set User Script Sandboxing (ENABLE_USER_SCRIPT_SANDBOXING) to No, then Clean Build Folder | | Two @main / missing ViewController on SwiftUI app | Use AppDelegate.SwiftUI.snippet + @UIApplicationDelegateAdaptor (do not use UIKit @main AppDelegate as-is) | | Old RCTBridge samples | Those are legacy — use ≥1.1.2 New Arch templates |


License

MIT