Quick start
Create a React Native app with a Backtick server in one command, then write a screen, serve it per request and draw it in your app.
npx create-backtick-app@latest my-app
It asks for a framework and a runtime. Pick React Native, and it creates an Expo app with a Backtick server beside it, then installs its packages.
To skip the questions, as an agent or a script would, pass the answers:
npx create-backtick-app@latest my-app --template react-native --runtime node
Run it
cd my-appnpm run ios
npm run ios starts your Backtick server and Expo together, then opens the
app in the iOS Simulator. Use npm run android for an Android emulator, or
npm run web for a browser.
The app shows a welcome screen. It isn't in the app: your server sent it.
Change the screen
The screen is server/Home.tsx. Replace it with this, and save:
import { cs } from "@backtickjs/core";import { useState } from "@backtickjs/react";import { Pressable, Text, View } from "@backtickjs/react-native";// A client component: it runs on the phone.const Counter = cs`() => {const [count, setCount] = $useState(0);return (<$Pressable onPress={() => setCount(count + 1)}><$Text style={{ fontSize: 18, color: "#0a7ea4" }}>Tapped {count} times</$Text></$Pressable>);}`;// A server component: it runs on your server, for every request.export async function Home() {const time = new Date().toLocaleTimeString();return cs`(<$Viewstyle={{flex: 1,justifyContent: "center",alignItems: "center",gap: 16,}}><$Text style={{ fontSize: 24 }}>Served at {$time}</$Text><$Counter /></$View>)`;}
The app redraws with the new screen, without rebuilding. Tap the counter, then
save again: the time changes, because the server ran Home again.
What you just wrote:
Homeis a server component. It runs on your server, for every request. Read from a database here, call an API, use any npm package: none of it reaches the phone.cs`…`is a client script. The code inside the backticks runs on the phone. Here, it's the screen's JSX.$timeis a splice. It's a value from your server, written into the screen as data. TypeScript checks it on both sides.Counteris a client component. It's a script that takes props, used as<$Counter />. Its state lives on the phone.$Viewand$useStateare React Native and React, with the same names and types, spliced from@backtickjs/react-nativeand@backtickjs/react.
What's in your project
my-app/├── App.tsx The app: fetches each screen from your server and draws it├── server/│ ├── index.tsx Your server: bundles a screen per request│ ├── Home.tsx The screen you just changed│ └── HelloWave.tsx The welcome screen's waving hand, safe to delete└── package.json
Everything in server/ reaches users without an app release: deploy your
server, and users get the change the next time they open the screen.
npm run typecheck checks the app and your server, the code inside every
cs`…` included. npm run reset-project replaces server/Home.tsx with a
blank screen, and deletes HelloWave.tsx, when you're ready to start your own.
Next steps
- Tutorial: build a coffee-ordering screen, step by step, in the project you just created.
- Thinking in Backtick: what runs where, and what crosses between your server and the phone.