Model or dataset
dabit3/react-native-ai avatar
dabit3/react-native-ai

React Native AI: adding a model means editing four files, the root has a package lock and no package manifest, and the sample function name has a typo

Full stack framework for building cross-platform mobile AI apps

1,304 stars168 forksTypeScriptMIT

At a glance

What is it?
This framework scaffolds a mobile app and a small server so a phone can talk to several model providers through one proxy. It streams text, generates images, and ships five themes. The parts that matter for an adopter are the extension path and the layout: bringing a new provider online is a documented sequence of edits to a constants file, a screen, a utility and a router, on two sides of the repository.
Who is it for?
React Native AI fits someone building a mobile chat client who wants a server side to hold provider credentials and who is comfortable editing a template rather than configuring a plugin. It does not fit a team that wants to swap providers through configuration, because every provider is a code change on both sides.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 29 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 4, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Adding a model is five edits in the app and two on the server

The documentation is unusually explicit about what extension costs, which is more useful than a plugin interface would be. To add a chat model on the app side you do five things: add the definition to the models array in the constants file, create local state to hold the new model's data, update the chat function to handle the new model type, create a function that calls the new model, and update a helper in the utilities file to map it to your server path. Then you render it. On the server side you create a new file in the chat folder matching the type you defined, and update the chat router to use the route, with a note that you can probably copy and reuse much of the streaming code from the existing paths. That last sentence is the honest summary of the whole design: the framework is a working template, and each provider is a fork of the previous one. Removing a provider is one line, which is the only part of the story that is a single edit.

Every model type gets its own list, and the sample name is misspelled

Step five is rendering the model in the interface, and the example shows why it is a separate step rather than an argument to an existing renderer. Each chat type gets its own conditional branch and its own list component with its own data and its own scroll behaviour:

tsx
{
  chatType.label.includes('newModel') && (
    <FlatList
      data={newModelReponse.messages}
      renderItem={renderItem}
      scrollEnabled={false}
    />
  )
}

So the per-provider render path duplicates rather than shares, and the duplication grows with each provider you add. The sample also gives the function you are supposed to create a name with a missing letter, spelled with the two consonants in the wrong order, and step three instructs you to create exactly that function. Anyone following the guide literally ends up with that name in their own code, in the chat screen, in whatever dispatches to it. It is a small thing, but it is the kind of artefact that appears in other people's repositories for a decade because the tutorial is the source.

The root holds a package lock and no package manifest

Look at the top level listing:

text
package-lock.json
skills-lock.json

There is a package lock and no package manifest beside it. The repository is split into three directories: the mobile app, the server, and the command line tool that generates a new project, plus a licence file, a readme, two workflow directories and those two lock files. Neither readme file is mentioned anywhere in the visible documentation, and no package manifest appears at the root of the listing, which means the lock file belongs to one of the sub-projects or was committed at the wrong level. Either way, running an install from the root will not do what a reader expects, and the two run commands in the quick start are scoped to a directory each rather than to the root, so the layout has to be understood before anything installs. The skills lock is the more interesting of the two: nothing in the documentation describes what it pins.

The provider list is a snapshot of vendor model names

The first feature bullet names the models: two generations from one provider including a mini variant, three from another including a family grouping three tiers, and one each from three more providers, with specific version numbers attached to every one. The image bullet names a single provider and a single image model family. That is a snapshot, and snapshots of model names are the fastest decaying text in a readme. The framework itself is version-agnostic, since a provider is just a streaming handler on the server and a constants entry plus a renderer on the app, but the readme is where a reader looks to decide whether their provider is supported, and there it will be out of date within a few model generations. Nothing in the documentation says which versions the code was tested against or how to check what the template actually calls, so the reliable check is to read the handlers in the server's chat folder.

The proxy exists so provider keys never reach the phone

