agentsclimarketplace

Code style

Skill jjmendezrodriguez/jm-claude-plugin/skills/code-style

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.From its SKILL.md

Install
npx -y skills add jjmendezrodriguez/jm-claude-plugin --skill code-style

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

6.0 KB, as published. Nobody here has run it

Code Style — JS / TS / React / Tailwind

Staff Engineer standard: optimize for readability at scale, not cleverness.


1. Universal Rules (all files)

✅ 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)

2. Naming Conventions

ElementConventionExample
Functions / hookscamelCase, verbgetUserData, useAuthSession
Variables / statecamelCaseisLoading, userData
ConstantsUPPER_SNAKE_CASEMAX_RETRIES, API_BASE_URL
Classes / TypesPascalCaseUserService, ApiResponse
React componentsPascalCaseUserDashboard, LoginForm
Files (TS/JS)kebab-caseuser-service.ts, auth-hook.ts
Files (components)PascalCaseUserCard.tsx, LoginForm.tsx

Pick ONE convention per project. Enforce it via ESLint.


3. TypeScript Strict Mode

// tsconfig.json — non-negotiable
{
  "strict": true,           // enables all strict checks
  "noUncheckedIndexedAccess": true,
  "exactOptionalPropertyTypes": true
}

Rules:

  • No any — use unknown + type guards if needed
  • Explicit return types on public functions
  • Prefer type over interface unless extending
  • Use discriminated unions over optional fields
// ✅ 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 };

4. Function Documentation (JSDoc)

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
}

5. Code Flow

// ✅ 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.


6. React 19+ Components

// ✅ 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:

  • Keep components under ~80 lines — extract sub-components if larger
  • Logic → custom hooks. UI → component. Never mix.
  • No inline functions in JSX props if they cause re-renders
  • Co-locate: UserCard.tsx, useUserCard.ts, UserCard.test.tsx in same folder

7. Tailwind CSS

// ✅ 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:

  • Use cn() (clsx + tailwind-merge) for conditional classes — always
  • No arbitrary values unless design token doesn't exist ([20px] → use spacing scale)
  • Extract repeated class groups into a component or @apply in global CSS (sparingly)
  • Mobile-first: base → sm: → md: → lg:

8. Deep-Dive References

references/ holds extended guides:

FileContents
tailwind-deep.md + references/Tailwind v4.1+ utilities, responsive patterns, dark mode, component variants
typescript-advanced.mdAdvanced TS: conditional types, mapped types, template literals, variance, branded types

9. Quick Checklist (before PR)

[ ] 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

Keep looking

Skills are one crate of 626,194. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.