- Accordion
- Action Sheet
- Alert Dialog
- Alert
- Audio Player
- Audio Recorder
- Audio Waveform
- Avatar
- AvoidKeyboard
- Badge
- BottomSheet
- Button
- Camera Preview
- Camera
- Card
- Carousel
- Checkbox
- Collapsible
- Color Picker
- Combobox
- Date Picker
- File Picker
- Gallery
- Hello Wave
- Icon
- Image
- Input OTP
- Input
- Link
- MediaPicker
- Mode Toggle
- Onboarding
- ParallaxScrollView
- Picker
- Popover
- Progress
- Radio
- ScrollView
- SearchBar
- Separator
- Share
- Sheet
- Skeleton
- Spinner
- Switch
- Table
- Tabs
- Text
- Toast
- Toggle
- Video
- View
Use this when you need to store data and sync it across devices, but do not want sign-in yet. You get everything from the Expo starter plus a Convex backend and a working demo query.
If you want users to sign in, go to Expo + Convex + Auth instead.
Create the app
pnpm dlx bna-ui convex my-app --no-auth
Plain npx bna-ui convex scaffolds the full authentication setup — Google,
Apple, password and email OTP. The --no-auth flag is what selects the
backend-only variant.
The CLI scaffolds the project, installs dependencies, then runs
npx convex dev --once for you. That step is interactive: a browser window
opens so you can log in or sign up, and you pick or create a Convex project. It
writes your deployment URL to .env.local as EXPO_PUBLIC_CONVEX_URL, which is
what app/_layout.tsx reads.
Pass --skip-convex to skip that and run it yourself later.
Run it
Convex-backed apps need two processes. In one terminal:
pnpm dlx convex dev
That watches convex/ and pushes function changes as you save. In another:
pnpm dlx expo start
Press i, a or w to open the app. The home tab shows the demo task list —
add a task and it round-trips through your deployment.
What you get
On top of the Expo starter:
app/_layout.tsx Root layout: ConvexProvider + ThemeProvider
app/(tabs)/(home)/ The demo screen, reading from Convex
convex/
├── schema.ts The `tasks` table
├── tasks.ts list (query), add / toggle / remove (mutations)
├── tsconfig.json Convex's own TS config
└── _generated/ Types, regenerated by `npx convex dev`
package.json gains one dependency: convex.
The demo
convex/schema.ts defines a single table:
import { v } from 'convex/values';
import { defineSchema, defineTable } from 'convex/server';
export default defineSchema({
tasks: defineTable({
text: v.string(),
isCompleted: v.boolean(),
}),
});convex/tasks.ts exposes it. Queries read, mutations write — both are plain
TypeScript functions that run on the server:
export const list = query({
handler: async (ctx) => {
return await ctx.db.query('tasks').order('desc').take(50);
},
});
export const add = mutation({
args: { text: v.string() },
handler: async (ctx, args) => {
return await ctx.db.insert('tasks', {
text: args.text,
isCompleted: false,
});
},
});The screen subscribes with useQuery. It returns undefined while the first
result is in flight, then stays live for the rest of the session — when anything
writes to tasks, every subscribed client re-renders. There is no refetching and
no cache to invalidate:
import { api } from '@/convex/_generated/api';
import { useMutation, useQuery } from 'convex/react';
const tasks = useQuery(api.tasks.list);
const addTask = useMutation(api.tasks.add);
if (tasks === undefined) return <Spinner size='lg' variant='circle' />;Delete convex/tasks.ts, drop the tasks table from the schema and rewrite the
home screen whenever you are ready to build your own thing.
Environment
| Variable | Set by | Used by |
|---|---|---|
EXPO_PUBLIC_CONVEX_URL | npx convex dev, into .env.local | app/_layout.tsx to build the client |
.env.local is gitignored. Your teammates run npx convex dev once to get
their own, or you point them at a shared deployment.
Adding auth later
Nothing here blocks it. @convex-dev/auth layers onto an existing Convex
project — install it, run npx @convex-dev/auth, spread authTables into your
schema, and swap ConvexProvider for ConvexAuthProvider in the root layout.
The auth guide describes the finished shape,
and scaffolding a throwaway project with plain npx bna-ui convex is a quick way
to see the pieces side by side.