One feature bullet is short and load bearing: a server proxy that makes it easy to add authentication and authorisation with whichever provider you choose. That is the reason the project ships two applications instead of one. The mobile app talks to your own server, and the server talks to the model providers, so the keys live on the server and the app ships without any. The environment section is consistent with that: the server's example environment file is the place to configure things, and one specific variable is named as required for image generation. The setup instruction is also practical, since the file ships with an example name and the instruction is to rename it if it is not already present. What is not documented is the authentication story the proxy enables: the app has no login, no token handling and no session, so the server endpoint is open to anyone who can reach it, and that is a decision you have to make yourself.

Five themes ship, three of them named after companies

Theming is documented as a few lines, and it is genuinely a few lines. You open one file in the app, spread an existing theme or start from scratch, and set a name, a label, a tint colour, a text colour, two tab bar colours and a placeholder colour. Then you add the theme to an export list at the bottom of the same file:

ts
export {
  lightTheme, darkTheme, hackerNews, miami, vercel, christmas
}

That export list is the second edit, and it is the kind that gets forgotten, since nothing errors when a theme is defined but not exported. The five shipped themes include a light and a dark one and three named after things outside this project: one after a news site, one after a city, and one after a hosting company. Shipping a template with third-party names in the theme list is normal for a starter kit and worth renaming before anything public goes out, since those strings end up in your bundle. The example theme in the documentation uses two greens and a red, which is a reminder that the palette is entirely yours to pick.

The description promises image processing the documentation never covers

The repository's one line description lists three capabilities: streaming text and chat interfaces, image services and text to image with multiple models, and image processing. The visible documentation covers the first two. Generation has its own section with its own constants array, its own screen and its own server handler folder, and it comes with a note that names the real design question, which is whether a model takes text, image or both as input, and a warning that the app is set up for both but that you must update the generate function to pass values accordingly. Image processing has no section, no flag, no script and no model. It may well exist in the code, and the visible text simply does not say so, but a reader choosing a framework on the strength of a description would be reading a capability list rather than a manual. The image pipeline otherwise mirrors the chat one exactly, down to copying a handler file and adding a route.

Editorial conclusion

React Native AI fits someone building a mobile chat client who wants a server side to hold provider credentials and who is comfortable editing a template rather than configuring a plugin. It does not fit a team that wants to swap providers through configuration, because every provider is a code change on both sides. Four things to check after generating a project. Whether the generated structure matches what you need, since the documentation assumes two directories with separate run commands and never states a React Native version or how the native projects are set up. How many files a provider change touches, since the documented sequence runs through a constants array, a screen, a utility and a router. Whether the model list in the readme is still current, since it is a snapshot of vendor model names that will age. And what the lock files in the root are for, since a package lock appears with no package manifest beside it.

Frequently asked questions

How do I create a new React Native AI project?

Run the generator from the command line, which scaffolds both the mobile app and the server. Then run the start command inside the app directory and the development command inside the server directory, and configure the server environment variables from its example file.

How do I add a new LLM model to React Native AI?

On the app side: add it to the models array in the constants file, add local state, update the chat function, create the function that calls the model, update the type helper in the utilities file, and render it in the interface. On the server: add a file in the chat folder and register the route in the chat router.

Do API keys have to go in the React Native AI mobile app?

No. The framework ships a server proxy specifically so authentication and authorisation can live on the server with a provider of your choice, and the environment variables are configured on the server side, where image generation needs a Gemini key.

How do I add a new theme in React Native AI?

Open the theme file in the app, spread an existing theme or start from scratch, set the name, label, tint colour, text colour, the two tab bar colours and the placeholder colour, then add the theme to the export list at the bottom of that same file.

Which model providers does React Native AI support?

The readme names two generations from one provider including a mini variant, three from another including a family of three tiers, and one each from three further providers, plus Gemini for image generation. The names carry specific version numbers, so treat that list as a snapshot and read the server handlers for what the template actually calls.

Official sources

  1. dabit3/react-native-ai on GitHub
  2. Issues
  3. License: MIT
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dabit3-react-native-ai.svg)](https://hysenlabs.com/projects/dabit3-react-native-ai)