One Logo Pool Ball
wwwwwwwwwwwwwwwwwww

Installation

A quick tutorial from start to finish

Getting started with One is as easy as:

Terminal window
npx one

The CLI will guide you through the process of bootstrapping one of our starter templates.

If this is your first One app, we recommend taking this route, as you can choose between bare-bones example all the way up to a full stack with a user system and authentication. We will be launching more starters as the project matures.

Using an AI agent? Install the official One skills so Claude Code, Cursor, Codex, etc. know how to build with One:
Terminal window
npx skills add onestack/skills
Full list and per-agent install instructions: github.com/onestack/skills.

5-minute tutorial

While we recommend using a preset to get started, it’s helpful to walk through creating a new One app from scratch.

For those of you who prefer to learn by doing, we’ve put together a 5-minute tutorial that will have you building a basic app in no time.

Let’s begin with our package.json:

package.json
{
"name": "one-app",
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "one dev",
"build": "one build",
"serve": "one serve",
"prebuild:native": "one prebuild",
"ios": "one run:ios",
"android": "one run:android"
},
"dependencies": {
"one": "latest",
"react": "19.2.3",
"react-native": "0.87.1",
"react-native-web": "^0.21.2",
"@react-navigation/native": "8.0.0-alpha.44",
"react-native-screens": "~4.27.0",
"react-native-reanimated": "~4.6.0",
"react-native-worklets": "~0.12.2"
},
"devDependencies": {
"@react-native-community/cli": "^20.2.0",
"@react-native-community/template": "^0.87.1",
"vite": "^8"
}
}

It is strongly recommended to pin the one version for production stability:

Terminal window
# npm
npm install one@latest --save-exact
# yarn
yarn add one@latest --exact
# pnpm
pnpm add one@latest --save-exact
# bun
bun add one@latest --exact

This ensures consistent behavior across different environments and deployments.

If using pnpm or a package manager that symlinks dependencies, you’ll want to disable that setting. One has (just a few) patches that fix dependencies. This is because the React Native ecosystem has many weirdly published packages (think JSX or Flowtype published in .js files, or non-standard legacy babel experimental transforms, etc). We are working with package authors to improve this, but we’ve found patches to be more reliable, simpler and less mysterious than other solutions.

Platform Support: One currently doesn’t support Windows or Bun with the --bun runtime for development. We’re happy to accept contributions that add support for these platforms. For now, please use macOS or Linux with Node.js or other supported package managers.

Vite Config

Next, let’s add our ultra-simple vite.config.ts:

vite.config.ts
import type { UserConfig } from 'vite'
import { one } from 'one/vite'
export default {
plugins: [
one({
native: {
app: {
name: 'OneApp',
ios: { bundleId: 'com.example.oneapp' },
android: { applicationId: 'com.example.oneapp' },
},
},
}),
],
} satisfies UserConfig

TSConfig

One will create a TSConfig for you when you first start the dev server, with some defaults that work well. Of course you can create your own if you’d prefer. The default looks like this:

{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"~/*": ["./*"]
},
"strict": true,
"rootDir": ".",
"module": "Preserve",
"moduleResolution": "Bundler",
"preserveSymlinks": true,
"skipLibCheck": true,
"jsx": "react-jsx",
"noImplicitAny": false,
"types": ["node", "react", "vite/client"],
"lib": ["dom", "esnext"]
},
"exclude": ["node_modules", "**/test", "**/dist", "**/types", "**/__tests__"]
}

For TypeScript types on One’s preset environment variables, add /// <reference types="one/env" /> to any .d.ts file in your project.

File System Routes

One expects your file system routes to be placed in an app directory.

app/_layout.tsx serves as the top-level wrapper for all routes, ideal for:

  1. Consistent page structure
  2. Global styles or themes
  3. Persistent navigation
  4. App-wide state management

One uses the <Slot /> component to indicate where child components should render, allowing for nested layouts and fine-grained control over your UI structure.

Let’s create a root layout app/_layout.tsx:

app/_layout.tsx
import { Slot } from 'one'
export default function Layout() {
return <Slot />
}

And then create a simple index page app/index.tsx:

app/index.tsx
import { View, Text } from 'react-native'
export default function MyApp() {
return (
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
minHeight: '100%',
}}
>
<Text>Hello from One</Text>
</View>
)
}

You can now install your node modules and run your app. 🎉

Terminal window
bun install && bun run dev

Running your app

If the port isn’t taken, you should be able to load http://localhost:8081 and to see your website (use --port to change the port).

For native, generate the React Native projects once and launch the platform you want:

Terminal window
bun run prebuild:native
bun run ios
# or
bun run android

One’s default native path uses its Vite and Rolldown pipeline and does not require Expo or a Babel config.

Note that for web-only projects you don’t need react-native, and further note that if you want something that has a much broader styling featureset and much lighter bundle-size on web, you can use Tamagui, which has no dependency on React Native.

About Metro Mode

Metro remains available for packages that require it. Set bundler: 'metro' in the native configuration and generate its explicit config:

Terminal window
bunx one metro-eject

The generated babel.config.cjs delegates to the preset (module.exports = require('one/babel-preset')), which builds on React Native’s preset. Those Babel settings belong to the Metro path and are not part of One’s default bundler.

Metro provides:

Use Metro when a dependency requires it. See the Metro Mode documentation for more details.

Edit this page on GitHub.