Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# Copy to .env.local. EXPO_PUBLIC_* vars are inlined into the JS bundle at build
# time, so treat them as public (dev/demo only). Without a Cerebras key here, the
# time, so treat them as public (dev/demo only). Without a Thesys key here, the
# app just asks for one on first launch and stores it on-device.

# Required (unless you enter it in-app on first launch):
EXPO_PUBLIC_CEREBRAS_API_KEY=csk-REPLACE_ME
# Required (unless you enter it in-app on first launch) - https://console.thesys.dev/keys:
EXPO_PUBLIC_THESYS_API_KEY=sk-th-REPLACE_ME

# Optional tools:
# EXPO_PUBLIC_EXA_API_KEY= # web_search, else the model invents data
# EXPO_PUBLIC_UNSPLASH_ACCESS_KEY= # real photos, else LoremFlickr

# Optional model overrides (any OpenAI-compatible endpoint):
# EXPO_PUBLIC_CEREBRAS_BASE_URL=https://api.cerebras.ai/v1
# EXPO_PUBLIC_GENOS_MODEL=gemma-4-31b
# Optional model overrides (any OpenAI-compatible OpenUI Cloud endpoint):
# EXPO_PUBLIC_THESYS_BASE_URL=https://api.thesys.dev/v1/embed
# EXPO_PUBLIC_GENOS_MODEL=google/gemma-4-31b-it

# Opt out of anonymous run analytics:
# EXPO_PUBLIC_POSTHOG_DISABLED=1
30 changes: 17 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,20 @@ npm install # postinstall applies the react-lang patch
npm run ios # or: npm run android, or npm start for Expo Go
```

On first launch the app asks for a free [Cerebras](https://cloud.cerebras.ai)
API key and stores it on-device (Keychain / Keystore). Generation runs straight
from the phone to the model. There is no backend to deploy.
On first launch the app asks for a [Thesys](https://console.thesys.dev/keys) API
key and stores it on-device (Keychain / Keystore). Generation runs straight from
the phone to [OpenUI Cloud](https://openui.com), which owns the system prompt
and routes the model call to Cerebras. There is no backend to deploy.

To skip the key prompt during development, or to turn on optional tools, drop a
`.env.local` in the project root:

```bash
EXPO_PUBLIC_CEREBRAS_API_KEY=csk-... # skip the first-launch key screen
EXPO_PUBLIC_THESYS_API_KEY=sk-th-... # skip the first-launch key screen
# EXPO_PUBLIC_EXA_API_KEY= # enable the web_search tool (Exa)
# EXPO_PUBLIC_UNSPLASH_ACCESS_KEY= # real semantic photos (else LoremFlickr)
# EXPO_PUBLIC_GENOS_MODEL=gemma-4-31b
# EXPO_PUBLIC_CEREBRAS_BASE_URL= # any OpenAI-compatible endpoint
# EXPO_PUBLIC_GENOS_MODEL=google/gemma-4-31b-it
# EXPO_PUBLIC_THESYS_BASE_URL= # any OpenAI-compatible OpenUI Cloud endpoint
```

> Expo SDK 54 is pinned to match the Expo Go build on the App Store and Play
Expand All @@ -81,17 +82,19 @@ EXPO_PUBLIC_CEREBRAS_API_KEY=csk-... # skip the first-launch key screen

```mermaid
flowchart LR
A["ui/contract.tsx<br/>(one contract)"] --> B["system prompt<br/>(generated)"]
B --> C["Cerebras LLM<br/>(streaming)"]
A["ui/contract.tsx<br/>(one contract)"] --> B["chatLibrary + prompt spec<br/>(generated config)"]
B --> C["OpenUI Cloud → Cerebras<br/>(streaming)"]
C --> D["openui-lang<br/>(the DSL)"]
D --> E["Renderer<br/>(react-lang)"]
E --> F["native UI<br/>(Cupertino / Material)"]
```

One contract, `ui/contract.tsx`, is the single source of truth for every
component the model can use: its name, its props, and a description. That
contract generates the system prompt, so the model always knows exactly the UI
vocabulary the app can render. As tokens stream back, the OpenUI
contract is serialized into the `chatLibrary` OpenUI Cloud generates the system
prompt from, so the model always knows exactly the UI vocabulary the app can
render - and Cloud validates every screen it streams back against that same
library. As tokens stream back, the OpenUI
[`<Renderer>`](https://openui.com) parses openui-lang incrementally and paints
real native components, live, before the response has even finished.

Expand All @@ -113,7 +116,7 @@ the OpenUI stack:
| Package | Role |
| --- | --- |
| [`@openuidev/react-lang`](https://openui.com) | The OpenUI runtime: parses streaming openui-lang and renders it through a pluggable component library. The core of the whole app. |
| [`@openuidev/cli`](https://openui.com) | Generates the system prompt from the component contract (`npm run generate:prompt`). |
| [`@openuidev/thesys-server`](https://openui.com) | Turns the component contract into the OpenUI Cloud request config - `chatLibrary` + AppLess prompt options (`npm run generate:prompt`). |
| [`expo`](https://expo.dev) / [`react-native`](https://reactnative.dev) | The native app runtime (Expo SDK 54, New Architecture). |
| [`react-native-svg`](https://github.com/software-mansion/react-native-svg) | Chart geometry shared across both design systems. |
| [`react-native-webview`](https://github.com/react-native-webview/react-native-webview) | Keyless Google Maps embed for `MapView`. |
Expand All @@ -123,8 +126,9 @@ the OpenUI stack:
| [`zod`](https://zod.dev) | Prop schemas in the component contract. |
| [`@react-native-community/slider`](https://github.com/callstack/react-native-slider) | Native slider input for forms. |

Screens are generated by [Cerebras](https://cloud.cerebras.ai); live search is
powered by [Exa](https://exa.ai). Both are bring-your-own-key.
Screens are generated through [OpenUI Cloud](https://openui.com) on
[Cerebras](https://cloud.cerebras.ai); live search is powered by
[Exa](https://exa.ai). Both are bring-your-own-key.

## Design systems

Expand Down
Loading