@pj21/create-expo-app
v1.0.1
Published
Scaffold a new Expo app from the pooyaj21/expo-template repo
Maintainers
Readme
create-expo-app
Scaffolds a new Expo app from pooyaj21/expo-template.
The template lives in its own repository and is cloned at run time — the two stay separate projects, the template ships on its own cadence, and this CLI never needs a release just because a screen changed.
npx @pj21/create-expo-app # → "My App" in ./my-app
npx @pj21/create-expo-app "Order Tracker" # → ./order-tracker
npx @pj21/create-expo-app Order Tracker # quotes are optionalWith no name it creates My App. Everything else — the slug, the URL scheme, the bundle id, the package name, the directory — is derived from that one string, which is what stops a project ending up with four identifiers that disagree.
| Input | Becomes |
| --------------- | ------------------------------------------ |
| Order Tracker | name Order Tracker |
| | slug / directory / package order-tracker |
| | scheme ordertracker:// |
| | bundle id com.pj21.ordertracker |
Options
| Flag | Does |
| ------------------- | --------------------------------------------------------------- |
| --bundle-id <id> | iOS bundle id and Android package (default com.pj21.<scheme>) |
| --dir <path> | Target directory (default: the slug) |
| --template <spec> | Repo, git URL, or local path (default pooyaj21/expo-template) |
| --ref <branch> | Template branch or tag (default: the repo's default branch) |
| --no-install | Skip npm install |
| --no-git | Skip git init |
| -h, --help | Usage |
| -v, --version | CLI version |
It runs git init but never commits — the first commit is yours to make.
Choosing a template
--template pooyaj21/expo-template#next # a branch, via shorthand
--ref v2.0.0 # a tag
--template [email protected]:acme/tpl.git # any git URL
--template ../expo-template # a local checkout, for template workSet CREATE_EXPO_APP_TEMPLATE to change the default for a machine.
git clone is used rather than a tarball download so your existing credentials
(SSH keys, credential helper) carry over — which is what makes a private
template work with no token handling here. A local path that exists on disk wins
over the owner/repo reading, since a real directory is the less surprising
interpretation.
What it does
- Shallow-clones the template, then deletes its
.git— the new project starts on a clean slate rather than inheriting the template's history. (A local--templatepath is copied instead, skippingnode_modules,.git,.expo,ios,android,.idea,.envand husky's generated.husky/_.) - Rewrites the identity constants at the top of
app.config.ts, thenameinpackage.json, and the README heading. If those constants ever move, it fails loudly rather than emitting a project still called "App Template". - Creates
.envfrom.env.example, so the firstnpm starthas a config, andexpo-env.d.tsif the template does not carry one — without it a fresh clone cannot typecheck until someone runsexpo start. git init, thennpm install— in that order, because husky'sprepareinstalls its hooks into a repository that has to exist first.
A failed clone cleans up after itself, so a retry is not blocked by the wreckage of the last attempt.
Paths with spaces are refused
Xcode and CocoaPods run build phases through an unquoted shell, so a space
anywhere in a project's absolute path truncates it. expo-constants' "Generate
app.config" phase then fails with No such file or directory: /Users/you/My and
nothing points at the real cause.
The CLI checks the resolved path up front and refuses. The directory it picks
never has a space — an ancestor usually does, so run it from somewhere like
~/Projects, not ~/My Projects.
Publishing
The unscoped name create-expo-app belongs to Expo on npm, so this publishes
under the scope in package.json (@pj21/create-expo-app) and is invoked as
npm create @pj21/expo-app or npx @pj21/create-expo-app. Change the name
field if you want a different one.
The published tarball is ~8 kB: the template is not in it.
Requirements
Node 18.3+ (for util.parseArgs). No runtime dependencies.
