/eisland-dev-refactor-module-split
Refactor a monolithic React component file into a standardized module structure with components/, hooks/, utils/, types/, and config/ subdirectories. Use this skill whenever the user asks to "split", "refactor", "拆分", "拆解", or "restructure" a component file into subdirectories,
$ npx -y skills add JNTMTMTM/eIsland --skill eisland-dev-refactor-module-split --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/eisland-dev-refactor-module-split
Context preview
The summary Claude sees to decide when to auto-load this skill.
Refactor a monolithic React component file into a standardized module structure with components/, hooks/, utils/, types/, and config/ subdirectories. Use this skill whenever the user asks to "split", "refactor", "拆分", "拆解", or "restructure" a component file into subdirectories,
SKILL.md
eisland-dev-refactor-module-split.SKILL.mdname: eisland-dev-refactor-module-split
author: JNTMTMTM
description: >
Refactor a monolithic React component file into a standardized module structure with
components/, hooks/, utils/, types/, and config/ subdirectories. Use this skill whenever
the user asks to "split", "refactor", "拆分", "拆解", or "restructure" a component file
into subdirectories, or when they mention organizing code into modules.
Refactor Module Split
Split a monolithic React component file into a clean module structure with five subdirectories: `components/`, `hooks/`, `utils/`, `types/`, and `config/`, plus an `index.ts` entry point.
When to use
- A single `.tsx` file has grown large and contains multiple concerns (utility functions, hooks, sub-components, constants, type definitions)
- The user explicitly asks to split/refactor a component into subdirectories
- The file is a React component that mixes UI rendering, state management, utility logic, and configuration
Process
Step 0: Ensure module scaffolding exists
Before extracting any code, verify the target module directory has the required structure. If any of the following are missing, create them first:
<module>/
├── index.ts (if missing, create with placeholder export)
├── types/ (if missing, create directory)
├── config/ (if missing, create directory)
├── utils/ (if missing, create directory)
├── hooks/ (if missing, create directory)
└── components/ (if missing, create directory)
- Empty directories should contain a `.gitkeep` placeholder
- `index.ts` should initially export the original component (update after refactoring)
Step 1: Analyze the source file
Read the target file in full. Categorize every piece of code into one of five buckets:
| Bucket | Criteria | Target directory | |--------|----------|-----------------| | **Types** | `type`, `interface`, component prop interfaces, hook return types | `types/` | | **Constants** | `const` values, config keys, store keys, i18n keys/defaults | `config/` | | **Pure functions** | No React hooks, no side effects, deterministic input→output | `utils/` | | **React hooks** | Uses `useState`, `useEffect`, `useMemo`, `useCallback`, or custom hooks | `hooks/` | | **Sub-components** | Returns JSX, used within the main component | `components/` |
Also check if the file's sibling directories already exist (e.g., `components/` or `hooks/` may already have files from prior refactoring). Don't duplicate existing extractions.
Step 2: Create the extracted files
For each extracted piece, create a new file in the appropriate directory. Every file must include:
1. **License header** — copy the exact GPL-3.0 block from the source file 2. **File-level JSDoc** — `@file`, `@description`, `@author` tags 3. **Function/type JSDoc** — `@param`, `@returns` for all exported functions 4. **Correct imports** — relative paths back to shared types or store slices
Naming conventions:
- `types/` — camelCase with module prefix (e.g., `todoTypes.ts`, `albumTypes.ts`, `localFileSearchTypes.ts`)
- `config/` — camelCase with module prefix (e.g., `todoConfig.ts`, `albumConfig.ts`, `localFileSearchConfig.ts`)
- `utils/` — camelCase with module prefix (e.g., `todoUtils.ts`, `albumUtils.ts`, `localFileSearchUtils.ts`)
- `hooks/` — camelCase with `use` prefix (e.g., `useTodos.ts`, `useAlbumItems.ts`, `useLocalFileSearch.ts`)
- `components/` — PascalCase component name (e.g., `TodoTab.tsx`, `TodoHeader.tsx`, `AlbumGridItem.tsx`)
Step 3: Define types first
Create `types/<module>Types.ts` **before** other files. This file must contain:
1. **Domain types** — data models, enums, union types used by the module 2. **Hook return type** — `Use<Module>Return` interface describing the hook's full return shape 3. **Component prop interfaces** — `<Component>Props` for every sub-component
All component prop interfaces and hook return types MUST be defined in `types/`, not inline in component or hook files.
Example pattern:
// types/todoTypes.ts
/** 紧急程度 */
export type Priority = 'P0' | 'P1' | 'P2';
/** 单条待办 */
export interface TodoItem { ... }
/** useTodos hook 返回值类型 */
export interface UseTodosReturn { ... }
/** TodoHeader 组件入参 */
export interface TodoHeaderProps { ... }
/** TodoInputBar 组件入参 */
export interface TodoInputBarProps { ... }Step 4: Rewrite the source file
Replace the extracted code in the original file with imports from the new modules. The source file should become a thin composition layer that:
- Imports hook from `../hooks/use<Module>`
- Imports sub-components from `./<ComponentName>`
- Calls the hook at the top level
- Destructures hook return values and passes them as props to sub-components
- Contains no extracted logic, no `useEffect`, no utility functions
Step 5: Create the index.ts entry point
Create `<module>/index.ts` that re-exports the main component:
export { TodoTab } from './components/TodoTab';Step 6: Verify
Run these checks in order — all must pass before committing:
# 1. TypeScript compilation
npx tsc --noEmit --pretty
# 2. Comment standards compliance (file headers, JSDoc)
npm run comment:check
# 3. i18n completeness (all t() keys exist in both zh-CN and en-US)
npm run i18n:check
# 4. Unit tests
npm run test
If any check fails, fix the issue before proceeding. Common failures:
- `comment:check` — missing license header, missing `@file`/`@description`/`@author`, missing JSDoc on exported functions
- `i18n:check` — a `t('key')` call references a key not present in both locale files
- `test` — a refactored import path broke a test, or an extracted function changed behavior
Step 7: Commit
Use a conventional commit message:
refactor(<module-name>): extract types, utils, hooks, components, config from <OriginalFile>
- types/<name>Types.ts: type definitions + component prop interfaces
- utils/<name>Utils.ts: <what it does>
- hooks/us
Read more
name: eisland-dev-refactor-module-split author: JNTMTMTM description: > Refactor a monolithic React component file into a standardized module structure with components/, hooks/, utils/, types/, and config/ subdirectories. Use this skill whenever the user asks to "split", "refactor", "拆分", "拆解", or "restructure" a component file into subdirectories, or when they mention organizing code into modules.
Refactor Module Split
Split a monolithic React component file into a clean module structure with five subdirectories: `components/`, `hooks/`, `utils/`, `types/`, and `config/`, plus an `index.ts` entry point.
When to use
- A single `.tsx` file has grown large and contains multiple concerns (utility functions, hooks, sub-components, constants, type definitions)
- The user explicitly asks to split/refactor a component into subdirectories
- The file is a React component that mixes UI rendering, state management, utility logic, and configuration
Process
Step 0: Ensure module scaffolding exists
Before extracting any code, verify the target module directory has the required structure. If any of the following are missing, create them first:
<module>/ ├── index.ts (if missing, create with placeholder export) ├── types/ (if missing, create directory) ├── config/ (if missing, create directory) ├── utils/ (if missing, create directory) ├── hooks/ (if missing, create directory) └── components/ (if missing, create directory)
- Empty directories should contain a `.gitkeep` placeholder
- `index.ts` should initially export the original component (update after refactoring)
Step 1: Analyze the source file
Read the target file in full. Categorize every piece of code into one of five buckets:
| Bucket | Criteria | Target directory | |--------|----------|-----------------| | **Types** | `type`, `interface`, component prop interfaces, hook return types | `types/` | | **Constants** | `const` values, config keys, store keys, i18n keys/defaults | `config/` | | **Pure functions** | No React hooks, no side effects, deterministic input→output | `utils/` | | **React hooks** | Uses `useState`, `useEffect`, `useMemo`, `useCallback`, or custom hooks | `hooks/` | | **Sub-components** | Returns JSX, used within the main component | `components/` |
Also check if the file's sibling directories already exist (e.g., `components/` or `hooks/` may already have files from prior refactoring). Don't duplicate existing extractions.
Step 2: Create the extracted files
For each extracted piece, create a new file in the appropriate directory. Every file must include:
1. **License header** — copy the exact GPL-3.0 block from the source file 2. **File-level JSDoc** — `@file`, `@description`, `@author` tags 3. **Function/type JSDoc** — `@param`, `@returns` for all exported functions 4. **Correct imports** — relative paths back to shared types or store slices
Naming conventions:
- `types/` — camelCase with module prefix (e.g., `todoTypes.ts`, `albumTypes.ts`, `localFileSearchTypes.ts`)
- `config/` — camelCase with module prefix (e.g., `todoConfig.ts`, `albumConfig.ts`, `localFileSearchConfig.ts`)
- `utils/` — camelCase with module prefix (e.g., `todoUtils.ts`, `albumUtils.ts`, `localFileSearchUtils.ts`)
- `hooks/` — camelCase with `use` prefix (e.g., `useTodos.ts`, `useAlbumItems.ts`, `useLocalFileSearch.ts`)
- `components/` — PascalCase component name (e.g., `TodoTab.tsx`, `TodoHeader.tsx`, `AlbumGridItem.tsx`)
Step 3: Define types first
Create `types/<module>Types.ts` **before** other files. This file must contain:
1. **Domain types** — data models, enums, union types used by the module 2. **Hook return type** — `Use<Module>Return` interface describing the hook's full return shape 3. **Component prop interfaces** — `<Component>Props` for every sub-component
All component prop interfaces and hook return types MUST be defined in `types/`, not inline in component or hook files.
Example pattern:
// types/todoTypes.ts
/** 紧急程度 */
export type Priority = 'P0' | 'P1' | 'P2';
/** 单条待办 */
export interface TodoItem { ... }
/** useTodos hook 返回值类型 */
export interface UseTodosReturn { ... }
/** TodoHeader 组件入参 */
export interface TodoHeaderProps { ... }
/** TodoInputBar 组件入参 */
export interface TodoInputBarProps { ... }Step 4: Rewrite the source file
Replace the extracted code in the original file with imports from the new modules. The source file should become a thin composition layer that:
- Imports hook from `../hooks/use<Module>`
- Imports sub-components from `./<ComponentName>`
- Calls the hook at the top level
- Destructures hook return values and passes them as props to sub-components
- Contains no extracted logic, no `useEffect`, no utility functions
Step 5: Create the index.ts entry point
Create `<module>/index.ts` that re-exports the main component:
export { TodoTab } from './components/TodoTab';Step 6: Verify
Run these checks in order — all must pass before committing:
# 1. TypeScript compilation npx tsc --noEmit --pretty # 2. Comment standards compliance (file headers, JSDoc) npm run comment:check # 3. i18n completeness (all t() keys exist in both zh-CN and en-US) npm run i18n:check # 4. Unit tests npm run test
If any check fails, fix the issue before proceeding. Common failures:
- `comment:check` — missing license header, missing `@file`/`@description`/`@author`, missing JSDoc on exported functions
- `i18n:check` — a `t('key')` call references a key not present in both locale files
- `test` — a refactored import path broke a test, or an extracted function changed behavior
Step 7: Commit
Use a conventional commit message:
refactor(<module-name>): extract types, utils, hooks, components, config from <OriginalFile> - types/<name>Types.ts: type definitions + component prop interfaces - utils/<name>Utils.ts: <what it does> - hooks/us
eIsland - A sleek, Apple Dynamic Island inspired floating widget for Windows, built with Electron.
Repo: JNTMTMTM/eIsland
Other skills on eisland.
- /eisland-dev-add-empty-setting-subpage
Add a new empty subpage (tab) to an existing eIsland settings section with page navigation support. Use this skill whenever the user wants to add a new tab/page/subpage to any settings section in the eIsland project, including requests like "添加分页", "add a tab", "add subpage",
Open skill - /eisland-dev-add-guide-step
创建 eIsland 引导配置窗口的新步骤页面。当用户要求在引导界面(Guide)中新增配置步骤、引导页面、引导分页时使用此 skill。 触发关键词:guide 步骤、引导页面、引导分页、Guide step、新建引导页、添加引导配置。 适用于 src/renderer/components/components/ 目录下的 Guide 模块。
Open skill - /eisland-dev-add-svg-icon
Add a new SVG icon to the project's icon enum system with matching test assertions. Use this skill whenever the user asks to "add SVG icon", "添加图标", "add icon enum", "注册图标", "补齐图标枚举", "add SVG enum", or wants to register a new .svg file in the SvgIcon utility. Also trigger when
Open skill - /eisland-dev-generate-release-worklog
Generate a release announcement markdown for eIsland. Use this skill whenever the user asks to "generate release notes", "create announcement", "写更新日志", "生成发布公告", "draft release notes", or mentions preparing a new version release document.
Open skill - /eisland-dev-git-commit
Analyze the current git status, review all staged and unstaged changes, and create a commit with a proper English commit message following conventional commit format. Use this skill whenever the user asks to "commit", "提交", "git commit", "analyze and commit", "check git status
Open skill - /eisland-dev-update-docs
Update or create documentation in the eIsland VuePress docs site (web/eisland-web-docs). Use this skill whenever the user asks to update docs, add documentation, write a doc article, document a feature, update the tech stack docs, update plugin docs, update command docs, or any
Open skill

