rnbrand
v0.4.0
Published
RNBrand — production-ready CLI for React Native white-label branding, icons, splash, Firebase, and builds
Maintainers
Readme
RNBrand
White-label branding CLI for React Native — update app name, package / bundle IDs, versions, icons, and full-screen splash screens from one config file.
npm install --save-dev rnbrand
npx rnbrand init && npx rnbrand doctor && npx rnbrand applySafety: Always commit (or back up) before
apply. Local rollback is best-effort — Git is your source of truth. See Best practices.
Table of contents
- Features
- Why RNBrand?
- Requirements
- Installation
- Quick start
- Basic example
- Configuration
- Commands
- Plugins
- Assets
- Platform limitations
- Best practices
- Troubleshooting
- FAQ
- Architecture
- Contributing
- License
Features
| Feature | What it does |
|---------|----------------|
| Selective apply | Only keys present in rnforge.config.json are changed |
| App identity | Display name, Android applicationId, iOS bundle ID |
| Versioning | Shared or per-platform version / build numbers |
| Icons | Generate Android mipmaps + iOS AppIcon from one source |
| Splash | Full-screen portrait cover → responsive Android + iOS assets |
| Doctor | Read-only health check before you touch native files |
| Backup / rollback | Snapshot under .rnforge-backup/ + restore command |
| Build helpers | Clean / run Android & iOS after branding |
| Fonts | Custom .ttf/.otf → Android assets + iOS UIAppFonts (separate command) |
Shipped commands: init · apply · fonts · doctor · build · rollback / revert · version
Shipped plugins: app-name · package · version · icon · splash · firebase
Planned: switch (multi-brand)
Why RNBrand?
Manual white-label work means editing strings.xml, Info.plist, Gradle, Xcode assets, and splash storyboards by hand — easy to miss a density or break launch screens.
RNBrand gives you:
- One config for the fields you care about
- Validation (
doctor+ apply-time checks) before writes - Dry-run to preview changes
- Rollback when something goes wrong (plus Git as the real safety net)
| Approach | Selective updates | Asset generation | Health check | Rollback |
|----------|-------------------|------------------|--------------|----------|
| Hand-edit native files | Manual | Manual | None | Git only |
| Ad-hoc scripts | Varies | Varies | Rare | Rare |
| RNBrand | Config keys only | Icon + splash | doctor | Built-in + Git |
Requirements
| | Minimum |
|--|---------|
| Node.js | 18+ |
| Project | React Native app root (android/ + ios/ + package.json) |
| iOS builds | macOS + Xcode (rnbrand build ios) |
Installation
npm install --save-dev rnbrand
npx rnbrand --helpYarn / pnpm:
yarn add -D rnbrand
# or
pnpm add -D rnbrand# From a path to this repo
npm install --save-dev /absolute/path/to/modules/rnforge
# or
npm install --save-dev file:../modules/rnforge
# Global link
cd /path/to/modules/rnforge && npm link
cd /path/to/your-rn-app && npm link rnbrand
rnbrand versionNote: The npm package is
rnbrand. The config file is still namedrnforge.config.json(and backups live in.rnforge-backup/).
Quick start
Run these from your React Native project root.
# 1. Commit first
git add -A && git commit -m "chore: before rnbrand"
# 2. Scaffold config + branding folders
npx rnbrand init
# 3. Drop in assets
# branding/icon.png — square ≥ 1024×1024
# branding/splash.png — portrait ≥ 1080×1920 (recommended 1242×2688)
# 4. Validate
npx rnbrand doctor
# 5. Preview, then apply
npx rnbrand apply --dry-run
npx rnbrand apply
# 6. Build
npx rnbrand build android --clean
# npx rnbrand build ios --cleanIf branding went wrong:
npx rnbrand rollback --yes
# or: git restore .Basic example
rnforge.config.json (project root):
{
"appName": "Shopping App",
"packageName": "com.company.shopping",
"bundleIdentifier": "com.company.shopping",
"version": "1.0.0",
"buildNumber": 1,
"icon": "./branding/icon.png",
"splash": {
"image": "./branding/splash.png",
"fullScreen": true
}
}npx rnbrand doctor
npx rnbrand apply --dry-run
npx rnbrand apply --yesSelective update (only change what you include):
{
"appName": "Rajhans Admin",
"version": "1.0.0"
}{
"icon": "./branding/icon.png"
}Missing keys are left untouched in the native project.
Configuration
File: rnforge.config.json in the React Native project root.
Field reference
| Field | Type | Plugin | Notes |
|-------|------|--------|-------|
| appName | string | app-name | 2–50 chars; no < > or control characters |
| packageName | string | package | Android applicationId (e.g. com.company.app) |
| bundleIdentifier | string | package | iOS bundle ID |
| version | string | version | e.g. 1.0.0 |
| buildNumber | number | version | Positive integer |
| android | object | version | Optional { version, versionCode } |
| ios | object | version | Optional { version, buildNumber } |
| icon | string | icon | Path to source icon |
| splash | string | object | splash | Path or { image, fullScreen } |
| plugins.enabled | string[] | — | Restrict which plugins run |
| firebase | object | firebase | { android?, ios?, services?, auth.providers?, androidGradle? } — platforms, modules, auth methods, optional Gradle version overrides |
| fonts | string | string[] | object | fonts command | Path / files for custom fonts — not applied by rnbrand apply |
Splash
| | Spec | |--|------| | Mode | Full-screen cover only — centered logos are not supported | | Recommended | 1242×2688 px portrait | | Minimum | 1080×1920 px, height ≥ width | | Formats | PNG / JPEG / WebP | | Tip | Keep important art centered — cover-fit may crop edges |
String form (always full-screen cover):
{
"splash": "./branding/splash.png"
}Object form:
{
"splash": {
"image": "./branding/splash.png",
"fullScreen": true
}
}Per-platform versions
{
"version": "1.0.0",
"buildNumber": 1,
"android": { "version": "1.2.0", "versionCode": 12 },
"ios": { "version": "1.2.1", "buildNumber": 8 }
}Restrict plugins
{
"appName": "Rajhans Admin",
"icon": "./branding/icon.png",
"plugins": { "enabled": ["app-name"] }
}With plugins.enabled set, only listed plugins run (even if other keys exist).
Re-init
npx rnbrand init reads an existing rnforge.config.json for prompt defaults. Use --force to overwrite the file.
Commands
Overview
| Command | Description |
|---------|-------------|
| npx rnbrand init | Create rnforge.config.json, branding/, brands/ |
| npx rnbrand doctor | Read-only health check (exit 1 on failure) |
| npx rnbrand apply | Apply branding for keys present in config |
| npx rnbrand fonts | Apply custom fonts (Android + iOS) — not part of apply |
| npx rnbrand build android\|ios | Build / run after branding |
| npx rnbrand rollback | Restore latest backup (revert alias) |
| npx rnbrand rollback --list | List backups under .rnforge-backup/ |
| npx rnbrand rollback --id <id> | Restore a specific backup |
| npx rnbrand version | Print CLI version |
Global flags
| Flag | Behavior |
|------|----------|
| -y, --yes | Non-interactive (skip prompts) |
| --dry-run | Preview only — no writes |
| -v, --verbose | Detailed logs |
| --cwd <path> | Project root (default: process.cwd()) |
| -V, --version | Package version |
| -h, --help | Help |
npx rnbrand apply --yes
npx rnbrand apply --dry-run
npx rnbrand apply --verbose
npx rnbrand apply --cwd /path/to/appinit
npx rnbrand init
npx rnbrand init --force
npx rnbrand init --cwd /path/to/appdoctor
npx rnbrand doctor
npx rnbrand doctor --verboseChecks include: Node ≥18, RN root, config validity, apply plan, icon/splash assets & sizes, Android/iOS targets, iOS launch wiring, backups, git cleanliness, stale Android build folders.
apply
npx rnbrand apply
npx rnbrand apply --dry-run
npx rnbrand apply --yes
npx rnbrand apply --skip-backup # not recommendedCreates a snapshot under .rnforge-backup/ before writing (unless --skip-backup).
fonts in config is ignored by apply — use rnbrand fonts.
fonts
Custom fonts are intentionally separate from branding apply.
# Put .ttf / .otf under branding/fonts, then:
npx rnbrand fonts
npx rnbrand fonts --path ./branding/fonts
npx rnbrand fonts --android-only
npx rnbrand fonts --ios-only
npx rnbrand fonts --dry-runConfig (optional if you pass --path):
{
"fonts": "./branding/fonts"
}Or:
{
"fonts": {
"path": "./branding/fonts",
"android": true,
"ios": true
}
}What it does
| Step | Detail |
|------|--------|
| Shared | Ensure react-native.config.js → assets: ['./branding/fonts'] |
| Android | Copy fonts → android/app/src/main/assets/fonts/ |
| iOS | Copy into app folder, Info.plist → UIAppFonts, register in pbxproj |
Rebuild the app after fonts (hot reload is not enough). Use the font’s PostScript / file name in fontFamily.
build
npx rnbrand build android
npx rnbrand build android --clean
npx rnbrand build android --release --no-install
npx rnbrand build ios --clean
npx rnbrand build ios --release --no-install
npx rnbrand build android --dry-run| Flag | Behavior |
|------|----------|
| (default) | npx react-native run-android / run-ios |
| --clean | Android: gradlew clean + remove build / .cxx. iOS: remove ios/build + pod install |
| --release | Android: assembleRelease. iOS: Release xcodebuild |
| --no-install | Build artifacts only (skip run-*) |
| --dry-run | Print commands only |
rollback / revert
npx rnbrand rollback --list
npx rnbrand rollback --yes
npx rnbrand rollback --id 2026-07-10T07-52-35-819Z --yesRestores backed-up files and deletes folders created during that apply (via pre-apply snapshot). If rollback fails, use Git.
Plugins
Plugins run only when their config keys are present (and allowed by plugins.enabled).
| Plugin ID | Config keys | Responsibility |
|-----------|-------------|----------------|
| app-name | appName | Android / iOS display name |
| package | packageName, bundleIdentifier | Application ID / bundle ID |
| version | version, buildNumber, android, ios | Version name/code & build numbers |
| icon | icon | Adaptive / legacy icons + AppIcon |
| splash | splash | Full-screen splash assets + launch wiring |
| firebase | firebase | Google services files + native Gradle / iOS wiring |
Lifecycle: validate → beforeApply → apply → afterApply
Restore: backup manager / rollback (not a separate plugin undo API)
Firebase plugin
Built for React Native — primary guide is rnfirebase.io.
Official Android / iOS docs are used only to fill gaps when RN Firebase skips a native step (plist in Xcode, AppDelegate, Gradle fallbacks, etc.).
On init: choose platforms + which services (Auth, Crashlytics, Firestore, …).
On apply: installs @react-native-firebase/* packages, copies config files, and updates native Gradle / Xcode / Podfile automatically.
{
"firebase": {
"android": "./branding/google-services.json",
"ios": "./branding/GoogleService-Info.plist",
"services": ["app", "analytics", "auth", "crashlytics"],
"auth": {
"providers": ["email", "phone", "google", "apple"]
}
}
}| What | Automation |
|------|------------|
| npm | Selected @react-native-firebase/* + auth extras |
| Android | See Android Gradle deps below |
| iOS | Plist → target + pbxproj; AppDelegate; Podfile frameworks |
| Auth providers | Asked on init when auth is selected |
Android Gradle deps (matched to installed RN Firebase)
Versions auto-match the app's @react-native-firebase/app → package.json → sdkVersions.android (same source Expo config plugins use). Apply installs npm packages first, then writes Gradle with those versions. Override with firebase.androidGradle if needed; otherwise pinned fallbacks (4.5.0 / 3.0.7 / 2.0.2).
Official Firebase Android setup BoM/implementation lines are for pure native apps — not applied here.
| When | android/build.gradle (buildscript) | android/app/build.gradle |
|------|--------------------------------------|----------------------------|
| Always (Firebase) | classpath("com.google.gms:google-services:<resolved>") | apply plugin: "com.google.gms.google-services" |
| + crashlytics | classpath("com.google.firebase:firebase-crashlytics-gradle:<resolved>") | apply plugin: "com.google.firebase.crashlytics" (after google-services) |
| + perf | classpath("com.google.firebase:perf-plugin:<resolved>") | apply plugin: "com.google.firebase.firebase-perf" |
| ❌ Never (RN) | — | firebase-bom / implementation("com.google.firebase:…") — SDKs come from npm autolinking |
Auth providers: email, anonymous, phone, google, apple, facebook
Platform-specific: omit android or ios to skip that OS. After iOS: cd ios && pod install --repo-update.
Supported services: app, analytics, auth, crashlytics, firestore, database, storage, messaging, functions, remote-config, perf, app-check, in-app-messaging, installations, app-distribution, ml.
Assets
Place files under branding/ (or point config paths elsewhere).
| File | Guidance |
|------|----------|
| icon.png | Square PNG, ≥ 1024×1024. Opaque preferred for iOS. |
| splash.png | Full-screen portrait. Rec. 1242×2688, min 1080×1920. |
| google-services.json | Android Firebase — from Firebase Console |
| GoogleService-Info.plist | iOS Firebase — from Firebase Console; must be in the Xcode target (plugin registers it) |
After init, see branding/README.md in your project.
Platform limitations
- Android 12+ system splash is primarily icon + background color. Full-bleed art is best-effort via
windowBackground/ older APIs — verify on a real device. - Icon and splash sources that fail size rules cause doctor / apply validation errors.
- Wrong working directory (not the RN root) can miss targets or write in the wrong place — always run from the app root or pass
--cwd.
Best practices
- Commit before every
apply— treat Git as the primary restore path. - Prefer a clean working tree so diffs show exactly what RNBrand changed.
- Run
doctor, thenapply --dry-run, thenapply. - Put real icon / splash files in place before apply (init only scaffolds paths).
- After package ID or heavy native changes, use
build --clean(especially Android). - Keep
.rnforge-backup/until you no longer need local rollback — do not rely on it alone for production or shared repos. - Use selective config — remove keys you do not want updated.
Troubleshooting
Android build fails after apply
cd android && ./gradlew clean && cd ..
rm -rf android/app/build android/build android/app/.cxx android/.cxx
npx rnbrand build android --clean
# or: npx react-native run-androidiOS splash / launch screen wrong or blank
npx rnbrand doctor --verbose
npx rnbrand build ios --clean
# or: cd ios && pod install && cd .. && npx react-native run-iosConfirm UILaunchStoryboardName / LaunchScreen wiring via doctor.
Splash validation errors
- Use a portrait image (height ≥ width).
- Minimum 1080×1920; recommended 1242×2688.
- Centered logo-only images are not supported.
Icon validation errors
- Square source, ≥ 1024×1024.
- Prefer opaque PNG for iOS App Store–style icons.
Rollback did not fully restore
npx rnbrand rollback --list
npx rnbrand rollback --id <backupId> --yes
git status
git restore .Missing rnforge.config.json
npx rnbrand initDoctor exits with code 1
Fix every fail line (assets, config, native targets, stale caches). Warnings alone may still allow apply — prefer a clean doctor run.
FAQ
Why is the package rnbrand but the config is rnforge.config.json?
The published npm name is rnbrand. Config and backup directory names remain rnforge.* for compatibility with existing projects.
Does apply change every native branding field?
No. Only keys present in rnforge.config.json are applied.
Can I use a centered logo as splash?
No. Splash is full-screen cover only.
Is .rnforge-backup enough without Git?
No. It is best-effort. Always commit or copy the project before apply.
Does Firebase work today?
Yes. Add firebase.android and/or firebase.ios paths, place the Google services files under branding/, then npx rnbrand apply. Only platforms listed in config are wired.
Is there a JS API?
RNBrand is a CLI. Use npx rnbrand <command>. Programmatic embedding is not a supported public API in 0.1.0.
Architecture
rnforge/ # repository folder
bin/rnbrand.js # CLI entry
commands/ # init, apply, doctor, build, rollback, version
config/ # defaults + Zod schema
lib/core/ # context, FS, plugins, backup, apply plan
lib/doctor/ # health checks
lib/build/ # android / ios runners
lib/icons/ # icon validate + generate
lib/splash/ # splash validate + generate
lib/validators/ # app name, etc.
plugins/ # app-name, package, version, icon, splash, firebase
templates/
utils/Contributing
Issues and PRs: github.com/Rajubarde12/rnforge
git clone https://github.com/Rajubarde12/rnforge.git
cd rnforge
npm install
npm test
node bin/rnbrand.js --helpPlease open an issue before large features. Keep changes focused; add tests for new behavior.
Package name: rnbrand · publishConfig.access: public
cd modules/rnforge # or your clone root
git status
npm test
npm pack --dry-run
npm login
npm whoami
npm publish --access public
# verify
npm view rnbrand version
npx [email protected] --help
# later releases
npm version patch # or minor / major
npm publish --access public
git push && git push --tagsprepublishOnly runs npm test automatically.
License
MIT © Rajubarde12
Docs wishlist
Useful additions for a high-traffic package (not required to use RNBrand today):
| Item | Status |
|------|--------|
| Screenshots / GIF of init → apply → device | Not included yet |
| Before / after native file diffs | Not included yet |
| Migration guide (future breaking changes) | N/A for 0.1.0 |
| Performance notes (sharp / large assets) | Not documented yet |
| Comparison vs other branding tools | High-level table only above |
| CONTRIBUTING.md / CODE_OF_CONDUCT.md | Not in repo yet |
