# Mobile Expo

> React Native + Expo + Supabase + EAS conventions. Loaded automatically when building a mobile app.

- **Type:** Skill
- **Install:** `agentstack add skill-sso-ss-vibe-ship-it-mobile-expo`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [sso-ss](https://agentstack.voostack.com/s/sso-ss)
- **Installs:** 0
- **Category:** [Databases](https://agentstack.voostack.com/c/databases)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [sso-ss](https://github.com/sso-ss)
- **Source:** https://github.com/sso-ss/vibe-ship-it/tree/main/template/skills/platforms/mobile-expo
- **Website:** https://vibe-ship-it.vercel.app/

## Install

```sh
agentstack add skill-sso-ss-vibe-ship-it-mobile-expo
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Mobile Platform: React Native + Expo

The default mobile stack. React Native + Expo + Supabase + EAS Build.

## Project Structure

Explain to the designer as:
> "Your app is organized into folders. Think of each folder as a room with a specific purpose."

```
app/                      ← Screens (each file = a screen in your app)
  (tabs)/                 ← Tab bar screens
    index.tsx             ← First tab (Home)
    explore.tsx           ← Second tab
    _layout.tsx           ← Tab bar configuration
  _layout.tsx             ← Root layout (wraps everything)
  +not-found.tsx          ← Screen shown when navigating to missing route
components/               ← Reusable pieces (buttons, cards, headers)
constants/                ← Colors, sizes, config values
hooks/                    ← Shared logic
utils/
  supabase.ts             ← Database connection
assets/
  images/                 ← App images
  fonts/                  ← Custom fonts
app.json                  ← App name, icon, splash screen, permissions
.env                      ← Secret settings (database keys)
```

## Key Conventions

### No HTML — Use React Native Components

Mobile apps don't use HTML. Map web concepts to mobile:

| Web (HTML) | Mobile (React Native) | Notes |
|---|---|---|
| `` | `` | Container — like a box |
| ``, `` | `` | All text MUST be in `` |
| `` | `` | Images |
| `` | `` | Tappable areas |
| `` | `` | Text fields |
| `` + `` | `` | Scrollable lists |
| `` | `` (from expo-router) | Navigation |
| CSS classes | `StyleSheet` or inline styles | No Tailwind by default |

### Styling

No Tailwind in mobile. Use StyleSheet:

```tsx
import { StyleSheet, View, Text } from 'react-native'

export default function HomeScreen() {
  return (
    
      Welcome
    
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 24,
    backgroundColor: '#fff',
  },
  title: {
    fontSize: 32,
    fontWeight: '700',
    color: '#111',
  },
})
```

Alternatively, install NativeWind for Tailwind-like classes:
```bash
npx expo install nativewind tailwindcss
```

Then you can use: `Welcome`

### Navigation (Expo Router)

Works like Next.js — file-based routing:
- `app/index.tsx` → Home screen
- `app/profile.tsx` → Profile screen
- `app/(tabs)/` → Tab bar navigation
- `app/[id].tsx` → Dynamic screen (e.g., product detail)

Navigate between screens:
```tsx
import { Link } from 'expo-router'

Go to Profile
```

Or programmatically:
```tsx
import { router } from 'expo-router'

router.push('/profile')
```

### No Server Actions

Mobile apps run entirely on the device. There's no server. Everything talks to Supabase directly:

```tsx
import { supabase } from '@/utils/supabase'

// Fetch data
const { data } = await supabase.from('bookings').select('*')

// Save data
await supabase.from('bookings').insert({ name, email, date })
```

### Images

```tsx
import { Image } from 'react-native'

// Local image

// Remote image (from Supabase Storage, etc.)

```

### Environment Variables

Create `.env` in project root:
```
EXPO_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
EXPO_PUBLIC_SUPABASE_ANON_KEY=eyJ...
```

- `EXPO_PUBLIC_` prefix = accessible in app code
- Access with `process.env.EXPO_PUBLIC_SUPABASE_URL`

## Common Commands

| Command | What it does |
|---|---|
| `npx expo start` | Start dev server (scan QR with phone to preview) |
| `npx expo start --ios` | Open in iPhone simulator |
| `npx expo start --android` | Open in Android emulator |
| `eas build --platform ios` | Build for App Store |
| `eas build --platform android` | Build for Play Store |
| `eas submit` | Submit to App Store / Play Store |

## Prerequisites

The designer needs:
1. **Expo Go app** on their phone (free, from App Store / Play Store) — for live preview
2. **Expo account** (free) — `npx expo login`
3. For publishing: **Apple Developer** ($99/year) or **Google Play Developer** ($25 one-time)

> "Download the Expo Go app on your phone. That's how you'll preview your app while we build."

## Packages to Install as Needed

| When | Package | Install |
|---|---|---|
| Database/Auth/Storage | Supabase | `npx expo install @supabase/supabase-js` |
| Secure token storage | SecureStore | `npx expo install expo-secure-store` |
| Image picker | ImagePicker | `npx expo install expo-image-picker` |
| Camera | Camera | `npx expo install expo-camera` |
| Icons | Expo Vector Icons | Built-in with Expo |
| Animations | Reanimated | `npx expo install react-native-reanimated` |
| Tailwind-like styling | NativeWind | `npx expo install nativewind tailwindcss` |

Use `npx expo install` instead of `npm install` — it picks compatible versions.

## Supabase Setup (One Time)

Same as web:
1. Go to supabase.com and create a free project
2. Go to Settings → API
3. Copy the URL and anon key
4. Create `.env` with those values

## Supabase Client

```typescript
// utils/supabase.ts
import 'react-native-url-polyfill/auto'
import { createClient } from '@supabase/supabase-js'
import * as SecureStore from 'expo-secure-store'

const ExpoSecureStoreAdapter = {
  getItem: (key: string) => SecureStore.getItemAsync(key),
  setItem: (key: string, value: string) => SecureStore.setItemAsync(key, value),
  removeItem: (key: string) => SecureStore.deleteItemAsync(key),
}

export const supabase = createClient(
  process.env.EXPO_PUBLIC_SUPABASE_URL!,
  process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY!,
  {
    auth: {
      storage: ExpoSecureStoreAdapter,
      autoRefreshToken: true,
      persistSession: true,
      detectSessionInUrl: false,
    },
  }
)
```

## Limitations vs Web

Tell the designer upfront:
- "Phone apps take longer to publish — Apple reviews apps, which can take a day or two"
- "You can test instantly on your phone though, using Expo Go"
- "Emails can't be sent from the app directly — we'd use a server function or Supabase Edge Function for that"

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [sso-ss](https://github.com/sso-ss)
- **Source:** [sso-ss/vibe-ship-it](https://github.com/sso-ss/vibe-ship-it)
- **License:** MIT
- **Homepage:** https://vibe-ship-it.vercel.app/

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-sso-ss-vibe-ship-it-mobile-expo
- Seller: https://agentstack.voostack.com/s/sso-ss
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
