Skip to Content
AIOverview

AI

NativeExpress includes three AI features: a streaming chat, an image generation studio, and an object scanner. All three talk to OpenRouter  through Supabase Edge Functions, using the Vercel AI SDK .

Prerequisites

Complete the Supabase project setup, set your edge function secrets, and deploy the functions.

Set OPENROUTER_API_KEY as a Supabase function secret before using AI features. A missing key returns provider_not_configured when a request reaches the provider setup.

How it works

Every AI feature is built the same way:

The provider key is kept only in Supabase function secrets, never in your app bundle or on the device. The client sends a Supabase access token, and the function derives the user from it rather than trusting a user id in the request body.

Before a function sends anything to OpenRouter, it checks that the user has allowed it, and refuses with ai_consent_required otherwise. The App Store requires that permission. See AI consent.

FeatureFunctionClient entry point
Chatsupabase/functions/chatsrc/features/chat/chatTransport.ts
Image generationsupabase/functions/generatesrc/features/create/generateImage.ts
Scansupabase/functions/identifysrc/features/scan/hooks/scans.ts

Each feature is an independent directory under src/features/, with its own screens, components, hooks and repository. Remove the ones your app does not need with yarn remove:feature; see Removing features and integrations.

Where data is stored

TableHolds
threadsOne row per conversation: owner, model, title, updated_at
messagesOne row per message: thread_id, role, and parts as JSON
generationsOne row per generated image: prompt, model, style, aspect ratio, image_path
scansOne row per scan: image_path and the structured result JSON

All four have owner-scoped row-level security: a user can only read and write their own rows.

Images are stored in a private Supabase Storage bucket called chat-media, under {userId}/…, and its policies scope each signed-in user to objects under their own prefix. Rows store the stable object path rather than a signed URL, because signed URLs expire, and the app signs the path on demand for display.

Configuration

Each feature’s models and presets are set in its own edge function’s config.json, and the app reads the same file through src/features/<feature>/config.ts:

FeatureFileHolds
Chatsupabase/functions/chat/config.jsonThe model list for the picker. See Models
Image generationsupabase/functions/generate/config.jsongenerateModel, style presets and aspect ratios
Scansupabase/functions/identify/config.jsonidentifyModel

The two settings every AI function shares, freeMessagesPerMonth and the AI consent version consentVersion, are in supabase/functions/_utils/ai.config.json. config.js exposes them to the app:

config.js
ai: require('./supabase/functions/_utils/ai.config.json'),

Redeploy the affected functions after editing any of these files. The AI_FREE_MESSAGES secret overrides freeMessagesPerMonth on the server, so keep the two in sync. See Models and Quota and paywall.

In this section

Last updated on