AI-powered adeno-associated virus (AAV) vector design for gene therapy including capsid engineering, promoter selection, and tropism optimization.
日本語の概要は準備中です。原文の説明を表示しています。
React 19+ with TypeScript — hooks, custom hooks, state management (useState/useReducer/useContext), React Query/SWR, Tailwind CSS, performance. Use when building React components, apps, or optimizing renders.
インストール方法を見るインストールする前に、エージェントに与えられる指示の中身を確認できます。
Optimized for React 19+, TypeScript 5.5+, React Testing Library 16+, and modern server-first app architectures.
Expert guidance for building high-quality React applications with React 19+, modern hooks, TypeScript, and best practices following official React documentation at https://react.dev.
Apply the shared Component Review Rubric before approving React components, then run the React-specific checks below.
Before claiming "skill applied successfully":
// Before
'use client';
export function Dashboard() {
const [orders, setOrders] = useState<Order[]>([]);
useEffect(() => {
fetch('/api/orders').then((r) => r.json()).then(setOrders);
}, []);
return <OrdersTable orders={orders} />;
}
// After
export async function Dashboard() {
const orders = await getOrders();
return <OrdersTable orders={orders} />;
}
Lets the server boundary load data directly and keeps the client side focused on interaction, not bootstrapping.
Use symptom -> action triggers: when one matches, apply this skill and verify with the protocol below.
Core React Development:
State Management & Data:
Component Patterns:
Performance & Quality:
Recommended Structure:
src/
├── components/ # Reusable UI components
│ ├── ui/ # Primitives (Button, Input, Modal)
│ ├── forms/ # Form components
│ └── layout/ # Layout components
├── hooks/ # Custom hooks
├── contexts/ # Context providers
├── pages/ # Page components
├── lib/ # Utilities, API clients
├── types/ # TypeScript types
├── styles/ # Global styles
└── main.jsx # App entry point
interface ButtonProps {
variant: 'primary' | 'secondary' | 'danger';
size?: 'sm' | 'md' | 'lg';
onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
children: React.ReactNode;
disabled?: boolean;
isLoading?: boolean;
}
export function Button({
variant = 'primary',
size = 'md',
onClick,
children,
disabled = false,
isLoading = false,
}: ButtonProps) {
const baseClasses = 'rounded-lg font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2';
const variantClasses = {
primary: 'bg-blue-600 hover:bg-blue-700 text-white focus:ring-blue-500',
secondary: 'bg-gray-100 hover:bg-gray-200 text-gray-900 focus:ring-gray-500',
danger: 'bg-red-600 hover:bg-red-700 text-white focus:ring-red-500',
};
const sizeClasses = {
sm: 'px-3 py-1.5 text-sm',
md: 'px-4 py-2 text-base',
lg: 'px-5 py-2.5 text-lg',
};
return (
<button
disabled={disabled || isLoading}
onClick={onClick}
className={`${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]}`}
>
{isLoading ? 'Loading...' : children}
</button>
);
}
interface ListProps<T> {
items: T[];
renderItem: (item: T, index: number) => React.ReactNode;
keyExtractor: (item: T) => string;
emptyMessage?: string;
}
function List<T>({ items, renderItem, keyExtractor, emptyMessage = 'No items' }: ListProps<T>) {
return (
<ul>
{items.length === 0 ? (
<li>{emptyMessage}</li>
) : (
items.map((item, index) => (
<li key={keyExtractor(item)}>
{renderItem(item, index)}
</li>
))
)}
</ul>
);
}
// Usage
<List
items={users}
renderItem={(user) => `${user.firstName} ${user.lastName}`}
keyExtractor={(user) => user.id}
/>
Composition over Inheritance:
// ✅ GOOD - Component composition
function Card({ children }: { children: React.ReactNode }) {
return (
<div className="border rounded-lg p-4 shadow-sm">
{children}
</div>
);
}
function CardHeader({ children }: { children: React.ReactNode }) {
return (
<div className="font-bold text-lg mb-2 border-b pb-2">
{children}
</div>
);
}
function CardBody({ children }: { children: React.ReactNode }) {
return <div>{children}</div>;
}
// Usage
<Card>
<CardHeader>Title</CardHeader>
<CardBody>Content here</CardBody>
</Card>
// ❌ BAD - Inheritance or complex props
function Card({ renderHeader, renderBody, renderFooter }: { ... }) { ... }
Presentational vs Container Components:
// Presentational - UI only, doesn't fetch data
interface UserCardProps {
user: User;
onStatusChange: (status: string) => void;
}
function UserCard({ user, onStatusChange }: UserCardProps) {
return (
<div>
<h3>{user.name}</h3>
<select value={user.status} onChange={(e) => onStatusChange(e.target.value)}>
<option value="active">Active</option>
<option value="inactive">Inactive</option>
</select>
</div>
);
}
// Container - Fetches data, passes to presentational
function UserContainer() {
const { data: user, mutate: updateStatus } = useUser(userId);
return user ? (
<UserCard user={user} onStatusChange={(status) => updateStatus({ status })} />
) : (
<LoadingSpinner />
);
}
// Simple state
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<span>{count}</span>
<button onClick={() => setCount(c => c + 1)}>Increment</button>
</div>
);
}
// Complex state - use useReducer instead
function Form() {
type FormState = {
name: string;
email: string;
submitted: boolean;
};
const [form, setForm] = useState<FormState>({
name: '',
email: '',
submitted: false,
});
const updateField = (field: keyof FormState) => (
e: React.ChangeEvent<HTMLInputElement>
) => setForm(f => ({ ...f, [field]: e.target.value }));
return (
<form>
<input value={form.name} onChange={updateField('name')} />
<input value={form.email} onChange={updateField('email')} />
</form>
);
}
type Action =
| { type: 'ADD_TODO'; payload: string }
| { type: 'TOGGLE_TODO'; payload: number }
| { type: 'DELETE_TODO'; payload: number };
type TodoState = {
items: Array<{ id: number; text: string; completed: boolean }>;
};
function todosReducer(state: TodoState, action: Action): TodoState {
switch (action.type) {
case 'ADD_TODO':
return {
items: [
...state.items,
{ id: Date.now(), text: action.payload, completed: false },
],
};
case 'TOGGLE_TODO':
return {
items: state.items.map((item) =>
item.id === action.payload ? { ...item, completed: !item.completed } : item
),
};
case 'DELETE_TODO':
return {
items: state.items.filter((item) => item.id !== action.payload),
};
default:
return state;
}
}
function TodoApp() {
const [state, dispatch] = useReducer(todosReducer, { items: [] });
return (
<div>
<ToDoList items={state.items} onToggle={(id) => dispatch({ type: 'TOGGLE_TODO', payload: id })} />
</div>
);
}
function UserProfile({ userId }: { userId: string }) {
const [user, setUser] = useState<User | null>(null);
// ✅ GOOD - Run on mount and when userId changes
useEffect(() => {
let cancelled = false;
async function fetchUser() {
const userData = await api.getUser(userId);
if (!cancelled) {
setUser(userData);
}
}
fetchUser();
return () => {
cancelled = true; // Cleanup to prevent state updates after unmount
};
}, [userId]);
// ✅ GOOD - Document title update
useEffect(() => {
if (user) {
document.title = `${user.name} - Profile`;
}
return () => {
document.title = 'App';
};
}, [user]);
if (!user) return <LoadingSkeleton />;
return (
<div>
<h1>{user.name}</h1>
{/* ... */}
</div>
);
}
// Context creation
type ThemeContextType = {
theme: 'light' | 'dark';
toggleTheme: () => void;
};
const ThemeContext = createContext<ThemeContextType | null>(null);
// Provider component
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState<'light' | 'dark'>('light');
const toggleTheme = () => setTheme(t => t === 'light' ? 'dark' : 'light');
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
// Custom hook for using context
export function useTheme() {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within ThemeProvider');
}
return context;
}
// Usage in component
function ThemedButton() {
const { theme, toggleTheme } = useTheme();
return (
<button
onClick={toggleTheme}
className={theme === 'dark' ? 'bg-gray-800 text-white' : 'bg-white text-black'}
>
Toggle {theme} theme
</button>
);
}
function ProductList({ products }: { products: Product[] }) {
// ✅ GOOD - Memoize expensive calculation
const sortedProducts = useMemo(() => {
return [...products].sort((a, b) => a.price - b.price);
}, [products]);
const expensiveAnalysis = useMemo(() => {
// Only recompute when prices change
const avgPrice = products.reduce((sum, p) => sum + p.price, 0) / products.length;
const maxPrice = Math.max(...products.map(p => p.price));
return { avgPrice, maxPrice };
}, [products]);
return (
<div>
<StatsCard data={expensiveAnalysis} />
<ProductCards products={sortedProducts} />
</div>
);
}
function ParentComponent() {
const [items, setItems] = useState<Item[]>([]);
// ✅ GOOD - Memoize callback to prevent child re-renders
const handleItemAdd = useCallback((item: Item) => {
setItems(prev => [...prev, item]);
}, []);
const handleItemRemove = useCallback((id: string) => {
setItems(prev => prev.filter(item => item.id !== id));
}, []);
return (
<div>
<AddItemForm onAdd={handleItemAdd} />
<ItemList items={items} onRemove={handleItemRemove} />
</div>
);
}
// Child component wrapped in React.memo
const ItemList = React.memo(function ItemList({
items,
onRemove,
}: {
items: Item[];
onRemove: (id: string) => void;
}) {
return (
<ul>
{items.map(item => (
<li key={item.id}>
{item.name}
<button onClick={() => onRemove(item.id)}>Remove</button>
</li>
))}
</ul>
);
});
Debounce rapid value changes, useful for search inputs:
import { useState, useEffect } from 'react';
function useDebounce<T>(value: T, delay: number = 500): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
}
// Usage
function SearchBar() {
const [query, setQuery] = useState('');
const debouncedQuery = useDebounce(query, 300);
useEffect(() => {
// This only runs 300ms after user stops typing
if (debouncedQuery) {
performSearch(debouncedQuery);
}
}, [debouncedQuery]);
return (
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search..."
/>
);
}
Persist state to localStorage:
function useLocalStorage<T>(key: string, initialValue: T) {
const [storedValue, setStoredValue] = useState<T>(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.error(`Error reading localStorage key "${key}":`, error);
return initialValue;
}
});
const setValue = (value: T | ((val: T) => T)) => {
try {
const valueToStore = value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
window.localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.error(`Error setting localStorage key "${key}":`, error);
}
};
return [storedValue, setValue] as const;
}
// Usage
function ThemeToggle() {
const [theme, setTheme] = useLocalStorage<'light' | 'dark'>('theme', 'light');
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Current theme: {theme}
</button>
);
}
Toggle boolean state with useful utilities:
function useToggle(initialValue: boolean = false) {
const [value, setValue] = useState(initialValue);
const toggle = useCallback(() => setValue(v => !v), []);
const setTrue = useCallback(() => setValue(true), []);
const setFalse = useCallback(() => setValue(false), []);
return { value, toggle, setTrue, setFalse, setValue } as const;
}
// Usage
function ModalExample() {
const { value: isOpen, toggle, setFalse: close } = useToggle(false);
return (
<>
<button onClick={toggle}>Open Modal</button>
<Modal isOpen={isOpen} onClose={close}>
<p>Modal content</p>
</Modal>
</>
);
}
Data fetching with loading and error states:
type UseFetchResult<T> = {
data: T | null;
loading: boolean;
error: Error | null;
refetch: () => Promise<void>;
};
function useFetch<T>(url: string): UseFetchResult<T> {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
const fetchData = useCallback(async () => {
setLoading(true);
setError(null);
try {
const response = await fetch(url);
const jsonData = await response.json();
setData(jsonData);
} catch (err) {
setError(err as Error);
} finally {
setLoading(false);
}
}, [url]);
useEffect(() => {
fetchData();
}, [fetchData]);
return { data, loading, error, refetch: fetchData };
}
// Usage
function UserProfile({ userId }: { userId: string }) {
const { data: user, loading, error } = useFetch<User>(`/api/users/${userId}`);
if (loading) return <LoadingSpinner />;
if (error) return <ErrorAlert message={error.message} />;
return (
<div>
<h1>{user?.name}</h1>
<p>{user?.email}</p>
</div>
);
}
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
// Zod schema for validation
const formSchema = z.object({
name: z.string().min(2, 'Name must be at least 2 characters'),
email: z.string().email('Invalid email address'),
age: z.number().min(18, 'Must be at least 18'),
subscribe: z.boolean().default(false),
});
type FormData = z.infer<typeof formSchema>;
function UserForm() {
const {
register,
handleSubmit,
formState: { errors, isSubmitting },
} = useForm<FormData>({
resolver: zodResolver(formSchema),
});
const onSubmit = async (data: FormData) => {
try {
await api.createUser(data);
alert('User created successfully!');
} catch (error) {
alert('Error creating user');
}
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div className="mb-4">
<label>Name</label>
<input {...register('name')} />
{errors.name && <span className="error">{errors.name.message}</span>}
</div>
<div className="mb-4">
<label>Email</label>
<input type="email" {...register('email')} />
{errors.email && <span className="error">{errors.email.message}</span>}
</div>
<div className="mb-4">
<label>Age</label>
<input type="number" {...register('age', { valueAsNumber: true })} />
{errors.age && <span className="error">{errors.age.message}</span>}
</div>
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? 'Creating...' : 'Create User'}
</button>
</form>
);
}
interface FormFieldProps {
label: string;
error?: string;
children: React.ReactNode;
}
function FormField({ label, error, children }: FormFieldProps) {
return (
<div className="mb-4">
<label className="block text-sm font-medium mb-1">{label}</label>
{children}
{error && <p className="text-red-500 text-sm mt-1">{error}</p>}
</div>
);
}
// Usage
<FormField label="Email" error={errors.email?.message}>
<input
type="email"
{...register('email')}
className="w-full px-3 py-2 border rounded"
/>
</FormField>
// Button component with variants
const buttonVariants = {
primary: 'bg-blue-600 hover:bg-blue-700 focus:ring-blue-500',
secondary: 'bg-gray-200 hover:bg-gray-300 focus:ring-gray-500',
danger: 'bg-red-600 hover:bg-red-700 focus:ring-red-500',
ghost: 'bg-transparent hover:bg-gray-100 focus:ring-gray-500',
};
const buttonSizes = {
sm: 'px-3 py-1.5 text-sm',
md: 'px-4 py-2 text-base',
lg: 'px-5 py-2.5 text-lg',
};
export function Button({
variant = 'primary',
size = 'md',
className = '',
children,
...props
}: ButtonProps) {
return (
<button
className={cn(
'rounded-lg font-medium transition-colors focus:outline-none focus:ring-2',
buttonVariants[variant],
buttonSizes[size],
className
)}
{...props}
>
{children}
</button>
);
}
interface CardProps {
isFeatured?: boolean;
children: React.ReactNode;
}
export function Card({ isFeatured = false, children }: CardProps) {
return (
<div
className={cn(
'rounded-lg shadow-md p-6 transition-all',
'bg-white hover:shadow-lg',
// Responsive padding
'sm:p-4 md:p-6 lg:p-8',
// Featured highlight
isFeatured && 'ring-2 ring-blue-500 border-2 border-blue-500'
)}
>
{children}
</div>
);
}
// AppContext.tsx
interface AppState {
user: User | null;
loading: boolean;
login: (credentials: LoginCredentials) => Promise<void>;
logout: () => void;
}
const AppContext = createContext<AppState | null>(null);
export function AppProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(false);
const login = async (credentials: LoginCredentials) => {
setLoading(true);
try {
const userData = await api.login(credentials);
setUser(userData);
} finally {
setLoading(false);
}
};
const logout = () => {
api.logout();
setUser(null);
};
return (
<AppContext.Provider value={{ user, loading, login, logout }}>
{children}
</AppContext.Provider>
);
}
export function useApp() {
const context = useContext(AppContext);
if (!context) throw new Error('useApp must be used within AppProvider');
return context;
}
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
// Fetch data
function UserProfile({ userId }: { userId: string }) {
const { data: user, isLoading, error } = useQuery({
queryKey: ['user', userId],
queryFn: () => api.getUser(userId),
staleTime: 5 * 60 * 1000, // 5 minutes
});
if (isLoading) return <LoadingSpinner />;
if (error) return <ErrorAlert message={error.message} />;
return (
<div>
<h1>{user?.name}</h1>
<p>{user?.email}</p>
</div>
);
}
// Mutate data
function UpdateUserForm({ user: initialUser }: { user: User }) {
const queryClient = useQueryClient();
const mutation = useMutation({
mutationFn: api.updateUser,
onSuccess: () => {
// Invalidate and refetch
queryClient.invalidateQueries({ queryKey: ['user', initialUser.id] });
},
});
const handleSubmit = (data: Partial<User>) => {
mutation.mutate({ ...initialUser, ...data });
};
return (
<form onSubmit={(e) => { e.preventDefault(); handleSubmit(/* data */); }}>
{/* Form fields */}
</form>
);
}
import { lazy, Suspense } from 'react';
// Lazy load components
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Reports = lazy(() => import('./pages/Reports'));
const Settings = lazy(() => import('./pages/Settings'));
function App() {
return (
<Suspense fallback={<LoadingSpinner />}>
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/reports" element={<Reports />} />
<Route path="/settings" element={<Settings />} />
</Routes>
</Suspense>
);
}
import { useVirtualizer } from '@tanstack/react-virtual';
function VirtualList({ items }: { items: Item[] }) {
const parentRef = useRef<HTMLDivElement>(null);
const virtualizer = useVirtualizer({
count: items.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 50, // Estimated item height
overscan: 5, // Render extra items beyond viewport
});
return (
<div ref={parentRef} className="h-96 overflow-auto">
<div
style={{
height: `${virtualizer.getTotalSize()}px`,
position: 'relative',
}}
>
{virtualizer.getVirtualItems().map((virtualItem) => {
const item = items[virtualItem.index];
return (
<div
key={virtualItem.key}
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: `${virtualItem.size}px`,
transform: `translateY(${virtualItem.start}px)`,
}}
>
{/*
...existing code...
*/}
</div>
);
})}
</div>
</div>
);
}
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { expect } from 'vitest';
import userEvent from '@testing-library/user-event';
describe('Button Component', () => {
it('renders children correctly', () => {
render(<Button>Click Me</Button>);
expect(screen.getByText('Click Me')).toBeInTheDocument();
});
it('calls onClick handler when clicked', async () => {
const user = userEvent.setup();
const handleClick = vi.fn();
render(<Button onClick={handleClick}>Click Me</Button>);
await user.click(screen.getByText('Click Me'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
it('is disabled when disabled prop is true', () => {
render(<Button disabled>Cannot Click</Button>);
expect(screen.getByRole('button')).toBeDisabled();
});
});
describe('UseFetch Hook', () => {
it('fetches data and returns it', async () => {
const { result } = renderHook(() => useFetch('/api/test'));
await waitFor(() => {
expect(result.current.data).toBeDefined();
expect(result.current.loading).toBe(false);
});
});
});
export async function OrdersPanel() {
const orders = await getOrders();
return <OrdersTable orders={orders} />;
}
import { ErrorBoundary } from 'react-error-boundary';
<ErrorBoundary fallbackRender={() => <p>Could not load dashboard.</p>}>
<Dashboard />
</ErrorBoundary>
import { axe } from 'jest-axe';
test('dialog passes axe checks', async () => {
const { container } = render(<AccountDialog open />);
expect(await axe(container)).toHaveNoViolations();
});
This skill is written to stay usable across GitHub Copilot, Claude Code, and Codex.
$CODEX_HOME/skills/react-development and restart Codex after major changes.Preferred MCP Server: None required
SKILL.md, bundled references or scripts, and manual verification. Show the exact commands, evidence, and final checks you used before concluding."まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
AI-powered adeno-associated virus (AAV) vector design for gene therapy including capsid engineering, promoter selection, and tropism optimization.
日本語の概要は準備中です。原文の説明を表示しています。
Improve the clarity and voice of AI-assisted academic writing (papers, theses, rebuttals) and
日本語の概要は準備中です。原文の説明を表示しています。
12-agent academic paper writing pipeline. 11 modes (full/plan/outline/revision/revision-coach/abstract/lit-review/format-convert/citation-check/disclosure/rebuttal-audit). 6 paper types, 5 citation formats, bilingual abstracts, LaTeX/DOCX-via-Pandoc/PDF output. Style Calibration + Writing Quality Check + Anti-Patterns with IRON RULE markers. Triggers: write paper, academic paper, guide my paper, parse reviews, audit my rebuttal, check my response draft, AI disclosure, 寫論文, 學術論文, 引導我寫論文, 審查意見, 評估回覆, 논문 작성, 초록 작성, 논문 수정, 논문 계획을 도와줘, 심사 의견 반영, 답변서 점검, AI 사용 고지.
日本語の概要は準備中です。原文の説明を表示しています。
Systematic writing framework for philosophy and interdisciplinary academic papers from optimized outline to submission-ready manuscript. Use when users want to: (1) write a paper from a detailed outline, (2) ensure quality control during writing, (3) maintain consistency across chapters, (4) prepare a submission-ready manuscript, or (5) systematically execute a planned paper. Triggered by phrases like 'write the paper from this outline,' 'compose the full manuscript,' 'execute the outline,' or when users have completed strategic planning (academic-paper-strategist skill) and are ready to write. Takes optimized outline as input; outputs complete manuscript with iterative quality checks.
日本語の概要は準備中です。原文の説明を表示しています。
Multi-perspective academic paper review with dynamic reviewer personas. Runs a 5-seat, role-separated review panel (Journal-Fit Reviewer + 3 peer-review roles + Devil's Advocate) with field-specific expertise; role separation is not a claim of independent error processes. Supports full review, re-review (verification), quick assessment, methodology focus, Socratic guided, and calibration modes. Triggers on: review paper, peer review, manuscript review, referee report, review my paper, critique paper, simulate review, editorial review, calibrate reviewer, reviewer calibration, measure reviewer accuracy, 審查論文, 論文審查, 模擬審查, 同儕審查, 幫我審這篇, 以審查人角度評估, 審查者校準, 논문 심사, 동료 심사, 모의 심사, 심사자 관점에서 평가, 심사자 보정.
日本語の概要は準備中です。原文の説明を表示しています。
Systematic strategic planning framework for philosophy and interdisciplinary academic papers targeting preprint platforms (PhilArchive, arXiv, PhilSci-Archive). Use when users want to: (1) plan a paper on a specific topic, (2) identify research gaps and assess originality, (3) develop optimized paper outlines, (4) prepare for preprint submission, or (5) understand platform requirements and writing standards. Triggered by phrases like 'plan a paper on,' 'help me design a paper about,' 'identify research gaps in,' 'is this idea original,' or when users need structured research planning. The skill guides through three phases: Platform Analysis (identifying target venue and studying sample papers), Theoretical Framework (AI-driven literature search and gap identification), and Outline Optimization (structured design with reviewer-perspective self-assessment). Each phase includes quality evaluation standards and validation checkpoints.
日本語の概要は準備中です。原文の説明を表示しています。