ents, matches them against curated knowledge modules, and injects only the relevant conventions into the AI's working context. The architecture prioritizes progressive disclosure: lightweight frontmatter stays active, while detailed implementation patterns load conditionally.
Step-by-Step Implementation
- Define Skill Boundaries: Group knowledge by architectural domain. Separate core platform primitives, ecosystem libraries, Expo-specific workflows, reusable component patterns, performance profiling, and testing strategies.
- Structure Metadata: Each skill requires a YAML or JSON manifest containing version constraints, platform targets, dependency tags, and trigger keywords.
- Build the Router: Create a TypeScript module that scans the skill directory, parses manifests, and matches incoming queries against trigger keywords and version requirements.
- Implement Progressive Loading: Keep skill summaries in the base system prompt. Load full implementation details only when the router confirms a match.
- Version Pinning: Enforce SDK and library version checks before injecting context. Reject or warn on mismatched versions.
Architecture Decisions & Rationale
Modular Over Monolithic: A single monolithic context file grows unmanageable and increases token consumption. Modular skills allow granular updates without rewriting entire instruction sets.
Metadata-Driven Routing: Keyword matching alone produces false positives. Combining keywords with version constraints and platform flags ensures the router selects the correct architectural pattern for the target environment.
Progressive Disclosure: AI assistants perform better with focused context. Loading full implementation details only when triggered reduces noise and prevents the model from conflating unrelated patterns.
TypeScript Implementation
import fs from 'fs/promises';
import path from 'path';
import yaml from 'js-yaml';
interface SkillManifest {
id: string;
domain: string;
sdkRange: string[];
rnVersion: string;
tags: string[];
summary: string;
filePath: string;
}
interface QueryContext {
query: string;
targetSdk: string;
rnVersion: string;
platform: 'ios' | 'android' | 'all';
}
class ContextSkillRouter {
private skills: SkillManifest[] = [];
private baseDir: string;
constructor(projectRoot: string) {
this.baseDir = path.join(projectRoot, '.ai-skills');
}
async initialize(): Promise<void> {
const entries = await fs.readdir(this.baseDir, { withFileTypes: true });
const manifests = entries.filter(d => d.isDirectory());
for (const dir of manifests) {
const manifestPath = path.join(this.baseDir, dir.name, 'manifest.yaml');
try {
const raw = await fs.readFile(manifestPath, 'utf-8');
const data = yaml.load(raw) as any;
this.skills.push({
id: data.id,
domain: data.domain,
sdkRange: data.sdkRange,
rnVersion: data.rnVersion,
tags: data.tags,
summary: data.summary,
filePath: path.join(this.baseDir, dir.name, 'reference.md')
});
} catch {
console.warn(`Skipping invalid skill: ${dir.name}`);
}
}
}
async resolve(queryCtx: QueryContext): Promise<string[]> {
const matches = this.skills.filter(skill => {
const versionMatch = skill.rnVersion === queryCtx.rnVersion;
const sdkMatch = skill.sdkRange.includes(queryCtx.targetSdk);
const tagMatch = skill.tags.some(tag =>
queryCtx.query.toLowerCase().includes(tag.toLowerCase())
);
return versionMatch && sdkMatch && tagMatch;
});
const loadedContexts: string[] = [];
for (const skill of matches) {
const content = await fs.readFile(skill.filePath, 'utf-8');
loadedContexts.push(`## ${skill.domain} Context\n${content}`);
}
return loadedContexts;
}
}
export default ContextSkillRouter;
The router isolates version constraints from query matching. It validates React Native and Expo SDK versions before loading reference material, preventing architectural mismatches. The progressive loading pattern ensures only matched skills consume context tokens.
Pitfall Guide
1. Context Bleed from Over-Matching
Explanation: Keyword-based routing without version or platform validation injects irrelevant skills. The model receives conflicting patterns and generates hybrid code that fails at runtime.
Fix: Enforce strict version and platform checks in the routing logic. Require explicit tag matches before loading reference material.
2. New Architecture vs. Legacy Bridge Confusion
Explanation: React Native 0.76+ enables the New Architecture by default, but AI models frequently generate bridge-based native module code. Mixing C++ TurboModule patterns with legacy JNI/ObjC bridges causes build failures.
Fix: Include architecture flags in skill manifests. Route New Architecture queries to C++/JSI patterns and explicitly block legacy bridge generation when rnVersion >= 0.76.
3. State Library Collision
Explanation: Projects often experiment with Zustand, Jotai, and Redux Toolkit simultaneously. AI assistants generate mixed patterns, creating inconsistent state access and hydration logic.
Fix: Define a single source of truth strategy per project. Create dedicated skills for each library and enforce mutual exclusion in the routing configuration.
4. Reanimated UI-Thread Violations
Explanation: Reanimated v3 requires animation worklets to run on the UI thread. AI-generated code frequently places network calls or heavy computations inside useAnimatedStyle, causing frame drops.
Fix: Embed explicit worklet constraints in the animation skill. Include linting rules that flag non-worklet-safe operations inside animation blocks.
5. Testing Library API Drift
Explanation: Testing Library v13 and v14 introduced changes to async queries and mock rendering. AI models trained on older versions generate deprecated waitFor patterns or incorrect render options.
Fix: Pin test skills to specific major versions. Include migration notes in the reference material and validate query syntax against the target version.
6. Expo Config Plugin Overcomplication
Explanation: Developers hardcode native module linking instead of using Expo config plugins. AI assistants follow the pattern, breaking EAS Build and OTA update pipelines.
Fix: Standardize app.config.ts patterns in the Expo skill. Enforce plugin-based configuration and document native module resolution workflows.
7. Styling Inconsistency with NativeWind v4
Explanation: Mixing utility classes with inline styles or legacy StyleSheet objects creates unpredictable rendering and breaks Tailwind compilation.
Fix: Mandate utility-first conventions in the reusable component skill. Include build-time validation that rejects inline style overrides in production builds.
Production Bundle
Action Checklist
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|
| Solo developer / MVP | Single skill folder with broad tags | Fast setup, minimal maintenance | Low |
| Mid-size team / Expo SDK 54+ | Domain-split skills with version pinning | Prevents architectural drift across contributors | Medium |
| Enterprise / Multi-platform | Strict routing with CI validation + platform overrides | Guarantees build consistency and OTA update reliability | High |
| Legacy bridge migration | Separate legacy vs New Architecture skills | Isolates migration patterns and prevents mixed code generation | Medium |
Configuration Template
# .ai-skills/navigation-react-nav-v7/manifest.yaml
id: nav-react-nav-v7
domain: Navigation
sdkRange: ["53", "54", "55", "56"]
rnVersion: "0.76"
tags: ["navigation", "stack", "tabs", "deep-linking", "react-navigation"]
summary: "React Navigation v7 patterns for Expo Router integration, type-safe routes, and deep linking."
platform: "all"
# .ai-skills/navigation-react-nav-v7/reference.md
## Route Typing
Use `RootStackParamList` for compile-time route validation.
## Deep Linking
Configure `linking.prefixes` in `app.json` and handle with `useLinking()`.
## Performance
Lazy-load screens with `unmountOnBlur` for tab navigators.
// ai-context-loader.ts
import ContextSkillRouter from './ContextSkillRouter';
const router = new ContextSkillRouter(process.cwd());
await router.initialize();
const context = await router.resolve({
query: "implement tab navigation with lazy loading",
targetSdk: "54",
rnVersion: "0.76",
platform: "all"
});
console.log(context.join('\n\n'));
Quick Start Guide
- Initialize the skill directory: Run
mkdir -p .ai-skills/{core,ecosystem,expo,reusables,performance,testing} in your project root.
- Populate manifests: Copy the configuration template into each folder, adjusting
sdkRange, rnVersion, and tags to match your stack.
- Deploy the router: Add the TypeScript router to your development tooling or AI assistant configuration. Point it to
.ai-skills/.
- Validate routing: Run a test query against the router. Verify that only version-matched skills load and that context output excludes unrelated patterns.
- Integrate with AI workflow: Configure your AI assistant to call the router before generating code. Replace static system prompts with dynamic context injection.