本文へ移動
cccskills
無料GitHub で公開

rn-conventions

React Native project structure, Expo vs bare workflow detection, app.json/app.config.js patterns, asset handling, fonts, styling approaches, hot-reload-friendly idioms. Use this skill to: - Detect Expo (managed/dev-client/EAS/ejected) vs bare RN workflow. - Pick correct project layout for each workflow. - Configure app.json / app.config.js with bundle ID, splash, icons, deep link schemes. - Handle assets, fonts, images correctly. - Pick a styling approach (StyleSheet / NativeWind / restyle / styled-components). Do NOT use this skill for: - Platform-specific branching (see rn-platform-specific). - Navigation (see rn-navigation). - Storage (see rn-state-and-storage). - Testing (see rn-testing).

インストール方法を見る

含まれるファイル(1)

  • SKILL.md10.5 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

React Native Conventions

Workflow detection

MarkerWorkflow
expo in deps + app.json / app.config.{js,ts} + NO ios/ android/Expo managed
expo + expo-dev-client in depsExpo dev-client (custom native code via prebuild)
eas.json presentEAS Build (managed or dev-client built in cloud)
expo in deps + ios/ + android/ foldersExpo ejected (treat as bare for native code)
No expo, ios/ + android/ foldersBare RN (React Native CLI)

Detection precedence: ejected/bare overrides managed if native folders exist.

For new RN projects in 2024+, Expo is the default. Bare projects are typically:

  • Legacy projects predating Expo SDK 49.
  • Projects with custom native modules that must be in source (rare with config plugins).
  • Apps with complex native integrations (CarPlay, Apple Watch, Wear OS).

Project layouts

Expo Router (modern, file-based)

project-root/
├── app.json                       # OR app.config.{js,ts} for dynamic config
├── package.json
├── tsconfig.json
├── babel.config.js                # plugins: ['babel-plugin-module-resolver', etc.]
├── metro.config.js                # bundler config (optional)
├── eas.json                       # if using EAS Build
├── app/                           # Expo Router root
│   ├── _layout.tsx                # root layout (always)
│   ├── index.tsx                  # / (home)
│   ├── +not-found.tsx             # 404
│   ├── (auth)/                    # group (parens hide from URL)
│   │   ├── _layout.tsx            # auth stack
│   │   ├── login.tsx
│   │   └── signup.tsx
│   ├── (app)/                     # authenticated app group
│   │   ├── _layout.tsx            # tabs/drawer
│   │   ├── index.tsx              # /
│   │   ├── profile.tsx
│   │   └── [id].tsx               # dynamic
│   └── _root.tsx                  # SafeAreaProvider, theme provider, etc.
├── components/
│   ├── ui/                        # Button, Input, Card primitives
│   └── features/
├── hooks/
├── lib/
├── assets/
│   ├── icons/
│   ├── images/
│   └── fonts/
└── __tests__/                     # OR colocated *.test.tsx

React Navigation (classical, modular routes)

project-root/
├── app.json
├── package.json
├── tsconfig.json
├── App.tsx                        # entry: NavigationContainer + RootNavigator
├── src/
│   ├── navigation/
│   │   ├── RootNavigator.tsx      # Auth/App switch
│   │   ├── AuthNavigator.tsx
│   │   ├── AppNavigator.tsx       # tabs/drawer
│   │   └── types.ts               # ParamList types
│   ├── screens/
│   │   ├── LoginScreen.tsx
│   │   ├── HomeScreen.tsx
│   │   └── ProfileScreen.tsx
│   ├── components/
│   ├── hooks/
│   ├── lib/
│   └── assets/
└── __tests__/

Bare workflow additions

Bare RN projects also have:

  • ios/ — Xcode project, Info.plist, Podfile.
  • android/ — Gradle project, AndroidManifest.xml, build.gradle.
  • index.js (root entry registering the app via AppRegistry.registerComponent).

For Expo managed, all native config flows through app.json/app.config.js. For bare, edit native files directly.

app.json / app.config.js

Static (app.json):

{
  "expo": {
    "name": "MyApp",
    "slug": "my-app",
    "version": "1.0.0",
    "orientation": "portrait",
    "icon": "./assets/icon.png",
    "splash": {
      "image": "./assets/splash.png",
      "resizeMode": "contain",
      "backgroundColor": "#ffffff"
    },
    "scheme": "myapp",
    "ios": {
      "bundleIdentifier": "com.example.myapp",
      "supportsTablet": true,
      "infoPlist": {
        "NSCameraUsageDescription": "Allow $(PRODUCT_NAME) to access your camera"
      }
    },
    "android": {
      "package": "com.example.myapp",
      "permissions": ["CAMERA"],
      "adaptiveIcon": {
        "foregroundImage": "./assets/adaptive-icon.png",
        "backgroundColor": "#ffffff"
      }
    },
    "plugins": [
      "expo-router",
      ["expo-camera", { "cameraPermission": "Allow $(PRODUCT_NAME) to access your camera" }]
    ],
    "extra": {
      "eas": { "projectId": "..." }
    }
  }
}

Dynamic (app.config.js):

