skills/expo-workflow-expert/SKILL.md
Expo managed workflow expert for EAS Build, Submit, Update, config plugins, and custom dev clients. Activate on: Expo project, EAS Build, EAS Update, config plugin, expo-dev-client, Expo Router, Expo SDK 52, app.json configuration. NOT for: bare React Native (use react-native-architect), native module authoring (use react-native-architect), Flutter (use flutter-bloc-state-manager).
npx skillsauth add curiositech/windags-skills expo-workflow-expertInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Expert in the Expo managed workflow including EAS Build/Submit/Update, config plugins, custom dev clients, and Expo Router.
Activate on: "Expo project", "EAS Build", "EAS Submit", "EAS Update", "config plugin", "expo-dev-client", "Expo Router", "Expo SDK 52", "app.json config", "expo prebuild"
NOT for: Bare React Native → react-native-architect | Native module authoring → react-native-architect | Flutter → flutter-bloc-state-manager
npx create-expo-app@latest my-appnpx eas init and configure eas.json for build profilesnpx eas build --profile development for custom native builds| Domain | Technologies |
|--------|-------------|
| Build | EAS Build, local builds (npx expo run:ios/android), prebuild |
| Updates | EAS Update (OTA), update groups, channels, rollbacks |
| Submit | EAS Submit to App Store Connect and Google Play Console |
| Routing | Expo Router 4, file-based routing, API routes, typed routes |
| Config | Config plugins, app.json/app.config.ts, Expo Modules API |
{
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"ios": {
"simulator": true
}
},
"preview": {
"distribution": "internal",
"channel": "preview"
},
"production": {
"channel": "production",
"autoIncrement": true
}
},
"submit": {
"production": {
"ios": {
"appleId": "[email protected]",
"ascAppId": "123456789",
"appleTeamId": "ABCDE12345"
},
"android": {
"serviceAccountKeyPath": "./google-services.json",
"track": "internal"
}
}
}
}
Production Channel:
├─ Branch: production
├─ Update: JS-only changes ship instantly (no binary rebuild)
└─ Rollback: `eas update:rollback --channel production`
Preview Channel:
├─ Branch: staging
├─ Internal testers get latest changes
└─ QA before promoting to production
Flow:
Code change → Is it JS-only?
├─ YES → eas update --channel production --message "fix: ..."
│ (Users get update in < 1 minute, no store review)
└─ NO (native change) → eas build + eas submit
(Full store review cycle)
// plugins/withCustomSplash.ts
import { ConfigPlugin, withAndroidManifest } from 'expo/config-plugins';
const withCustomSplash: ConfigPlugin = (config) => {
return withAndroidManifest(config, async (modConfig) => {
const mainApplication = modConfig.modResults.manifest.application?.[0];
if (mainApplication) {
// Add custom meta-data to AndroidManifest.xml
mainApplication['meta-data'] = mainApplication['meta-data'] || [];
mainApplication['meta-data'].push({
$: {
'android:name': 'expo.modules.splashscreen.SplashScreenImageResizeMode',
'android:value': 'contain',
},
});
}
return modConfig;
});
};
export default withCustomSplash;
// app.config.ts — use the plugin
export default {
plugins: [
'./plugins/withCustomSplash',
['expo-camera', { cameraPermission: 'Allow camera for scanning' }],
],
};
expo eject when a config plugin would suffice. Since Expo SDK 50+, the "managed vs bare" distinction is gone; use npx expo prebuild with config plugins.expo-dev-client) for full-fidelity testing.app.config.ts for environment-specific bundle IDs, API URLs, and feature flags.[ ] app.config.ts used (not static app.json) for dynamic configuration
[ ] EAS Build configured with development, preview, and production profiles
[ ] EAS Update channels match build profiles
[ ] Development build created (not relying on Expo Go)
[ ] Config plugins used for native customization (no manual native edits)
[ ] Expo Router with typed routes enabled
[ ] Auto-increment build numbers in production profile
[ ] EAS Submit configured for both App Store and Google Play
[ ] OTA updates tested with preview channel before production
[ ] Rollback procedure documented and tested
[ ] Bundle size monitored (expo-optimize for image compression)
[ ] Expo SDK on latest stable version
tools
Building resilient distributed systems with circuit breakers, retries with full-jitter exponential backoff, retry budgets (per-request 3-attempt + per-client 10% ratio per Google SRE), deadline propagation, and the cascading-failure math (4 layers × 3 retries = 64x amplification). Grounded in Resilience4j, Microsoft Cloud Patterns, AWS Architecture Blog (Marc Brooker), and Google SRE Book.
testing
Designing HTTP cache headers that work correctly across browsers, CDNs, and shared proxies — `Cache-Control` directives per RFC 9111, `stale-while-revalidate` and `stale-if-error` per RFC 5861, the Vary header for varying responses, and surrogate keys for tag-based purging. Grounded in IETF RFCs and Cloudflare/Fastly docs.
development
Use when designing or fixing a Content Security Policy on a real site, choosing between nonce-based and hash-based CSP, adding strict-dynamic, debugging "Refused to execute inline script" errors, deploying CSP in report-only mode first, configuring report-to / report-uri, or auditing an existing policy for unsafe-inline / unsafe-eval / wildcards. Triggers: "CSP blocks legitimate inline script", strict-dynamic, nonce-{RANDOM}, sha256-{HASH}, object-src none, base-uri none, frame-ancestors, Trusted Types, X-Content-Security-Policy obsolete, report-only vs enforced. NOT for general HTTP security headers (HSTS, COOP/COEP), Trusted Types deep dive, CORS configuration, or building a WAF.
tools
Choosing and operating an HTTP API versioning strategy that doesn't break clients — Stripe's date-based pinned versions, the Deprecation/Sunset header pair (RFC 9745 + RFC 8594), URI vs header vs media-type approaches, and the version-transformer pattern. Grounded in Stripe's published architecture and IETF RFCs.