From jm-claude-plugin
Code style guide for JavaScript, TypeScript (Strict Mode), React 19+, and Tailwind CSS. Use this skill whenever writing, reviewing, or refactoring any JS/TS file, React component, or Tailwind UI. Trigger on: "how should I name this?", "is this clean?", "review my component", "refactor this", "best practices", any new function/hook/component creation, or any code that feels inconsistent. Apply proactively — don't wait to be asked.
How this skill is triggered — by the user, by Claude, or both
Slash command
/jm-claude-plugin:code-styleThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Staff Engineer standard: optimize for **readability at scale**, not cleverness.
Staff Engineer standard: optimize for readability at scale, not cleverness.
✅ Descriptive names in English
✅ One function = one responsibility
✅ Max ~25 lines per function — if longer, extract
✅ Comments explain WHY, not WHAT
✅ Linear flow: Validate → Process → Return
✅ Avoid deep nesting (max 2 levels)
✅ Consistent formatter (Prettier + ESLint — no exceptions)
| Element | Convention | Example |
|---|---|---|
| Functions / hooks | camelCase, verb | getUserData, useAuthSession |
| Variables / state | camelCase | isLoading, userData |
| Constants | UPPER_SNAKE_CASE | MAX_RETRIES, API_BASE_URL |
| Classes / Types | PascalCase | UserService, ApiResponse |
| React components | PascalCase | UserDashboard, LoginForm |
| Files (TS/JS) | kebab-case | user-service.ts, auth-hook.ts |
| Files (components) | PascalCase | UserCard.tsx, LoginForm.tsx |
Pick ONE convention per project. Enforce it via ESLint.
// tsconfig.json — non-negotiable
{
"strict": true, // enables all strict checks
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true
}
Rules:
any — use unknown + type guards if neededtype over interface unless extending// ✅ Discriminated union — safe, exhaustive
type Result<T> =
| { status: "ok"; data: T }
| { status: "error"; message: string };
// ❌ Optional soup — ambiguous
type Result<T> = { data?: T; error?: string };
Required on: exported functions, hooks, service methods.
/**
* Fetches paginated users from the API.
*
* @param page - 1-based page number
* @param limit - Items per page (max 100)
* @returns Paginated user list
* @throws {NotFoundError} When page exceeds total
*
* @example
* const users = await getUsers(1, 20);
*/
export async function getUsers(page: number, limit: number): Promise<PaginatedResult<User>> {
// implementation
}
// ✅ GOOD — linear, fail-fast, readable
const processPayment = async (amount: number): Promise<PaymentResult> => {
if (amount <= 0) throw new ValidationError("Amount must be positive");
const result = await paymentService.charge(amount);
return result;
};
// ❌ BAD — nested ifs, scattered returns, no types
const processPayment = async (amount) => {
if (amount > 0) {
if (user.verified) {
if (balance >= amount) {
return await charge(amount);
} else { return null; }
}
}
return null;
};
Pattern: Validate → Process → Return. Always.
// ✅ Typed props, single responsibility, no logic leaking into JSX
type UserCardProps = {
userId: string;
onSelect: (id: string) => void;
};
export const UserCard = ({ userId, onSelect }: UserCardProps) => {
const { data, isLoading } = useUser(userId); // logic in hook
if (isLoading) return <Skeleton />;
return (
<article onClick={() => onSelect(userId)}>
<h2>{data.name}</h2>
</article>
);
};
Rules:
UserCard.tsx, useUserCard.ts, UserCard.test.tsx in same folder// ✅ Readable: group by concern, use cn() for conditionals
import { cn } from "@/lib/utils";
const Button = ({ variant, disabled }: ButtonProps) => (
<button
className={cn(
"rounded-md px-4 py-2 text-sm font-medium transition-colors",
variant === "primary" && "bg-blue-600 text-white hover:bg-blue-700",
variant === "ghost" && "bg-transparent text-gray-700 hover:bg-gray-100",
disabled && "cursor-not-allowed opacity-50"
)}
>
Click
</button>
);
// ❌ BAD — unreadable wall of classes, no structure
<button className="rounded-md px-4 py-2 text-sm font-medium bg-blue-600 text-white hover:bg-blue-700 cursor-not-allowed opacity-50 transition-colors">
Rules:
cn() (clsx + tailwind-merge) for conditional classes — always[20px] → use spacing scale)@apply in global CSS (sparingly)base → sm: → md: → lg:references/ holds extended guides:
| File | Contents |
|---|---|
tailwind-deep.md + references/ | Tailwind v4.1+ utilities, responsive patterns, dark mode, component variants |
typescript-advanced.md | Advanced TS: conditional types, mapped types, template literals, variance, branded types |
[ ] No `any` in TypeScript
[ ] JSDoc on all exported functions
[ ] No function > 25 lines without justification
[ ] No nesting > 2 levels
[ ] Tailwind classes use cn() for conditionals
[ ] Component has single responsibility
[ ] Logic extracted to custom hook if >3 useState/useEffect
[ ] Files follow naming convention for the project
Provides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.
npx claudepluginhub jjmendezrodriguez/jm-claude-plugin --plugin jm-claude-plugin