export default ({ config }) => ({
  ...config,
  name: process.env.APP_VARIANT === 'dev' ? 'MyApp (Dev)' : 'MyApp',
  ios: {
    ...config.ios,
    bundleIdentifier: process.env.APP_VARIANT === 'dev' ? 'com.example.myapp.dev' : 'com.example.myapp',
  },
});

Use dynamic config for env-aware bundle IDs (dev vs prod), feature flags, etc.

Common app.config.js patterns

  • Multiple variants (dev/staging/prod) via env vars.
  • Config plugins to inject native changes without ejecting:
plugins: [
  ['expo-build-properties', { ios: { useFrameworks: 'static' }, android: { kotlinVersion: '1.9.0' } }],
  ['./plugins/withCustomManifest', { /* options */ }],
]
  • Read from .env via expo-constants:
import Constants from 'expo-constants';
const apiUrl = Constants.expoConfig?.extra?.apiUrl;

Asset handling

Images

import { Image } from 'react-native';
import { Image as ExpoImage } from 'expo-image';

// Static, bundled with app
<Image source={require('./assets/logo.png')} style={{ width: 100, height: 100 }} />

// Remote
<Image source={{ uri: 'https://example.com/photo.jpg' }} style={{ width: 100, height: 100 }} />

// Expo Image — better caching, faster decode, supports placeholders
<ExpoImage
  source={require('./assets/logo.png')}
  contentFit="cover"
  transition={300}
  placeholder={blurhash}
/>

For multiple resolutions: name files logo.png, logo@2x.png, logo@3x.png — RN bundler picks based on screen density.

Fonts

Expo:

import { useFonts } from 'expo-font';

export default function Layout() {
  const [loaded] = useFonts({
    'Inter-Regular': require('./assets/fonts/Inter-Regular.ttf'),
    'Inter-Bold': require('./assets/fonts/Inter-Bold.ttf'),
  });
  if (!loaded) return null;
  return <App />;
}

Pair with expo-splash-screen to prevent FOUC:

import * as SplashScreen from 'expo-splash-screen';
SplashScreen.preventAutoHideAsync();

const [loaded] = useFonts({...});
useEffect(() => { if (loaded) SplashScreen.hideAsync(); }, [loaded]);

Bare: link via react-native-asset or manually in Xcode/Android Studio.

Vector icons

import { Ionicons, MaterialIcons, Feather } from '@expo/vector-icons';
<Ionicons name="home" size={24} color="black" />

Bare projects: install react-native-vector-icons, link manually.

Styling approaches

StyleSheet.create (default, fastest)

const styles = StyleSheet.create({
  container: { flex: 1, padding: 16 },
  title: { fontSize: 18, fontWeight: '600' },
});

<View style={styles.container}>
  <Text style={styles.title}>Hi</Text>
</View>

StyleSheet.create returns numeric IDs for style references — slightly more performant than inline objects on first render (deduplicates).

NativeWind (Tailwind for RN)

import { View, Text } from 'react-native';
<View className="flex-1 p-4">
  <Text className="text-lg font-semibold">Hi</Text>
</View>

Install: pnpm add nativewind tailwindcss. Configure tailwind.config.js and babel.config.js.

restyle (Shopify, theme-driven)

import { Box, Text } from '@theme';
<Box flex={1} padding="m">
  <Text variant="header">Hi</Text>
</Box>

Best for design-system-heavy apps.

styled-components/native

import styled from 'styled-components/native';
const Container = styled.View`flex: 1; padding: 16px;`;

Familiar to web devs but slightly slower than StyleSheet at scale.

Pick what's installed. Don't introduce a new approach.

Fast Refresh and module-level state

React Native uses Metro + Fast Refresh. Module-level mutable state breaks Fast Refresh — components don't re-render when the module changes.

// ❌ Module-level mutable
let counter = 0;
export function increment() { counter++; }
// ✅ Use Context, Zustand, or other React-aware state
import { create } from 'zustand';
export const useCounter = create<{ count: number; inc: () => void }>((set) => ({
  count: 0,
  inc: () => set((s) => ({ count: s.count + 1 })),
}));

Hooks are Fast-Refresh-friendly by default.

EAS Build (Expo managed deployment)

eas.json:

{
  "cli": { "version": ">= 5.0.0" },
  "build": {
    "development": { "developmentClient": true, "distribution": "internal" },
    "preview": { "distribution": "internal" },
    "production": {}
  },
  "submit": { "production": {} }
}

Run via npx eas-cli build --profile production --platform all. Cloud builds → .ipa (iOS) / .aab (Android) artifacts. Out of pipeline scope; documented for awareness.

