Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
61271cb
chore: bootstrapped demo Expo app
artus9033 Jan 15, 2026
0282537
chore: use expo config plugin in expo demo app
artus9033 Jan 15, 2026
a9dbb08
chore: reset Expo project
artus9033 Jan 16, 2026
9c92eaa
chore: use workspace specifier for monorepo deps
artus9033 Jan 16, 2026
4a5702a
fix: do not toss up source sets in Gradle plugin
artus9033 Jan 16, 2026
4893be4
feat: base implementation for brownfield Expo config plugin
artus9033 Jan 22, 2026
a65a9f1
chore: update lock files
artus9033 Jan 22, 2026
6aba560
chore: update app.json in ExpoApp
artus9033 Jan 22, 2026
f30f055
chore: enable debug logging in app.json in ExpoApp
artus9033 Jan 22, 2026
594aaf5
feat: use new logging system in the plugin
artus9033 Jan 22, 2026
9e0ba69
feat: templates engine for project modifications
artus9033 Jan 22, 2026
a5840e9
feat: patch for Expo SDK pre v55, fix source file paths
artus9033 Jan 23, 2026
b544e47
feat: implemented Android brownfield plugin
artus9033 Jan 23, 2026
af69bca
chore: update ExpoApp scripts
artus9033 Jan 23, 2026
2afa209
fix: dedent gradle script insertion
artus9033 Jan 23, 2026
64eb48d
fix: depend on Material in AndroidApp; fix typo in gradle scripting c…
artus9033 Jan 23, 2026
23e4c8e
fix: package name in ExpoApp
artus9033 Jan 23, 2026
95b580c
chore: use debug signing config for AndroidApp release variant - for …
artus9033 Jan 23, 2026
a066b02
chore: missing indent in gradleHelpers insertion
artus9033 Jan 23, 2026
0f34957
fix: add missing expo modifications to template build.gradle.kts
artus9033 Jan 23, 2026
0a9c3ca
chore: use the Expo classes in template ReactNativeHostManager.kt
artus9033 Jan 23, 2026
080a124
fix: iOS xcode project processing of target UUID
artus9033 Jan 23, 2026
834d850
fix: make Android Expo config explicitly specify versions of RN Andro…
artus9033 Jan 23, 2026
a4c0913
fix: running package:ios again
thymikee Jan 23, 2026
ccf8f48
chore: udpate rock to 0.12.8
thymikee Jan 23, 2026
4bf29e7
chore: make nodemon watch template files in dev script for brownfield…
artus9033 Jan 23, 2026
ac7abeb
chore: reformat files, extract capitalized string helper, suppress un…
artus9033 Jan 30, 2026
d9050d5
chore: deintegrate isExpo gradle plugin prop in favor of auto-detection
artus9033 Jan 30, 2026
c2648c7
chore: typo in Android native demo app theme name
artus9033 Jan 30, 2026
4a59b38
feat: config Maven publishing for part of the core expo modules
artus9033 Jan 31, 2026
74b0d80
fix: correct artifact, group and version discovery for manually white…
artus9033 Jan 31, 2026
7d9f2f7
feat: inject transitive dependencies into POM publication files
artus9033 Feb 2, 2026
619eb2b
feat: instead of publishing, inject proper POM and Gradle Module JSON…
artus9033 Feb 2, 2026
1d36921
feat: functional Expo demo in AndroidApp
artus9033 Feb 3, 2026
310a7b2
chore: re-enable signing of gradle plugin
artus9033 Feb 3, 2026
1867458
chore: use 0.0.1-snapshot by default in Expo plugin on Android
artus9033 Feb 3, 2026
09c0dce
fix: filter out remaining expo transitive dependencies, add version m…
artus9033 Feb 11, 2026
2ce1d5b
feat: seamless integration of Expo features into the brownfield CLI
artus9033 Feb 12, 2026
1985835
refactor: restructure RNApp sources
artus9033 Feb 12, 2026
a64e2fe
feat: reuse RNApp sources in ExpoApp
artus9033 Feb 12, 2026
adf3ea3
feat: set up flavors for AndroidApp to consume expo or vanilla artifacts
artus9033 Feb 12, 2026
957b5ff
ci: update CI to account for AndroidApp flavors
artus9033 Feb 12, 2026
9390219
chore: remove obsolete comment
artus9033 Feb 12, 2026
7bbc2d1
fix: monorepo-prone expo detection in CLI
artus9033 Feb 12, 2026
e214f81
feat: proper code sharing for RN demo apps
artus9033 Feb 12, 2026
c52ce57
fix: make ReactNativeHostManager singatures match across flavors, pro…
artus9033 Feb 12, 2026
4456f06
fix: restore .brownie.ts files in each project for codegen to work pr…
artus9033 Feb 12, 2026
f0adf90
feat: added an image view to the demo app
artus9033 Feb 12, 2026
341f535
chore: strip obsolete comment
artus9033 Feb 12, 2026
580b19c
fix: proper module name in ios script
artus9033 Feb 12, 2026
5a21b7c
fix: brownie not to crash on Android
artus9033 Feb 12, 2026
afad19d
fix: handle brownie no stores in project in the CLI
artus9033 Feb 12, 2026
b6ba4b7
feat: demo apps reorganized, pulled in clean template for expo app
artus9033 Feb 12, 2026
69b6497
feat: integrate brownie store with Expo demo app
artus9033 Feb 12, 2026
470be26
docs: update docs
artus9033 Feb 12, 2026
a4cd611
Merge branch 'main' into feat/expo-config-plugin
artus9033 Feb 12, 2026
7c3b790
feat: temporarily deintegrate brownie from expo demo before android i…
artus9033 Feb 12, 2026
48fd6e1
Merge branch 'main' into feat/expo-config-plugin
artus9033 Feb 12, 2026
2b1680c
chore: rename expo app project
artus9033 Feb 12, 2026
6058678
chore: re-enable signing of the gradle plugin
artus9033 Feb 12, 2026
77726ee
chore: add changesets
artus9033 Feb 12, 2026
6f7cb58
refactor: format files
artus9033 Feb 12, 2026
9a274d1
fix(ci): path to RN project in androidapp-road-test
artus9033 Feb 12, 2026
e08a74c
refactor: format files to comply with detekt
artus9033 Feb 12, 2026
0f6d0b6
chore: revert changes to brownie
artus9033 Feb 12, 2026
27fb93c
fix: paths in packageIos in RN projects
artus9033 Feb 12, 2026
d867bb3
ci: update workflow for Apple apps
artus9033 Feb 12, 2026
24db114
feat: demo iOS app supporting interchanging brownfield artifacts
artus9033 Feb 12, 2026
0989c60
fix: patchExpoPre55.sh
artus9033 Feb 12, 2026
f4a44b8
fix: reorder build phases in iOS to first run patching after expo con…
artus9033 Feb 13, 2026
54fa5fc
wip: reorder build script phases PoC for Expo config plugin
artus9033 Feb 13, 2026
6d86267
chore: reorder code properly
artus9033 Feb 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@callstack/brownfield-example-android-app",
"@callstack/brownfield-example-ios-app",
"@callstack/brownfield-example-rn-app",
"@callstack/brownfield-example-expo-app",
"@callstack/react-native-brownfield-tester-integrated",
"@callstack/brownfield-gradle-plugin-react"
],
Expand Down
5 changes: 5 additions & 0 deletions .changeset/deep-garlics-sit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@callstack/brownfield-cli': major
---

