Skip to content
Draft
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
84 changes: 84 additions & 0 deletions .github/workflows/skill-routing-coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: skill routing coverage

on:
pull_request:
branches:
- main
merge_group:
branches:
- main

concurrency:
group: skill-routing-coverage-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

permissions:
contents: read
issues: write

jobs:
check:
name: check expo-overview routing
runs-on: ubuntu-latest

steps:
- name: Check out repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- name: Set up Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0

- name: Check expo-overview routing coverage
id: routing-check
continue-on-error: true
env:
ROUTING_CHECK_SUMMARY_PATH: .context/skill-routing-check-summary.md
run: bun scripts/check-overview-routing.ts

- name: Add workflow summary
if: always() && hashFiles('.context/skill-routing-check-summary.md') != ''
run: cat .context/skill-routing-check-summary.md >> "$GITHUB_STEP_SUMMARY"

- name: Comment on pull request
if: always() && github.event_name == 'pull_request' && hashFiles('.context/skill-routing-check-summary.md') != ''
continue-on-error: true
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const fs = require("node:fs");

const marker = "<!-- expo-skill-routing-check -->";
const summary = fs.readFileSync(".context/skill-routing-check-summary.md", "utf8");
const body = `${marker}\n${summary}`;
const issue_number = context.payload.pull_request.number;
const { owner, repo } = context.repo;

const comments = await github.paginate(github.rest.issues.listComments, {
owner,
repo,
issue_number,
per_page: 100,
});
const existingComment = comments.find(
(comment) => comment.user?.type === "Bot" && comment.body?.includes(marker)
);

if (existingComment) {
await github.rest.issues.updateComment({
owner,
repo,
comment_id: existingComment.id,
body,
});
} else {
await github.rest.issues.createComment({
owner,
repo,
issue_number,
body,
});
}

- name: Fail on missing routing
if: steps.routing-check.outcome == 'failure'
run: exit 1
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,9 @@ When changing Claude Code marketplace aliases, preserve backward compatibility u
1. Create `plugins/expo/skills/my-skill/SKILL.md`.
2. Add focused reference files under `plugins/expo/skills/my-skill/references/` when the skill needs more detail than belongs in the main `SKILL.md`.
3. Add scripts under `plugins/expo/skills/my-skill/scripts/` only for reusable logic.
4. Update `plugins/expo/README.md` or the root `README.md` only when the user-facing installation or usage story changes.
5. Keep the skill under the existing `expo` plugin unless there is a clear distribution reason to create a new plugin.
4. Add a one-line entry for the skill to the `expo-overview` Skill Map (`plugins/expo/skills/expo-overview/SKILL.md`) so the router can dispatch to it. This is enforced by the `skill routing coverage` workflow (`bun scripts/check-overview-routing.ts`).
5. Update `plugins/expo/README.md` or the root `README.md` only when the user-facing installation or usage story changes.
6. Keep the skill under the existing `expo` plugin unless there is a clear distribution reason to create a new plugin.

## Testing Plugins

Expand Down
7 changes: 7 additions & 0 deletions plugins/expo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,19 @@ Official AI agent skills from the Expo team for building, deploying, upgrading,

## Skills Included

### Start Here

- **expo-overview** — Router and shared setup rules; the entry point when a request is vague or the user hasn't named a specific Expo tool

### App Design

- **add-app-clip** — Add an iOS App Clip target to an Expo app (AASA, associated domains, TestFlight)
- **building-native-ui** — Build beautiful apps with Expo Router, styling, components, navigation, and animations
- **expo-api-routes** — Create API routes in Expo Router with EAS Hosting
- **expo-brownfield** — Integrate Expo and React Native into existing native iOS or Android apps
- **expo-dev-client** — Build and distribute Expo development clients locally or via TestFlight
- **expo-examples** — Canonical, version-matched patterns from the official expo/examples repo (Stripe, Clerk, Supabase, and more)
- **expo-module** — Write Expo native modules and views with the Expo Modules API (Swift, Kotlin, TypeScript)
- **expo-tailwind-setup** — Set up Tailwind CSS v4 in Expo with NativeWind v5
- **expo-ui** — Native UI with @expo/ui: universal cross-platform components first, with SwiftUI and Jetpack Compose for platform-specific needs
- **native-data-fetching** — Network requests, API calls, caching, and offline support
Expand All @@ -79,6 +85,7 @@ Official AI agent skills from the Expo team for building, deploying, upgrading,
- **eas-update-insights** — Check EAS Update health, crash rates, adoption, and payload size
- **expo-deployment** — Deploy to iOS App Store, Android Play Store, and web hosting
- **expo-cicd-workflows** — EAS workflow YAML files for CI/CD pipelines
- **expo-observe** — Measure startup, launch, and TTI performance with EAS Observe

