# expo-app-template and the case for a React Native starter that is already decided

> expo-app-template is a TypeScript starter for React Native that fixes the stack for you, from Expo Router and React Compiler to fbtee for translations, and hands over a Vite+ powered toolchain. It saves setup research and takes on opinions you did not choose.

**nkzw-tech/expo-app-template** — Modern, sensible defaults and fast Expo app template.

- Repository: https://github.com/nkzw-tech/expo-app-template
- Stars: 766 · Forks: 53
- Language: TypeScript
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/nkzw-tech-expo-app-template

## The template's real content is a list of decisions already made

The pitch in the README is blunt about what a new React Native project costs. You have to make a lot of decisions and install tons of packages every time you create a new app, and the template exists so you copy a working set of them instead of researching each one.

The decisions listed are specific rather than generic. Expo 57 and React Native 0.86 with the New Architecture are the base, with Expo Router for navigation, Uniwind and Tailwind for styling, fbtee for i18n, TypeScript throughout, and React Compiler in the mix. The library list also includes @gorhom/bottom-sheet, Legend List, react-native-svg with react-native-svg-transformer, react-native-gesture-handler, react-native-reanimated, react-native-mmkv and react-native-nitro-modules, plus react-native-safe-area-context and react-native-screens.

Two of these are worth more attention than the rest. React Compiler is listed as a technology rather than left implicit, and the repository carries babel-plugin-react-compiler in dependencies along with a babel.config.js at the root, so the compiler is wired into the build rather than aspirational. Legend List is present as @legendapp/list, which is a deliberate choice of list implementation over the older options, and the bottom sheet and SVG transformer are picked for the specific look an app tends to want.

The result is a starter where almost nothing about the stack is left to the person cloning it.

## Vite+ runs the toolchain, and Expo is invoked through it

The most surprising thing about this template is that the build tool is not Expo. Vite+ is listed as a technology, and the scripts in package.json route almost everything through it: prepare runs vp config, dev:setup runs vp run fbtee:all, and fbtee:all itself calls vpx fbtee collect and vpx fbtee translate. The project also pins pnpm through pnpm-lock.yaml and pnpm-workspace.yaml.

What is left to Expo is the runtime commands: dev runs expo start, ios runs expo run:ios with a device argument of iPhone 17 Pro, android runs expo run:android, prebuild runs expo prebuild, start runs expo start --dev-client, and web runs expo start --web. The main field of package.json points at expo-router/entry, so the router is the application entry point in the usual Expo way.

The entry is a Vite+ setup with the Expo SDK as a dependency, and the distinction matters for anyone coming from a default create-expo-app project. The two toolchains have different configuration surfaces, and a developer who expects a metro-only workflow will be looking in the wrong files. The repository layout confirms it: there is a vite.config.ts at the root next to metro.config.cjs and metro.transformer.cjs, plus a postcss.config.mjs and a global.css.

## Getting a working install: the commands are short

The project guide points at GitHub's template generator as the way in, with a link to create a new app using this template. After that, the prerequisites are Node.js 24, Vite+ and Cocoapods, and the two commands to install them are:

```bash
curl -fsSL https://vite.plus | bash
brew install cocoapods
```

Cocoapods is a macOS specific step, which tells you the target audience for the iOS path is a developer on a Mac with Xcode. The project guide also links to the Expo setup guides for building and running locally.

Dependencies are then installed with:

```bash
vp install && vp run dev:setup
```

Running the iOS app in a simulator is two more commands, first the native project generation and then the run:

```bash
vp run prebuild
vp run ios
```

The prebuild step generates the native iOS project from app.json, which is why app.json sits at the root of the tree, and the ios script targets a named simulator. The project guide notes that if the app is already installed on the simulator you can skip those steps and start the development server with pnpm dev instead, which is a useful shortcut once you iterate past the first run.

## fbtee handles translations as a build step, not a folder of JSON

Internationalization is the part of the template that is most specific to this author. fbtee is listed as the library for i18n, and the script wiring shows what that means in practice: fbtee:all runs vpx fbtee collect with a --disable-babel-config flag, then vpx fbtee translate. The dev:setup script runs fbtee:all, so translation work happens as part of the setup rather than as a separate manual step.

The collect and translate split suggests a two-phase flow where strings are gathered from the source and then the translation files are produced. The repository layout supports that reading: there is a translations/ directory at the root, alongside a src/ directory for the app code and an assets/ directory for images.

The collect step runs with --disable-babel-config, which is a detail worth copying. It tells the collector not to apply the project's Babel configuration during collection, which avoids the React Compiler plugin and any other transform interfering with the extraction pass. If you write your own tooling around fbtee, that flag is the kind of thing that costs an afternoon to rediscover.

The template also links to a separate nkzw-tech/server-template built on GraphQL with Pothos and Prisma, and to a web app template, so the same author maintains a wider set of starters rather than a single repository.

## Relay is a branch, not a dependency

Relay is marked optional in the README, and the way it is offered is a branch rather than a flag. The with-relay branch of the repository carries the Relay setup for data fetching, while the main branch does not.

