Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"json.schemas": [
{
"fileMatch": ["**/package.json"],
"url": "https://oss.callstack.com/react-native-brownfield/package-json.schema.json"
}
]
}
10 changes: 3 additions & 7 deletions apps/ExpoApp54/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
"test": "jest --config jest.config.js",
"prebuild": "expo prebuild",
"brownfield:prepare:android:ci": "cd .. && node --experimental-strip-types --no-warnings ./scripts/prepare-android-build-gradle-for-ci.ts ExpoApp54",
"brownfield:package:android": "brownfield package:android --module-name brownfieldlib --variant release --verbose",
"brownfield:publish:android": "brownfield publish:android --module-name brownfieldlib --verbose",
"brownfield:package:ios": "brownfield package:ios --scheme BrownfieldLib --configuration Release --verbose",
"brownfield:package:android": "brownfield package:android --variant release",
"brownfield:publish:android": "brownfield publish:android",
"brownfield:package:ios": "brownfield package:ios --configuration Release",
"eas:stg": "EXPO_TOKEN=$EAS_TOKEN eas update --channel production --message 'testing 1st stg channel update' --platform android"
},
"dependencies": {
Expand Down Expand Up @@ -54,9 +54,5 @@
"jest-expo": "~54.0.16",
"react-test-renderer": "19.1.0",
"typescript": "~5.9.3"
},
"brownie": {
"kotlin": "./android/brownfieldlib/src/main/java/com/callstack/rnbrownfield/demo/expoapp54/Generated/",
"kotlinPackageName": "com.callstack.rnbrownfield.demo.expoapp54"
}
}
10 changes: 10 additions & 0 deletions apps/ExpoApp54/react-native-brownfield.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"$schema": "https://oss.callstack.com/react-native-brownfield/schema.json",
"moduleName": "brownfieldlib",
"scheme": "BrownfieldLib",
"verbose": true,
"brownie": {
"kotlin": "./android/brownfieldlib/src/main/java/com/callstack/rnbrownfield/demo/expoapp54/Generated/",
"kotlinPackageName": "com.callstack.rnbrownfield.demo.expoapp54"
}
}
18 changes: 12 additions & 6 deletions apps/ExpoApp55/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
"test": "jest --config jest.config.js",
"prebuild": "expo prebuild",
"brownfield:prepare:android:ci": "cd .. && node --experimental-strip-types --no-warnings ./scripts/prepare-android-build-gradle-for-ci.ts ExpoApp55",
"brownfield:package:android": "brownfield package:android --module-name brownfieldlib --variant release --verbose",
"brownfield:publish:android": "brownfield publish:android --module-name brownfieldlib --verbose",
"brownfield:package:ios": "brownfield package:ios --scheme BrownfieldLib --configuration Release --verbose",
"brownfield:package:android": "brownfield package:android --variant release",
"brownfield:publish:android": "brownfield publish:android",
"brownfield:package:ios": "brownfield package:ios --configuration Release",
"eas:stg": "EXPO_TOKEN=$EAS_TOKEN eas update --channel production --message 'testing 1st stg channel update' --platform ios --environment staging"
},
"dependencies": {
Expand Down Expand Up @@ -62,8 +62,14 @@
"typescript": "~5.9.2"
},
"private": true,
"brownie": {
"kotlin": "./android/brownfieldlib/src/main/java/com/callstack/rnbrownfield/demo/expoapp55/Generated/",
"kotlinPackageName": "com.callstack.rnbrownfield.demo.expoapp55"
"react-native-brownfield": {
"$schema": "../../packages/cli/schema.json",
"brownie": {
"kotlin": "./android/brownfieldlib/src/main/java/com/callstack/rnbrownfield/demo/expoapp55/Generated/",
"kotlinPackageName": "com.callstack.rnbrownfield.demo.expoapp55"
},
"moduleName": "brownfieldlib",
"scheme": "BrownfieldLib",
"verbose": true
}
}
6 changes: 3 additions & 3 deletions apps/RNApp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
"ios": "react-native run-ios",
"build:example:android-rn": "react-native build-android",
"build:example:ios-rn": "react-native build-ios",
"brownfield:package:android": "brownfield package:android --module-name :BrownfieldLib --variant release --verbose",
"brownfield:publish:android": "brownfield publish:android --module-name :BrownfieldLib --verbose",
"brownfield:package:ios": "brownfield package:ios --scheme BrownfieldLib --configuration Release --verbose",
"brownfield:package:android": "brownfield package:android --variant release",
"brownfield:publish:android": "brownfield publish:android",
"brownfield:package:ios": "brownfield package:ios --configuration Release",
"lint": "eslint .",
"start": "react-native start",
"test": "jest --config jest.config.js",
Expand Down
8 changes: 8 additions & 0 deletions apps/RNApp/react-native-brownfield.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* @type {import('@callstack/react-native-brownfield').BrownfieldConfig}
*/
module.exports = {
moduleName: ':BrownfieldLib',
scheme: 'BrownfieldLib',
verbose: true,
};
5 changes: 5 additions & 0 deletions docs/docs/docs/api-reference/_meta.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
[
{
"type": "file",
"name": "configuration",
"label": "Configuration files"
},
{
"type": "dir",
"name": "react-native-brownfield",
Expand Down
194 changes: 194 additions & 0 deletions docs/docs/docs/api-reference/configuration.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# Configuration files

The Brownfield CLI can load configuration from a file instead of repeating the same flags on every command.
That configuration covers both `@callstack/react-native-brownfield` and `@callstack/brownie` options.

Configuration keys use camelCase names that match CLI flags.
For example, `--module-name` becomes `moduleName`, `--build-folder` becomes `buildFolder`, and `--use-prebuilt-rn-core` becomes `usePrebuiltRnCore`.

## Choose one configuration source

The CLI supports exactly one configuration source per project:

- `react-native-brownfield.config.js`
- `react-native-brownfield.config.json`
- `package.json` under the `react-native-brownfield` key

Do not keep more than one of these at the same time.
If the CLI finds multiple sources, it throws an error instead of guessing which one should win.

When both a config value and a CLI flag are set for the same option, the CLI flag wins.
The CLI also validates the file against the published schema and logs warnings for unknown or invalid keys.

## JavaScript config file

If you prefer a JavaScript file, create `react-native-brownfield.config.js` and export a plain object with `module.exports`:

```js
/** @type {import('@callstack/react-native-brownfield').BrownfieldConfig} */
module.exports = {
moduleName: ':BrownfieldLib',
scheme: 'BrownfieldLib',
verbose: true,
brownie: {
kotlin:
'./android/BrownfieldLib/src/main/java/com/example/brownfield/Generated/',
kotlinPackageName: 'com.example.brownfield',
},
};
```

## JSON config file

If you want schema autocomplete and validation directly in the config file, use `react-native-brownfield.config.json`:

```json
{
"$schema": "https://oss.callstack.com/react-native-brownfield/schema.json",
"moduleName": "brownfieldlib",
"scheme": "BrownfieldLib",
"configuration": "Release",
"verbose": true,
"usePrebuiltRnCore": true,
"brownie": {
"kotlin": "./android/brownfieldlib/src/main/java/com/example/brownfield/Generated/",
"kotlinPackageName": "com.example.brownfield"
}
}
```

## package.json config

If you prefer to keep everything in `package.json`, place the configuration under `react-native-brownfield`:

```json
{
"name": "my-app",
"react-native-brownfield": {
"moduleName": ":BrownfieldLib",
"scheme": "BrownfieldLib",
"verbose": true,
"brownie": {
"kotlin": "./android/BrownfieldLib/src/main/java/com/example/brownfield/Generated/",
"kotlinPackageName": "com.example.brownfield"
}
}
}
```

## Configuration reference

All file-based options mirror CLI flags, but they use camelCase property names.

### Shared keys

| Key | Type | Description |
| --------- | --------- | --------------------------------------------------------------------- |
| `$schema` | `string` | JSON Schema URL used by editors for validation and autocomplete. |
| `verbose` | `boolean` | Enables verbose CLI logging. |
| `brownie` | `object` | Nested Brownie configuration used by `brownfield codegen`. See below. |

### Android keys

| Key | Type | Description |
| ------------ | -------- | -------------------------------------------------------------------- |
| `moduleName` | `string` | Android module name used for packaging and publishing AAR artifacts. |
| `variant` | `string` | Android build variant, for example `debug` or `freeRelease`. |

### iOS keys

| Key | Type | Description |
| -------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------- |
| `scheme` | `string` | Xcode scheme used for packaging. |
| `configuration` | `string` | Xcode build configuration, for example `Debug` or `Release`. |
| `target` | `string` | Explicit Xcode target name. |
| `destination` | `string[]` | One or more Xcode destinations, such as `simulator`, `device`, or full destination strings. |
| `buildFolder` | `string` | Custom build output directory. By default, Brownfield uses the `.brownfield/build` path inside the iOS project. |
| `archive` | `boolean` | Creates an archive build suitable for IPA export and distribution. |
| `extraParams` | `string[]` | Extra arguments passed to `xcodebuild`. |
| `exportExtraParams` | `string[]` | Extra arguments passed to the archive export step. |
| `exportOptionsPlist` | `string` | Export options plist filename used during archive export. |
| `installPods` | `boolean` | Controls automatic CocoaPods installation. Set `false` to match `--no-install-pods`. |
| `newArch` | `boolean` | Controls React Native new architecture support. Set `false` to match `--no-new-arch`. |
| `local` | `boolean` | Forces a local `xcodebuild` flow. |
| `usePrebuiltRnCore` | `boolean` | Controls whether iOS packaging uses React Native Apple prebuilts. Omit it to keep Brownfield's version-aware defaults. |

## Brownie configuration

The Brownie configuration lives inside the main Brownfield config under the `brownie` key.
This is the preferred format for Brownie code generation.

Currently supported Brownie keys are:

| Key | Type | Description |
| ------------------- | -------- | ----------------------------------------------------------------------- |
| `kotlin` | `string` | Directory where generated Kotlin Brownie store files should be written. |
| `kotlinPackageName` | `string` | Kotlin package name used in generated Brownie store files. |

Example inside `react-native-brownfield.config.json`:

```json
{
"$schema": "https://oss.callstack.com/react-native-brownfield/schema.json",
"brownie": {
"kotlin": "./android/BrownfieldLib/src/main/java/com/rnapp/brownfieldlib/Generated/",
"kotlinPackageName": "com.rnapp.brownfieldlib"
}
}
```

Only the Kotlin output is configurable.
Swift Brownie files are always generated to `node_modules/@callstack/brownie/ios/Generated/`.

## Migrating from legacy Brownie configuration

Legacy Brownie configuration used a top-level `brownie` block in `package.json`:

```json
{
"brownie": {
"kotlin": "./android/BrownfieldLib/src/main/java/com/rnapp/brownfieldlib/Generated/",
"kotlinPackageName": "com.rnapp.brownfieldlib"
}
}
```

The new format moves the same values under the main Brownfield config:

```json
{
"react-native-brownfield": {
"moduleName": ":BrownfieldLib",
"scheme": "BrownfieldLib",
"brownie": {
"kotlin": "./android/BrownfieldLib/src/main/java/com/rnapp/brownfieldlib/Generated/",
"kotlinPackageName": "com.rnapp.brownfieldlib"
}
}
}
```

You can also migrate to a standalone config file:

```json
{
"$schema": "https://oss.callstack.com/react-native-brownfield/schema.json",
"moduleName": ":BrownfieldLib",
"scheme": "BrownfieldLib",
"brownie": {
"kotlin": "./android/BrownfieldLib/src/main/java/com/rnapp/brownfieldlib/Generated/",
"kotlinPackageName": "com.rnapp.brownfieldlib"
}
}
```

Migration steps:

1. Pick one main Brownfield config source.
2. Move the legacy `package.json#brownie` values into the nested `brownie` object in that source.
3. Remove the old top-level `brownie` block from `package.json`.
4. Run `brownfield codegen` again.

Do not keep the legacy and new Brownie configuration at the same time.
If both are present, `brownfield codegen` throws an error.
If only the legacy format is present, the command still works for now, but it prints a migration warning.
6 changes: 5 additions & 1 deletion docs/docs/docs/cli/brownfield.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

The `brownfield` CLI provides utilities for building & packaging artifacts for brownfield projects that use the `@callstack/react-native-brownfield` library.

:::tip Configuration file
You can store supported `brownfield` CLI options in a project configuration file instead of passing the same flags on every command.
See [Configuration files](/docs/api-reference/configuration) for supported config sources and option names.
:::

## Usage

```bash
Expand Down Expand Up @@ -36,7 +41,6 @@ Available arguments:
| --no-install-pods | Skip automatic CocoaPods installation |
| --no-new-arch | Run React Native in legacy async architecture |
| --local | Force local build with xcodebuild |
| --verbose | Enable verbose logging |

The build directory will be placed in the `<iOS project folder>/.brownfield/build` folder by default and the build outputs (XCFrameworks) will be created in the `<iOS project folder>/.brownfield/package/build` folder:

Expand Down
5 changes: 5 additions & 0 deletions docs/docs/docs/cli/brownie.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

The `brownfield codegen` CLI command generates `@callstack/brownie` (Brownie) state management library native store types from TypeScript schema.

:::tip Configuration file
You can configure Brownie codegen from the main Brownfield config file by using the nested `brownie` object.
See [Configuration files](/docs/api-reference/configuration) for supported config sources and Brownie-specific settings.
:::

## Usage

```bash
Expand Down
29 changes: 23 additions & 6 deletions docs/docs/docs/getting-started/android.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -281,21 +281,38 @@ tasks.named("generateMetadataFileForMavenAarPublication") {
}
```

## 7. Create the AAR
## 7. Create a Brownfield Configuration

Create `react-native-brownfield.config.json` in your project root:

```json
{
"$schema": "https://oss.callstack.com/react-native-brownfield/schema.json",
"moduleName": "reactnativeapp",
"variant": "Release"
}
```

This lets the CLI reuse your packaging settings without repeating the same flags on every command.
See [Configuration files](/docs/api-reference/configuration) for JavaScript and `package.json` variants and the full list of supported options.

## 8. Create the AAR

Use the brownfield CLI to package your React Native app:

```bash
npx brownfield package:android --variant Release --module-name reactnativeapp
npx brownfield package:android
```

Then publish to **local Maven**:

```bash
npx brownfield publish:android --module-name reactnativeapp
npx brownfield publish:android
```

## 8. Add the AAR to Your Android App
If you prefer to keep the settings on the command line, you can still run `npx brownfield package:android --variant Release --module-name reactnativeapp` and `npx brownfield publish:android --module-name reactnativeapp` instead.

## 9. Add the AAR to Your Android App

Add **`mavenLocal()`** to your app's `settings.gradle.kts`:

Expand All @@ -315,7 +332,7 @@ dependencies {
}
```

## 9. Initialize React Native
## 10. Initialize React Native

In your **`MainActivity`**:

Expand All @@ -333,7 +350,7 @@ class MainActivity : AppCompatActivity() {
}
```

## 10. Show the React Native UI
## 11. Show the React Native UI

### Using Fragment

Expand Down
Loading