feat: support for CNG with new Expo config plugin
5 changes: 5 additions & 0 deletions .changeset/tasty-apes-retire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@callstack/react-native-brownfield': major
---

feat: add Expo config plugin
63 changes: 63 additions & 0 deletions .github/actions/androidapp-road-test/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Android road test (selected RN app & AndroidApp)
description: Package the given RN app as AAR, publish to Maven Local, and build the corresponding AndroidApp flavor

inputs:
flavor:
description: 'AndroidApp flavor to build (expo or vanilla)'
required: true

rn-project-path:
description: 'Path to the RN project to build'
required: true

rn-project-maven-path:
description: 'Maven path to the RN project, e.g. com/rnapp/brownfieldlib'
required: true

runs:
using: composite
steps:
- name: Setup
uses: ./.github/actions/setup

- name: Prepare Android environment
uses: ./.github/actions/prepare-android

- name: Restore Gradle cache
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-android-androidapp-${{ inputs.flavor }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-android-androidapp-${{ inputs.flavor }}-gradle-
${{ runner.os }}-android-androidapp-gradle-

# == RN app ==

- name: Package AAR with the Brownfield CLI
run: |
cd ${{ inputs.rn-project-path }}
yarn run brownfield:package:android
shell: bash

- name: Publish AAR artifact to Maven Local
run: |
cd ${{ inputs.rn-project-path }}
yarn run brownfield:publish:android
shell: bash

- name: Verify debug AAR exists in Maven Local
run: stat ~/.m2/repository/${{ inputs.rn-project-maven-path }}/0.0.1-SNAPSHOT/brownfieldlib-0.0.1-SNAPSHOT-debug.aar
shell: bash

- name: Verify release AAR exists in Maven Local
run: stat ~/.m2/repository/${{ inputs.rn-project-maven-path }}/0.0.1-SNAPSHOT/brownfieldlib-0.0.1-SNAPSHOT-release.aar
shell: bash

# == AndroidApp ==

- name: Build native Android Brownfield app
run: yarn run build:example:android-consumer:${{ inputs.flavor }}
shell: bash
85 changes: 85 additions & 0 deletions .github/actions/appleapp-road-test/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: Apple road test (selected RN app & AppleApp)
description: Package the given RN app as XCFramework, and build the corresponding AppleApp variant

inputs:
variant:
description: 'AppleApp yarn command variant to run (expo or vanilla)'
required: true

rn-project-path:
description: 'Path to the RN project to build'
required: true

runs:
using: composite
env:
USE_CCACHE: 1
CCACHE_DIR: ${{ github.workspace }}/.ios_ccache
CCACHE_BASEDIR: ${{ github.workspace }}
CCACHE_COMPRESS: '1'
steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6

- name: Setup
uses: ./.github/actions/setup

- name: Prepare iOS environment
uses: ./.github/actions/prepare-ios

- name: Install ccache
run: brew install ccache

- name: Enable ccache
run: echo "$(brew --prefix)/opt/ccache/libexec" >> $GITHUB_PATH

- name: Restore RNApp & AppleApp ccache
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5
with:
path: |
.ios_ccache
key: ${{ runner.os }}-rnapp-appleapp-${{ inputs.variant }}-ios-ccache-${{ hashFiles(format('{0}/ios/Podfile.lock', inputs.rn-project-path), format('{0}/ios/*.xcodeproj/project.pbxproj', inputs.rn-project-path), 'apps/AppleApp/Brownfield Apple App.xcodeproj/project.pbxproj') }}
restore-keys: |
${{ runner.os }}-rnapp-appleapp-${{ inputs.variant }}-ios-ccache-

# == RN app ==

- name: Restore Pods cache (RN ${{ inputs.variant }} app)
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5
with:
path: |
${{ inputs.rn-project-path }}/ios/Pods
key: ${{ runner.os }}-rnapp-${{ inputs.variant }}-ios-pods-${{ hashFiles(format('{0}/ios/Podfile.lock', inputs.rn-project-path)) }}
restore-keys: |
${{ runner.os }}-rnapp-${{ inputs.variant }}-ios-pods-

- name: Install pods (RN ${{ inputs.variant }} app)
run: |
cd ${{ inputs.rn-project-path }}/ios
pod install

- name: Restore DerivedData cache (RN ${{ inputs.variant }} app)
uses: actions/cache@v5
with:
path: ${{ inputs.rn-project-path }}/ios/build
key: ${{ runner.os }}-ios-rnapp-${{ inputs.variant }}-derived-data-${{ hashFiles(format('{0}/ios/Podfile.lock', inputs.rn-project-path), format('{0}/ios/*.xcodeproj/project.pbxproj', inputs.rn-project-path)) }}
restore-keys: |
${{ runner.os }}-ios-rnapp-${{ inputs.variant }}-derived-data-

- name: Package iOS framework with the Brownfield CLI
run: |
cd ${{ inputs.rn-project-path }}
yarn run brownfield:package:ios

# == AppleApp ==

- name: Build Brownfield iOS native app (${{ inputs.variant }})
run: |
yarn run build:example:ios-consumer:${{ inputs.variant }}

# ==============

- name: Log ccache stats
uses: ./.github/actions/ccache-summary
with:
name: RN ${{ inputs.variant }} app & AppleApp
139 changes: 39 additions & 100 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,61 +83,44 @@ jobs:
- name: Build integrated Android tester app
run: yarn run build:tester-integrated:android

android-rnapp-androidapp:
name: Android road test (RNApp & AndroidApp)
android-androidapp-expo:
name: Android road test (RNApp & AndroidApp - Expo)
runs-on: ubuntu-latest
needs: build-lint

steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6

- name: Setup
uses: ./.github/actions/setup

- name: Prepare Android environment
uses: ./.github/actions/prepare-android

- name: Restore Gradle cache
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5
- name: Run RNApp -> AndroidApp road test (Expo)
uses: ./.github/actions/androidapp-road-test
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-android-rnapp-androidapp-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-android-rnapp-androidapp-gradle-

# == RNApp ==

- name: Package AAR with the Brownfield CLI
run: |
cd apps/RNApp
yarn run brownfield:package:android

- name: Publish AAR artifact to Maven Local
run: |
cd apps/RNApp
yarn run brownfield:publish:android

- name: Verify debug AAR exists in Maven Local
run: stat ~/.m2/repository/com/rnapp/brownfieldlib/0.0.1-local/brownfieldlib-0.0.1-local-debug.aar
flavor: expo
rn-project-path: apps/ExpoApp
rn-project-maven-path: com/expoapp/brownfieldlib

- name: Verify release AAR exists in Maven Local
run: stat ~/.m2/repository/com/rnapp/brownfieldlib/0.0.1-local/brownfieldlib-0.0.1-local-release.aar
android-androidapp-vanilla:
name: Android road test (RNApp & AndroidApp - Vanilla)
runs-on: ubuntu-latest
needs: build-lint

# == AndroidApp ==
steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6

- name: Build native Android Brownfield app
run: |
yarn run build:example:android-consumer
- name: Run RNApp -> AndroidApp road test (Vanilla)
uses: ./.github/actions/androidapp-road-test
with:
flavor: vanilla
rn-project-path: apps/RNApp
rn-project-maven-path: com/rnapp/brownfieldlib

ios-tester-integrated:
name: iOS road test (TesterIntegrated)
runs-on: macos-26
needs: build-lint

env: &ios_env
env:
USE_CCACHE: 1
CCACHE_DIR: ${{ github.workspace }}/.ios_ccache
CCACHE_BASEDIR: ${{ github.workspace }}
Expand Down Expand Up @@ -203,76 +186,32 @@ jobs:
with:
name: TesterIntegrated

ios-rnapp-appleapp:
name: iOS road test (RNApp & AppleApp)
runs-on: macos-26
ios-appleapp-vanilla:
name: iOS road test (RNApp & AppleApp - Vanilla)
runs-on: ubuntu-latest
needs: build-lint

env: *ios_env

steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6

- name: Setup
uses: ./.github/actions/setup

- name: Prepare iOS environment
uses: ./.github/actions/prepare-ios

- name: Install ccache
run: brew install ccache

- name: Enable ccache
run: echo "$(brew --prefix)/opt/ccache/libexec" >> $GITHUB_PATH

- name: Restore RNApp & AppleApp ccache
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5
with:
path: |
.ios_ccache
key: ${{ runner.os }}-rnapp-appleapp-ios-ccache-${{ hashFiles('apps/RNApp/ios/Podfile.lock', 'apps/RNApp/ios/RNApp.xcodeproj/project.pbxproj', 'apps/AppleApp/Brownfield Apple App.xcodeproj/project.pbxproj') }}
restore-keys: |
${{ runner.os }}-rnapp-appleapp-ios-ccache-

# == RNApp ==

- name: Restore Pods cache (RNApp)
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5
with:
path: |
apps/RNApp/ios/Pods
key: ${{ runner.os }}-rnapp-ios-pods-${{ hashFiles('apps/RNApp/ios/Podfile.lock') }}
restore-keys: |
${{ runner.os }}-rnapp-ios-pods-

- name: Install pods (RNApp)
run: |
cd apps/RNApp/ios
pod install

- name: Restore DerivedData cache (RNApp)
uses: actions/cache@v5
- name: Run RNApp -> AppleApp road test (Vanilla)
uses: ./.github/actions/appleapp-road-test
with:
path: apps/RNApp/ios/build
key: ${{ runner.os }}-ios-rnapp-derived-data-${{ hashFiles('apps/RNApp/ios/Podfile.lock', 'apps/RNApp/ios/RNApp.xcodeproj/project.pbxproj') }}
restore-keys: |
${{ runner.os }}-ios-rnapp-derived-data-
variant: vanilla
rn-project-path: apps/RNApp

- name: Package iOS framework with the Brownfield CLI
run: |
cd apps/RNApp
yarn run brownfield:package:ios

# == AppleApp ==

- name: Build Brownfield iOS native app
run: |
yarn run build:example:ios-consumer
ios-appleapp-expo:
name: iOS road test (RNApp & AppleApp - Expo)
runs-on: ubuntu-latest
needs: build-lint

# ==============
steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6

- name: Log ccache stats
uses: ./.github/actions/ccache-summary
- name: Run RNApp -> AppleApp road test (Expo)
uses: ./.github/actions/appleapp-road-test
with:
name: RNApp & AppleApp
variant: expo
rn-project-path: apps/RNApp
16 changes: 9 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
Run `yarn` in the root of the repository to install all dependencies.

Depending on your needs, you may need to install CocoaPods in a subset of the below directories:

- example React Native iOS app: `cd apps/RNApp/ios && pod install`
- integrated iOS tester app: `cd apps/TesterIntegrated/swift && pod install`

Expand All @@ -18,17 +19,18 @@ We use [changesets](https://github.com/changesets/changesets) to make it easier

## Scripts

- `lint` - runs linting on all JS/TS source files in the monorepo *[Turbo]*
- `lint` - runs linting on all JS/TS source files in the monorepo _[Turbo]_
- `gradle-plugin:lint` - runs linting on the Brownfield Gradle plugin source code
- `typecheck` - runs TypeScript type checking on all TS source files in the monorepo *[Turbo]*
- `build` - runs all `build*` tasks in the Turbo repo - see below for more details *[Turbo]*
- `typecheck` - runs TypeScript type checking on all TS source files in the monorepo _[Turbo]_
- `build` - runs all `build*` tasks in the Turbo repo - see below for more details _[Turbo]_
- `dev` - runs all `dev` tasks in all workspaces
- `brownfield:plugin:publish:local` - publishes the Brownfield Gradle plugin to your local Maven repository for testing purposes
- `build:brownfield` - builds the React Native Brownfield package (`packages/react-native-brownfield`) *[Turbo]*
- `build:docs` - builds the documentation site (`docs/`) *[Turbo]*
- `build:brownfield` - builds the React Native Brownfield package (`packages/react-native-brownfield`) _[Turbo]_
- `build:docs` - builds the documentation site (`docs/`) _[Turbo]_
- `build:tester-integrated:android` - builds the Android integrated tester app (`apps/TesterIntegrated/android`)
- `build:tester-integrated:ios` - builds the iOS integrated tester app (`apps/TesterIntegrated/swift`)
- `build:example:android-rn` - builds the example React Native app for Android (`apps/RNApp/android`)
- `build:example:ios-rn` - builds the example React Native app for iOS (`apps/RNApp/ios`)
- `build:example:android-consumer` - builds the example native Android consumer app (`apps/AndroidApp`)
- `build:example:ios-consumer` - builds the example native Apple consumer app (`apps/AppleApp`)
- `build:example:android-consumer:expo` - builds the example native Android consumer (`apps/AndroidApp`) app's flavor consuming the Expo RN app (`apps/ExpoApp`) artifact
- - `build:example:android-consumer:vanilla` - builds the example native Android consumer (`apps/AndroidApp`) app's flavor consuming the vanilla RN app (`apps/RNApp`) artifact
- `build:example:ios-consumer` - builds the example native Apple consumer app (`apps/AppleApp`)
Loading
Loading