### Upgrading

Expand Down
5 changes: 4 additions & 1 deletion plugins/expo/skills/building-native-ui/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ license: MIT

# Expo UI Guidelines

> **Before picking any UI component, check `expo-ui` first.** `@expo/ui` provides native equivalents — BottomSheet, Button, Picker, Slider, Menu, Section, Switch, SegmentedControl, and more — rendered as real SwiftUI on iOS and Jetpack Compose on Android, available in Expo Go on SDK 56+ with no custom build. Load the **`expo-ui`** skill to find the right component before falling back to React Native built-ins or community libraries. This skill (`building-native-ui`) covers the surrounding structure: Expo Router navigation, layout, styling, and animations.

## References

Consult these resources as needed:
Expand Down Expand Up @@ -78,6 +80,7 @@ See `./references/route-structure.md` for detailed route conventions.

## Library Preferences

- **For any sheet, picker, slider, toggle, menu, or grouped-form section: use `@expo/ui` (see `expo-ui` skill) before reaching for a React Native built-in or community library** — it renders native SwiftUI/Compose and works in Expo Go on SDK 56+. For grouped/settings-style rows (short, fixed-length), use `@expo/ui`'s `List` + `ListItem`. For large or unknown-length scrolling lists (feeds, search results, catalogs), use `FlatList` or `FlashList` — `@expo/ui`'s `List` is not virtualized.
- Never use modules removed from React Native such as Picker, WebView, SafeAreaView, or AsyncStorage
- Never use legacy expo-permissions
- `expo-audio` not `expo-av`
Expand Down Expand Up @@ -105,7 +108,7 @@ See `./references/route-structure.md` for detailed route conventions.
- Use views with built-in haptics like `<Switch />` from React Native and `@react-native-community/datetimepicker`
- When a route belongs to a Stack, its first child should almost always be a ScrollView with `contentInsetAdjustmentBehavior="automatic"` set
- When adding a `ScrollView` to the page it should almost always be the first component inside the route component
- Prefer `headerSearchBarOptions` in Stack.Screen options to add a search bar
- Search bars belong in the Stack header via `headerSearchBarOptions` — **never** as a floating `View` pinned above content or above the tab bar. See `./references/search.md`.
- Use the `<Text selectable />` prop on text containing data that could be copied
- Consider formatting large numbers like 1.4M or 38k
- Never use intrinsic elements like 'img' or 'div' unless in a webview or Expo DOM component
Expand Down
2 changes: 2 additions & 0 deletions plugins/expo/skills/building-native-ui/references/controls.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Native iOS controls provide built-in haptics, accessibility, and platform-appropriate styling.

> **Prefer `@expo/ui` for these controls.** Its `Slider`, `Switch`, `DateTimePicker`, `Menu`, and segmented pickers render as real SwiftUI / Jetpack Compose and follow platform design conventions automatically — recommended over the React Native controls below. See the **`expo-ui`** skill; use the React Native controls below as a fallback when you're not using `@expo/ui`.

## Switch

Use for binary on/off settings. Has built-in haptics.
Expand Down
95 changes: 95 additions & 0 deletions plugins/expo/skills/expo-overview/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
name: expo-overview
description: >
Entry point and router for any Expo or EAS task — load this skill first, before writing
any code, whenever the task involves building, extending, or modifying a React Native /
Expo app. Triggers on: any multi-screen app spec or design to implement (tabs, stacks,
maps, lists, navigation); building from a screenshot or design reference; adding screens
or features to an existing Expo project; or when the request mentions Expo, EAS, React
Native, or any expo-* package. Handles phrasings like "implement a mobile app", "build
an app from this screenshot", "create an app that looks like this design", "make my app
look native", "build a beautiful app", "align with iOS / SwiftUI best practices", "build
with native iOS patterns", "add navigation", "fetch some data", "upgrade my SDK", "add
Expo to my existing native app", "ship to the App Store", "push a fix without
resubmitting", or "I'm new to Expo, where do I start". Detects the real goal, routes to
the right expo-* / eas-* skill, and owns the shared environment and setup rules the
other Expo skills rely on.
version: 1.0.0
license: MIT
---