That is a deliberate constraint of how a template can be consumed. A template repository is copied, and once copied you own the result, so optional integrations that require meaningful configuration are easier to deliver as a separate starting point than as a toggle inside one. The cost is that adopting Relay means starting from a different branch, and merging Relay into an app that already started from main is a job in itself.

The same pattern explains the external links to the server and web templates. Data fetching, the GraphQL server and the web frontend are all separate repositories, which keeps this one focused on the mobile client.

The ESM decision sits in the same category but is already applied. The project guide notes the package.json field "type": "module" and frames it as a settled matter, and the tree confirms the app is a native ES module package with a .cjs file present only for the Metro configuration, which is the one part of the toolchain that still expects CommonJS.

## Where a template like this stops being the right answer

The obvious case is an existing app. Every value in this repository is in the starting decisions, and a codebase that already has a router, a styling approach and a translation pipeline cannot borrow any of it without a migration that is larger than writing the pieces directly.

The second case is a hard constraint on the toolchain. Vite+ is required for the install and run commands, and the scripts assume it. A team on a locked-down corporate machine, or one that has standardised on a different build tool, will find the documented commands do not apply, because the project guide does not describe an alternative path that bypasses Vite+.

The third is platform coverage. The iOS instructions lean on macOS, since Cocoapods is installed with brew, and the ios script names an iPhone 17 Pro simulator, so the out-of-the-box path is tuned for one platform on one operating system. Android is supported through expo run:android, but the documented setup and run flow covers iOS.

A fourth, quieter limitation is the template's nature as a fixed starting point. The versions listed are fixed, Expo 57 with React Native 0.86, and upgrading a copied template means upgrading your own copy, since the upstream history is no longer connected to it.

## Maintenance, licence and what the repository contains

The project is MIT licensed and the last push to the repository was on 2026-09-16. There are no GitHub releases to pin to, so the template is consumed as a branch or a copy rather than as a versioned artifact, which is normal for templates but means there is no changelog to read before adopting one.

The contents give a fair picture of the scope. The root holds app.json for the Expo configuration, eas.json for the build service, babel.config.js, metro.config.cjs and metro.transformer.cjs for the bundler, vite.config.ts, postcss.config.mjs, global.css, app-env.d.ts for the type declarations, tsconfig.json, a .svgrrc for SVG component handling, and the assets/ directory. The source lives in src/, the translations in translations/, and the dependencies are pinned in pnpm-lock.yaml.

The three .svgrrc, metro.transformer.cjs and global.css entries are the tell that this is a working setup rather than a skeleton. The SVG transformer configuration matches the react-native-svg-transformer dependency, the Metro transformer file is there because the ESM package still needs a CommonJS entry for Metro, and global.css exists because Uniwind pulls Tailwind in through PostCSS.

For a team, the honest summary is that this is a well-chosen, opinionated starting point that saves a week of decisions and makes a different set of trade-offs than a default Expo project, and that adopting it means accepting the author's preferences about routing, styling, translation and build tooling rather than negotiating them.

## Conclusion

expo-app-template suits a team starting a new mobile app that would otherwise spend its first week choosing a router, a styling approach, a translation pipeline and a compiler setup, and it suits developers who want React Compiler and the New Architecture switched on from the first commit. It does not suit a team with an existing Expo app, since the value is entirely in the starting decisions, and it does not suit someone who needs Relay on day one without switching branches, since Relay lives on the with-relay branch rather than on main. Before you copy it, confirm Node.js 24, Vite+ and Cocoapods are available on the machine that will run the iOS build, and read the scripts section of package.json, because the tooling is Vite+ first and Expo second, which is the opposite of the usual expectation.

## FAQ

### How do I create a new app from expo-app-template?

The project guide links to GitHub's template generator with the template name expo-app-template and the owner nkzw-tech, so you create a repository from the template and then modify it freely. After that you install dependencies with vp install && vp run dev:setup.

### What does expo-app-template require before I can run the iOS app?

The prerequisites are Node.js 24, Vite+ and Cocoapods, installed with curl -fsSL https://vite.plus | bash and brew install cocoapods. The iOS simulator run then needs vp run prebuild followed by vp run ios.

### Does expo-app-template use Expo Router and TypeScript?

Yes. The project guide lists Expo Router and TypeScript among the technologies, and the main field in package.json points at expo-router/entry, with app-env.d.ts and tsconfig.json in the repository root.

### How does expo-app-template handle translations?

It uses fbtee for i18n, with a script that runs vpx fbtee collect --disable-babel-config followed by vpx fbtee translate. That fbtee:all script is what dev:setup invokes, and translation files live in the translations directory.

### Can I add Relay to an app based on expo-app-template?

Relay is marked optional and is provided on the with-relay branch of the repository rather than on the main branch. If you need Relay from the first commit, start from that branch instead of main.

## Sources

- [Issues](https://github.com/nkzw-tech/expo-app-template/issues)
- [License: MIT](https://github.com/nkzw-tech/expo-app-template/blob/main/LICENSE)
- [nkzw-tech/expo-app-template on GitHub](https://github.com/nkzw-tech/expo-app-template)
- [README](https://github.com/nkzw-tech/expo-app-template/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/nkzw-tech-expo-app-template
