From lisa-expo
This skill enforces the project's directory structure standards when creating or moving files. Use this skill when creating new components, screens, features, hooks, utilities, or any other code files to ensure they are placed in the correct location with proper naming conventions. Also use when reviewing file placement or restructuring code.
npx claudepluginhub codyswanngt/lisa --plugin lisa-expoThis skill uses the workspace's default tool permissions.
This skill ensures all new code follows the documented directory structure standards. It validates file placement, enforces the Container/View pattern, and ensures proper organization of features, components, and tests.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
This skill ensures all new code follows the documented directory structure standards. It validates file placement, enforces the Container/View pattern, and ensures proper organization of features, components, and tests.
<project-root>/
├── app/ # Expo Router - THIN WRAPPERS ONLY
├── features/ # Feature modules - PRIMARY CODE LOCATION
├── components/ # Shared components
│ ├── ui/ # GlueStack UI primitives
│ ├── icons/ # Icon components
│ ├── custom/ # Custom UI components
│ └── [ComponentName]/ # Feature-agnostic components
├── hooks/ # Global hooks (with __tests__/)
├── providers/ # Global React context providers (with __tests__/)
├── stores/ # Global state - Apollo reactive variables (with __tests__/)
├── utils/ # Utility functions (with __tests__/)
├── types/ # Global TypeScript types
├── generated/ # Auto-generated GraphQL types (DO NOT EDIT)
├── config/ # Configuration files
├── constants/ # Global constants
├── assets/ # Static assets (fonts/, icons/, css/)
├── e2e/ # End-to-end tests (fixtures/, pages/, tests/, utils/)
├── scripts/ # Build and development scripts
├── docs/ # Documentation
└── projects/ # Project-specific files (archive/)
Each feature in features/ MUST follow this structure:
features/[feature-name]/
├── components/ # Feature-specific components
│ └── [ComponentName]/ # Each component in its own directory
│ ├── [ComponentName]Container.tsx
│ ├── [ComponentName]View.tsx
│ └── index.tsx
├── screens/ # Screen components (same pattern as components)
│ └── [ScreenName]/
│ ├── [ScreenName]Container.tsx
│ ├── [ScreenName]View.tsx
│ └── index.tsx
├── hooks/ # Feature-specific hooks
│ └── __tests__/ # Hook tests
├── stores/ # Feature state (Apollo reactive variables)
├── utils/ # Feature utilities
│ └── __tests__/ # Utility tests
├── types.ts # Feature TypeScript types
├── constants.ts # Feature constants
├── config/ # Feature configuration
└── operations.graphql # GraphQL queries/mutations
Components and screens MUST follow the Container/View pattern:
[Name]Container.tsx)[Name]View.tsx)memo()index.tsx)// PlayerCard/PlayerCardContainer.tsx
export const PlayerCardContainer = () => {
const { data, loading } = useQuery(GET_PLAYER);
const handleClick = useCallback(() => {}, []);
return <PlayerCardView data={data} loading={loading} onClick={handleClick} />;
};
// PlayerCard/PlayerCardView.tsx
export const PlayerCardView = memo(({ data, loading, onClick }: Props) => {
if (loading) return <Skeleton />;
return <Pressable onPress={onClick}>...</Pressable>;
});
// PlayerCard/index.tsx
export { PlayerCardContainer as default } from './PlayerCardContainer';
The app/ directory contains Expo Router file-based routing. Route files MUST be thin wrappers:
// app/(root)/(tabs)/players/[playerId]/index.tsx
import { Main } from "@/features/player-detail/screens/Main";
export default function PlayerDetailScreen() {
return <Main />;
}
Test files MUST be placed in __tests__/ subdirectories:
hooks/
├── usePlayer.ts
└── __tests__/
└── usePlayer.test.ts
utils/
├── formatDate.ts
└── __tests__/
└── formatDate.test.ts
*.test.ts or *.test.tsx*.spec.ts or *.spec.tsxTo validate directory structure, run the validation script:
python3 .claude/skills/directory-structure/scripts/validate_structure.py [path]
The script checks:
__tests__/ directories| File Type | Correct Location |
|---|---|
| Feature component | features/[feature]/components/[Name]/ |
| Feature screen | features/[feature]/screens/[Name]/ |
| Feature hook | features/[feature]/hooks/ |
| Feature test | features/[feature]/hooks/__tests__/ |
| Global hook | hooks/ |
| Global hook test | hooks/__tests__/ |
| Shared component | components/[Name]/ |
| UI primitive | components/ui/ |
| Global utility | utils/ |
| Global utility test | utils/__tests__/ |
| Route wrapper | app/(root)/... |
| GraphQL types | generated/ (auto-generated) |
app/ - Route files are wrappers only__tests__/ subdirectory