React Native and Expo
One prompt: XP, levels, coins, streaks, badges, quests, leaderboards, leagues, referrals and push in a React Native or Expo app.
A React Native or Expo app reads Orishare as the signed-in user: the publishable key plus a
customer session. The default is server first: your backend holds the secret key, mints the
session and reports what happened. With Firebase that backend is the Cloud Functions kit
(Firebase app), with Supabase the Edge Function template
(Supabase app), otherwise your own server
(Web game, step 5). Never put a secret key (osk_) or the agent token
in the app or in EXPO_PUBLIC_* variables: they ship in the bundle.
The prompt
Paste this into your coding agent from the root of the app.
Add a reward system to this React Native / Expo app with Orishare: XP and levels, coins, a daily
streak with repair, badges, a starter quest, a weekly XP leaderboard, a weekly league, friend
referrals, friends with friend streaks and a weekly friend quest, and push notifications. Follow https://docs.orishare.com/docs/recipes/react-native.md
and the pages it links, step by step: sign up for Orishare yourself (no human needed), apply the
game starter configuration in the test environment, add the client module and screens the recipe
describes, test every HTTP call the app makes against the test environment, then give me the claim link
and a short list of what you built. Never put a secret key (osk_) or agent token (opat_) in the app.Steps
-
Sign up with Start here for AI agents, then apply the game starter in the test environment: Game setup. For an app that is not a game, rename the events (
lesson.completedforlevel.completed) in the change set before you apply it; the mechanics are the same. -
Get a session for the user from your backend. Firebase: deploy the
@orishare/firebase-functionskit (steps 2 to 5 of Firebase app) and callorishareSessionwith@react-native-firebase/functions(or thefirebase/functionsJS SDK). Supabase: deploy the Orishare Edge Function (steps 2 to 4 of Supabase app) and call it withsupabase.functions.invoke('orishare', { body: { action: 'session' } }). Any other backend mints it with the secret key (Web game, step 5). Each answerscustomer_tokenandexpires_at; pass the token touseServerSessionbelow and fetch a new one shortly before it expires. Exchanging the Firebase ID token or Supabase access token in the app instead (Game setup, identity) works without a backend, with client trust and caps; use one path per app, never both. -
The client module (
lib/orishare.ts):import * as Crypto from 'expo-crypto'; // or crypto.randomUUID() where available const API = 'https://api.orishare.com'; const PUBLISHABLE_KEY = process.env.EXPO_PUBLIC_ORISHARE_PUBLISHABLE_KEY!; // opk_, public const CONNECTION_ID = process.env.EXPO_PUBLIC_ORISHARE_CONNECTION_ID; // ic_, public let token: string | null = null; // memory only: not AsyncStorage or SecureStore // Without a backend only (client trust): exchange the provider token in the app. export async function exchange(providerToken: string) { const res = await fetch(`${API}/v1/customer_sessions`, { method: 'POST', headers: { Authorization: `Bearer ${PUBLISHABLE_KEY}`, 'Content-Type': 'application/json', 'Idempotency-Key': Crypto.randomUUID(), }, body: JSON.stringify({ grant_type: 'identity_token', connection_id: CONNECTION_ID, provider_token: providerToken, }), }); token = res.ok ? (await res.json()).customer_token : null; return token !== null; } export function useServerSession(serverToken: string) { token = serverToken; } export async function customer<T>( path: string, init: { method?: string; body?: unknown; key?: string } = {}, ): Promise<T> { const method = init.method ?? 'GET'; const res = await fetch(API + '/v1/customer/' + path, { method, headers: { Authorization: `Bearer ${PUBLISHABLE_KEY}`, 'X-Orishare-Customer-Token': token ?? '', 'Content-Type': 'application/json', ...(method !== 'GET' ? { 'Idempotency-Key': init.key ?? Crypto.randomUUID() } : {}), }, body: init.body === undefined ? undefined : JSON.stringify(init.body), }); if (res.status === 401) token = null; // expired: exchange again if (!res.ok) throw new Error(`orishare ${res.status}`); return res.json() as Promise<T>; } export const track = ( name: string, properties: Record<string, unknown> = {}, id = Crypto.randomUUID(), ) => customer('events', { method: 'POST', body: { id, name, properties } });Retry an intent with the same
keyand eventid, never a new one. -
What the app sends. Through your backend (server trust, no caps):
session.startedonce a day on open,level.completedandmatch.completed. With the Firebase kit that is theorishareEventscallable, with the Supabase function theeventsaction, each event with anoperation_idyou reuse on retry (session-<UTC day>,level-<n>); your own server sends them with the secret key (Web game, step 4). Only an app with no backend sends them itself withtrack, counted up to the per-day caps. -
Screens: Game setup, player screens. Players appear on the weekly board only after they opt in (
POST /v1/customer/leaderboard_profiles). Refresh them when the app returns to the foreground (AppState), not on a timer. -
Push. Get the native device token with
expo-notifications((await Notifications.getDevicePushTokenAsync()).data) and register it:customer('notification_devices', { method: 'POST', body: { kind: Platform.OS === 'ios' ? 'apns' : 'fcm', token, platform: Platform.OS } }). Which messages are sent: Game setup, notifications. Orishare sends no push until a person has claimed the project. -
Friends. Apply
/recipes/social.jsonand add the friends screens from Game setup, friends and social: share the friend code (a deep link or QR), requests, the friend list with each friend streak's flame andat_risk, a nudge button, the weekly friend quest and league friend standings. Friend streak days and friend quest progress are recorded by your backend with the secret key when a lesson or level is finished:orishareFriendProgress(Firebase kit) or thefriend_progressaction (Supabase function). -
Test the exact calls from a terminal against the test environment (Game setup, test), then in the simulator. Native requests send no
Originand need no allowed origin; Expo web does (Web game, step 7). -
Go live: Game setup, go live.
Godot
One prompt: XP, levels, coins, streaks, badges, quests, leaderboards, leagues and referrals in a Godot 4 game, with HTTPRequest and a customer session.
Roblox
One prompt: XP, levels, coins, streaks, badges, quests, leaderboards, leagues and referrals in a Roblox experience, from server scripts with HttpService.