Scaffold
Skill Shankulkarni/react-native-ai-plugin/plugins/rn-ai/skills/scaffold
Write better React Native code from day one - opinionated Claude Code rules, New Architecture ready.
npx -y skills add Shankulkarni/react-native-ai-plugin --skill scaffoldAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when creating a new React Native app from scratch -- Expo SDK 52+ managed workflow, NativeWind v4, Expo Router, React Query, zustand-x, EAS config, ESLint/Prettier/Husky.
SKILL.md
5.9 KB, ~1.7k tokens by cl100k_base, as published. Nobody here has run it
App Scaffolding
Stack
Expo SDK 52+ (managed), Expo Router v4, NativeWind v4, React Query, axios, react-hook-form + zod v4, zustand-x, Reanimated v3, Gesture Handler v2, MMKV, expo-secure-store, EAS.
Before You Start
Gather from user:
- App name (display name + slug)
- Bundle ID (e.g.
com.myorg.myapp) - API base URL (or "set up later")
- Auth type (email/password, OAuth, magic link, or none)
- Tab structure (main tabs of the app)
Step 1: Create Expo App
bunx create-expo-app@latest MyApp --template blank-typescript
cd MyApp
Step 2: Install Core Dependencies
bunx expo install expo-router react-native-safe-area-context react-native-screens expo-linking expo-constants expo-status-bar
bunx expo install nativewind react-native-reanimated react-native-gesture-handler
bun add tailwindcss@^3.4.0
bunx expo install @tanstack/react-query axios
bunx expo install react-hook-form @hookform/resolvers zod zod-empty
bunx expo install expo-secure-store react-native-mmkv
bunx expo install expo-image
bun add zustand-x mutative
Note: Install
tailwindcssseparately withbun add tailwindcss@^3.4.0— do NOT usebunx expo install tailwindcssas it resolves Tailwind v4 which NativeWind v4 does not support. NativeWind v4 requires Tailwind CSS v3.
Step 3: app.json
{
"expo": {
"name": "MyApp",
"slug": "my-app",
"version": "1.0.0",
"scheme": "myapp",
"newArchEnabled": true,
"ios": {
"supportsTablet": true,
"bundleIdentifier": "com.myorg.myapp"
},
"android": {
"adaptiveIcon": { "foregroundImage": "./assets/adaptive-icon.png" },
"package": "com.myorg.myapp"
},
"plugins": [
"expo-router",
"expo-secure-store"
]
}
}
Step 4: NativeWind v4 Setup
tailwind.config.js:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./app/**/*.{js,jsx,ts,tsx}', './src/**/*.{js,jsx,ts,tsx}'],
presets: [require('nativewind/preset')],
theme: {
extend: {
colors: {
primary: '#6366f1',
background: '#ffffff',
},
},
},
}
global.css:
@tailwind base;
@tailwind components;
@tailwind utilities;
metro.config.js:
const { getDefaultConfig } = require('expo/metro-config')
const { withNativeWind } = require('nativewind/metro')
const config = getDefaultConfig(__dirname)
module.exports = withNativeWind(config, { input: './global.css' })
babel.config.js:
module.exports = function (api) {
api.cache(true)
return {
presets: [
['babel-preset-expo', { jsxImportSource: 'nativewind' }],
'nativewind/babel',
],
}
}
Step 5: Folder Structure
app/
├── (auth)/
│ ├── _layout.tsx
│ ├── login.tsx
│ └── register.tsx
├── (app)/
│ ├── _layout.tsx
│ └── (tabs)/
│ ├── _layout.tsx
│ └── index.tsx
├── _layout.tsx
└── +not-found.tsx
src/
├── api/
├── components/
│ ├── ui/
│ └── app/
├── hooks/
├── stores/
├── libs/
│ ├── cn.ts
│ ├── query-client.ts
│ └── axios.ts
└── types/
Step 6: Core Libs
src/libs/cn.ts:
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) }
src/libs/query-client.ts:
import { QueryClient } from '@tanstack/react-query'
export const queryClient = new QueryClient({
defaultOptions: {
queries: { staleTime: Infinity, gcTime: Infinity, retry: false, refetchOnMount: false, refetchOnWindowFocus: false },
mutations: { retry: false },
},
})
src/libs/axios.ts:
import axios from 'axios'
export const api = axios.create({
baseURL: process.env.EXPO_PUBLIC_API_URL,
timeout: 30_000,
})
// Add auth interceptor: attach token from SecureStore
Step 7: Root Layout (app/_layout.tsx)
import '../global.css'
import { QueryClientProvider } from '@tanstack/react-query'
import { Stack } from 'expo-router'
import { queryClient } from '@/libs/query-client'
export default function RootLayout() {
return (
<QueryClientProvider client={queryClient}>
<Stack screenOptions={{ headerShown: false }} />
</QueryClientProvider>
)
}
Step 8: EAS
bun add -D eas-cli
bunx eas init
bunx eas build:configure
eas.json:
{
"cli": { "version": ">= 12.0.0" },
"build": {
"development": { "developmentClient": true, "distribution": "internal" },
"preview": { "distribution": "internal" },
"production": { "autoIncrement": true }
},
"submit": {
"production": {}
}
}
Step 9: ESLint + Prettier + Husky
bun add -D eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser prettier husky lint-staged
bunx husky init
eslint.config.js:
import tsPlugin from '@typescript-eslint/eslint-plugin'
import tsParser from '@typescript-eslint/parser'
export default [
{ files: ['src/**/*.{ts,tsx}', 'app/**/*.{ts,tsx}'], languageOptions: { parser: tsParser },
plugins: { '@typescript-eslint': tsPlugin },
rules: { '@typescript-eslint/no-explicit-any': 'error', 'no-console': 'error' } },
]
.prettierrc:
{ "singleQuote": true, "semi": false, "trailingComma": "all", "useTabs": true }
.husky/pre-commit:
bun run typecheck && bun run lint
Post-Scaffold Checklist
-
bun run typecheckpasses -
bunx expo startopens in Expo Go -
newArchEnabled: trueinapp.json -
(auth)/and(app)/layouts created -
.env.localwithEXPO_PUBLIC_API_URL(never committed)
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.