Anti-patterns

  • ❌ Editing ios/ or android/ files in Expo managed workflow. Use app.config.js config plugins.
  • ❌ Module-level mutable state — breaks Fast Refresh.
  • ❌ Storing JWTs in AsyncStorage.
  • ❌ Using <ScrollView> for long dynamic lists (use FlatList or FlashList).
  • ❌ Forgetting <SafeAreaView> — content clipped by notch/home indicator.
  • ❌ Hardcoding bundle IDs / API URLs — use app.config.js env-driven values.
  • ❌ Using web HTML primitives (<div>, <span>, <a>) — RN uses <View>, <Text>, <Pressable>/<Link>.
  • ❌ process.env.X for runtime config in managed Expo — use Constants.expoConfig.extra or build-time replacement via babel.
  • ❌ Snapshot tests of large component trees — high churn on RN especially.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Angular 18-21 project structure, standalone components vs NgModule, control flow (@if/@for/@switch + *ngIf/*ngFor legacy), decorators, dependency injection (inject() function), lifecycle hooks, pipes, Angular Universal SSR pointer. Use this skill to: - Detect project style (standalone vs NgModule) and apply matching patterns. - Pick correct decorators and DI approach. - Use modern control flow (@if/@for/@switch) in Angular 17+ projects. - Apply `inject()` function over constructor injection where appropriate. - Wire bootstrap correctly (bootstrapApplication for standalone, AppModule for legacy). Do NOT use this skill for: - State management (see angular-state-and-rx). - Routing (see angular-routing). - Forms (see angular-forms). - Testing (see angular-testing).

日本語の概要は準備中です。原文の説明を表示しています。

AratKruglik/claude-sdlc362026年9月21日 更新

Angular forms: Reactive Forms (preferred — typed FormGroup/FormControl since Angular 14, FormBuilder, custom + async validators, FormArray, multi-step) and Template-driven (`[(ngModel)]` + FormsModule). Validation strategies, server error mapping, accessibility. Use this skill to: - Build Reactive Forms with typed FormGroup/FormControl. - Use FormBuilder для concise syntax. - Implement custom synchronous and async validators. - Wire FormArray for dynamic field lists. - Map server errors back to form fields. - Pick Reactive vs Template-driven (prefer Reactive). Do NOT use this skill for: - General conventions (see angular-conventions). - State management beyond forms (see angular-state-and-rx). - Routing (see angular-routing). - Testing forms (see angular-testing).

日本語の概要は準備中です。原文の説明を表示しています。

AratKruglik/claude-sdlc362026年9月21日 更新

Angular Router (built-in `@angular/router`) — route configuration for standalone and NgModule projects, functional guards (Angular 14.1+), lazy loading, route resolvers, typed params via signals/observables, programmatic navigation, route data and meta. Use this skill to: - Configure routes (standalone-style or NgModule-style). - Use functional guards (canActivate as function, preferred over class-based in 17+). - Lazy-load components or feature modules. - Implement auth guards via route meta + functional guards. - Read params/queries via `inject(ActivatedRoute)` + signals or RxJS. Do NOT use this skill for: - General conventions (see angular-conventions). - State management (see angular-state-and-rx). - Forms (see angular-forms). - Testing routes (see angular-testing).

日本語の概要は準備中です。原文の説明を表示しています。

AratKruglik/claude-sdlc362026年9月21日 更新

State management for Angular 18-21: signals (signal/computed/effect), services-as-state, NgRx Store + Effects + Selectors, NgRx Component Store, NgRx Signals (newer signal-based store). RxJS essentials — operators, async pipe, takeUntilDestroyed, signal/observable interop. Use this skill to: - Pick the right state tool (signals / services / NgRx variant / vue-query equivalent). - Use signals correctly (signal/computed/effect — when each). - Build a Pinia-style service-as-state singleton. - Set up NgRx Store + Effects + Selectors. - Use RxJS without leaking subscriptions (async pipe, takeUntilDestroyed, Subject patterns). - Bridge signals ↔ observables via toSignal / toObservable. Do NOT use this skill for: - General Angular conventions (see angular-conventions). - Routing state (see angular-routing). - Form state (see angular-forms). - Testing state (see angular-testing).

日本語の概要は準備中です。原文の説明を表示しています。

AratKruglik/claude-sdlc362026年9月21日 更新

Testing Angular 18-21: TestBed, component harnesses (@angular/cdk/testing), Karma+Jasmine (default historical) vs Jest (jest-preset-angular, modern), Angular Testing Library (RTL-style). HttpClient mocking via HttpTestingController. NgRx Effects testing. Cypress / Playwright e2e. Use this skill to: - Detect runner (Karma+Jasmine vs Jest) and configure correctly. - Write component tests with TestBed. - Use component harnesses for Material / custom UI components. - Mock HttpClient via provideHttpClientTesting + HttpTestingController. - Test signal-based inputs with componentRef.setInput(). - Test NgRx Effects with provideMockActions. Do NOT use this skill for: - General Angular conventions (see angular-conventions). - Routing patterns broadly (see angular-routing — covers testing routes briefly). - Form patterns broadly (see angular-forms).

日本語の概要は準備中です。原文の説明を表示しています。

AratKruglik/claude-sdlc362026年9月21日 更新

Shared conventions for every SDLC development-phase architect agent: hard rules, code quality bar, workflow steps (superpowers invocation, spec reading, codebase exploration, verification), and the report/compact-summary contract. Architects load this skill first, then apply their stack-specific instructions on top.

日本語の概要は準備中です。原文の説明を表示しています。

AratKruglik/claude-sdlc362026年9月21日 更新

AratKruglik のスキルをすべて見る

このスキルの問題を報告する