Build and ship multiple Expo apps from one codebase.
pnpm create tenkit@latestTenkit creates Expo projects for products that need multiple native app identities: different names, icons, colors, bundle IDs, Android package names, URL schemes, EAS projects, and runtime business contexts.
Instead of copying an Expo app for every brand, venue, customer, or business unit, Tenkit keeps the shared product model explicit and generates a project around the Setup Type you choose.
- Create a generated Expo project with a familiar package-manager create command.
- Choose between White Label Apps, Runtime Tenant App, and Generic + Standalone Apps.
- Keep App Variant identity typed and reviewable: name, slug, scheme, bundle ID, Android package, native assets, theme, and EAS project.
- Keep Runtime Tenant behavior separate from build-time App Variant identity.
- Use generated local commands for Build Preparation, reset, and diagnostics.
- Verify Template output through generated app tests, TypeScript, and Expo config checks.
# Using pnpm
pnpm create tenkit@latest
# Using npm
npm create tenkit@latest
# Using npx
npx create-tenkit@latest
# Using Bun
bun create tenkit@latest
# Using bunx
bunx create-tenkit@latestThe create flow asks for:
- project name
- Setup Type
- App Variant names and Accents
- Styling Choice
It then creates a child folder, installs dependencies with the package manager you used to launch the create command, initializes git when safe, and prints next steps.
Tenkit can be launched through pnpm, npm, npx, Bun, or bunx. The create flow detects that launcher and uses the same package manager for generated project installation, local README commands, and final next steps. You can override detection with --package-manager pnpm, --package-manager npm, or --package-manager bun.
Non-interactive examples:
pnpm create tenkit@latest --name studio-app --setup white-label --yes
pnpm create tenkit@latest --name venue-network --setup runtime-tenants --yes
pnpm create tenkit@latest --name franchise-app --setup generic-standalone --yes
pnpm create tenkit@latest --name unistyles-app --setup white-label --styling unistyles --yesSkip convenience steps when needed:
pnpm create tenkit@latest --name demo --setup runtime-tenants --yes --no-install --no-git| Setup Type | Use When |
|---|---|
| White Label Apps | Every brand, customer, or venue ships as its own native app. |
| Runtime Tenant App | One native app opens multiple Runtime Tenants. |
| Generic + Standalone Apps | One Generic App Variant opens selected Runtime Tenants, while some Runtime Tenants also ship as Standalone App Variants. |
Public create slugs:
white-label
runtime-tenants
generic-standalone
| Styling Choice | Public value | Generated foundation |
|---|---|---|
| Bare | bare |
React Native StyleSheet. Default. |
| Uniwind | uniwind |
Tailwind styling for React Native. |
| Unistyles | unistyles |
Adaptive styling with Unistyles 3. |
Select a non-default Styling Option Value with --styling. Bare remains the default when Styling is omitted or --yes accepts defaults.
| Concept | Meaning |
|---|---|
| App Variant | A build-time native app identity: app name, slug, scheme, bundle ID, package name, assets, theme, and EAS project. |
| Runtime Tenant | A business, organization, customer, venue, or context opened at runtime. |
| Setup Type | The relationship model between App Variants and Runtime Tenants. |
| Template | Standalone project-generation source for a selected Setup Type. |
| Public CLI | The create command surface that generates Tenkit projects from Template source. |
| Playground | The Expo app inside this repo that proves setup behavior in a real runnable app. |
Build Preparation selects an App Variant. Runtime Tenant selection, when a setup uses Runtime Tenants, remains runtime behavior inside the app.
Clone the repo:
git clone <repository-url>
cd tenkitUse the project Node version and install dependencies:
nvm install
nvm use
corepack enable pnpm
pnpm installStart the Playground:
pnpm startThe root start command runs apps/playground. You can also run commands directly from that package:
cd apps/playground
pnpm startChoose a local App Variant with apps/playground/.env.local:
cp apps/playground/.env.example apps/playground/.env.localAPP_VARIANT_SLUG=first-tenantIf APP_VARIANT_SLUG is omitted, the Playground uses the default App Variant from apps/playground/src/active-setup/manifest.ts.
Run the selected variant:
pnpm ios
pnpm android
pnpm webPrepare native projects after changing App Variant identity, native assets, plugin config, or App Variant Environment:
pnpm tenkit buildReset generated native projects:
pnpm tenkit resetCheck setup health:
pnpm tenkit doctorpnpm tenkit is Playground-local tooling for Scaffold, Build Preparation, reset, and diagnostics. Public project creation lives in create-tenkit and delegates to @tenkit/cli.
Generate Template output into a separate folder:
pnpm proof -- --setup-type white-label --target ../tenkit-white-label-proof
pnpm proof -- --setup-type runtime-tenants --target ../tenkit-runtime-tenants-proof
pnpm proof -- --setup-type generic-standalone --target ../tenkit-generic-standalone-proofRun generated app shape proof tests:
pnpm test:proofRun full generated app command verification:
pnpm verify -- --setup-type white-label
pnpm verify -- --setup-type runtime-tenants
pnpm verify -- --setup-type generic-standaloneEach App Variant maps to exactly one EAS Project.
For each App Variant:
- Log in with EAS CLI.
- Create or find one EAS Project in your Expo account or organization.
- Copy that EAS Project ID into the App Variant's
eas.projectId. - Replace
EXPO_OWNERwith your Expo account or organization owner.
eas loginUse eas init only to create or discover an App Variant's EAS Project ID. EAS Project IDs are public identifiers and belong in setup data, not EAS environment variables.
.
├── apps/
│ └── playground/ # Runnable Expo Playground app
├── packages/
│ ├── cli/ # Public CLI implementation package
│ ├── create-tenkit/ # Thin package-manager create entrypoint
│ └── template-generator/ # Template source, generation, and writer package
├── package.json # Workspace command surface
└── pnpm-workspace.yaml # pnpm workspace configuration
pnpm test
pnpm check
pnpm typecheck
pnpm lintPublic CLI checks:
pnpm build
pnpm smoke
pnpm pack:dry-runTemplate-generator checks:
pnpm -F @tenkit/template-generator test
pnpm test:proof
pnpm verify -- --setup-type white-labelOpen an issue for bugs, missing Setup Type behavior, generated output problems, or CLI create-flow rough edges. Keep domain language precise: App Variant, Runtime Tenant, Setup Type, Template, Public CLI, Playground, Scaffold, and Build Preparation each mean different things in Tenkit.
This repo targets Expo SDK 57.
Read the exact versioned Expo docs before changing Expo code:
https://docs.expo.dev/versions/v57.0.0/
MIT
Using Tenkit at work? Sponsor me to support ongoing development and maintenance.