Skip to content

React Native CLI Projects

Voltra fully supports React Native CLI projects through the voltra CLI. Instead of relying on Expo config plugins, voltra apply updates the native project for you: it modifies the files Voltra needs, generates new Voltra-owned files, and cleans up outdated generated files from previous runs.

Install the same native Voltra packages you would use in Expo for the platforms you support, then add voltra as a dev dependency.

Terminal window
npm install @use-voltra/ios @use-voltra/ios-client
Terminal window
npm install @use-voltra/android @use-voltra/android-client
Terminal window
npm install -D voltra

Then create a voltra.config.ts file. Most properties under ios and android are the same as the Expo config equivalents (see Configuration below).

Minimal example:

import type { VoltraConfig } from 'voltra'
const config: VoltraConfig = {
ios: {
// Commonly needed on iOS so the app and extension can share data.
groupIdentifier: 'group.com.example.app',
widgets: [
{
// Basic widget identity fields.
id: 'portfolio',
displayName: 'Portfolio',
description: 'Track holdings',
// Optional, but commonly used for build-time initial widget content.
initialStatePath: './widgets/portfolio.ios.tsx',
},
],
},
android: {
widgets: [
{
id: 'portfolio',
displayName: 'Portfolio',
description: 'Track holdings',
// Required on Android.
targetCellWidth: 2,
targetCellHeight: 2,
initialStatePath: './widgets/portfolio.android.tsx',
},
],
},
}
export default config

Once the config is in place, apply the native project changes:

Terminal window
npx voltra apply

Most properties under ios and android use the same names as the Expo config equivalents:

The properties below are specific to the Voltra CLI:

Property Purpose
projectRoot Overrides the root directory Voltra should treat as the native project root. Useful when the config file does not live at the app root.
ios.userImagesPath Overrides the directory for user-provided iOS widget images.
ios.project Lets you override iOS project discovery when the app does not use the standard React Native layout. Supports fields such as rootDir, xcodeprojPath, mainTargetName, infoPlistPath, entitlementsPath, and podfilePath. See Multiple environments for setting entitlementsPath per build configuration.
android.userImagesPath Overrides the directory for user-provided Android widget images.
android.project Lets you override Android project discovery when the app does not use the standard React Native layout. Supports fields such as rootDir, appModuleName, manifestPath, and packageName.

For the full config shape, see VoltraConfig and related types in source.

Apps that ship several environments — dev, test, staging, production — build them from one Xcode project using a build configuration per environment, and each environment usually needs its own App Group so a dev build cannot read the production widget’s data.

ios.groupIdentifier, ios.keychainGroup and ios.project.entitlementsPath accept one value per Xcode build configuration name for that:

ios: {
groupIdentifier: {
Debug: 'group.com.example.app.dev',
ReleaseStaging: 'group.com.example.app.staging',
Release: 'group.com.example.app',
},
}

The keys are Xcode build configuration names, not scheme names. A scheme selects a build configuration per action, so a scheme that runs Debug and archives Release picks up the value for whichever configuration the build uses. Every build configuration of the app target must have a value; voltra apply lists the project’s configurations if one is missing or misspelled.

For groupIdentifier and keychainGroup, voltra apply writes the map into your Xcode project as a VOLTRA_* user-defined build setting holding one value per configuration, then writes a reference to that setting — not the value itself — into the entitlements and Info.plist files. Both the app and the generated widget extension inherit the setting, so each build picks up the value for the configuration it is built with. Voltra adds, updates, and removes these settings as your config changes; do not define your own settings under the VOLTRA_ prefix.

If you already keep environment values in .xcconfig files, pass a plain string referencing your own build setting instead, and Voltra copies it through verbatim:

ios: {
groupIdentifier: '$(MY_APP_GROUP)',
}

ios.project.entitlementsPath works differently: it does not create a VOLTRA_* setting. Most projects need no config at all — when a build configuration already points at its own .entitlements file, voltra apply discovers it and writes the App Group in directly. Set entitlementsPath per build configuration only when a file cannot be discovered; each path is then written as that configuration’s CODE_SIGN_ENTITLEMENTS on the app target.

Every time you change voltra.config.ts, reapply the native project changes (see the command above).

The JSX APIs and runtime APIs are the same as in the rest of the Voltra docs. Once voltra apply has set up your native project, continue with the platform guides for iOS and Android.