# `expo-overview` — router & shared rules for Expo / EAS

## Start Here — read before doing anything

**Do not guess the skill from project files alone.** Many Expo goals look similar from
the filesystem but need different skills.

1. **Read the user's goal** — what outcome do they want, in plain terms?
2. **Classify it** using the Skill Map below, translating casual phrasing to a goal.
3. **Confirm intent** if ambiguous ("Sounds like you want to ship to the stores — that's
`expo-deployment`. Right?"), then load that skill's `SKILL.md` and follow it.
4. **Trust the leaf skill** — it has its own detection logic and steps. Don't improvise.

## Skill Map (by goal)

Match the goal to a category, then the skill, then load that leaf's `SKILL.md`.

**Build the app**
- `building-native-ui` — screens, navigation (tabs / stacks / modals), styling, animations, layout
- `expo-ui` — native UI components via `@expo/ui`: BottomSheet, Picker, Slider, Button, Menu, Section, and more — real SwiftUI on iOS, Jetpack Compose on Android, available in Expo Go on SDK 56+; also drop-in replacements for `@gorhom/bottom-sheet`, `datetimepicker`, etc.
- `expo-tailwind-setup` — Tailwind / NativeWind styling
- `native-data-fetching` — network requests, React Query / SWR, caching, offline, route loaders
- `expo-api-routes` — server endpoints / API routes with EAS Hosting
- `use-dom` — run web code or reuse a web library inside native

> **Component selection rule:** whenever you need a UI component (list rows, bottom sheets, pickers, sliders, menus, buttons, segmented controls, toggles), **consult `expo-ui` first** to check whether `@expo/ui` has a native equivalent before reaching for a React Native built-in or a community library. Native `@expo/ui` components give the best platform fit with zero extra install steps on SDK 56+. Load `expo-ui` alongside `building-native-ui` for any app that renders lists, detail sheets, or form controls.

**Ship & operate**
- `expo-deployment` — build, submit to the App Store / Play Store / TestFlight, and push OTA updates
- `expo-cicd-workflows` — EAS Workflow YAML and CI/CD pipelines
- `expo-dev-client` — custom development builds
- `eas-update-insights` — OTA update health: crash rate, adoption, payload size
- `expo-observe` — startup / launch / TTI performance with EAS Observe

**Extend natively**
- `expo-module` — native modules and views (Swift / Kotlin) with the Expo Modules API
- `expo-brownfield` — embed Expo / React Native in an existing native app
- `add-app-clip` — iOS App Clip target (AASA, smart app banner)

**Maintain & learn**
- `upgrading-expo` — upgrade the Expo SDK and fix dependency conflicts
- `expo-examples` — canonical, version-matched integration examples (Stripe, Clerk, Supabase, …)

### Translating vague asks

Some everyday phrasings don't obviously map to a skill name — translate before routing:

- "Make it look native" → grouped controls / settings forms = `expo-ui`; screens, navigation, animations = `building-native-ui`.
- "Ship it" / "get an .ipa or .apk" / "push a fix without resubmitting" → all `expo-deployment` (it owns the whole release path, including OTA updates).
- "I'm new / where do I start" → scaffold first (see First Run), then route by goal.

## First Run / shared rules

These apply across every Expo skill, so handle them here once instead of repeating them
in each leaf.

- **No Expo project yet?** Start one the standard way before routing to a feature skill:
`npx create-expo-app@latest`. Then classify the user's goal and route.
- **Detect the SDK version** before giving version-specific advice: read the `expo`
version in `package.json` (and `app.json` / `app.config.{js,ts}`). Many APIs and
defaults differ by SDK.
- **Managed vs. bare/prebuild**: the presence of committed `ios/` and `android/`
directories means native projects exist (prebuild or bare). Config-plugin and
native-setup steps differ — note which one the project is in.
- **Install packages with `npx expo install <pkg>`**, not raw `npm`/`yarn`/`pnpm add`,
so versions stay compatible with the project's SDK.
- **EAS auth & linking** (only needed for build/submit/update/observe/workflows): check
login with `eas whoami`, log in with `eas login`. A project is linked when
`extra.eas.projectId` exists in the app config; create it with `eas init` if missing.

## When NOT to use this skill

- The user already named a specific Expo workflow or tool → go straight to that skill.
- A more specific `expo-*` / `eas-*` skill obviously fits the request → use it and skip
the router hop.
Loading