Claude Code Plugins

Community-maintained marketplace

Feedback

mymind-coding-patterns

@vojtaholik/mymind
1
0

Coding conventions and patterns for the mymind codebase. Use this skill when writing or modifying any code in this project to ensure consistency with established patterns.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name mymind-coding-patterns
description Coding conventions and patterns for the mymind codebase. Use this skill when writing or modifying any code in this project to ensure consistency with established patterns.

MyMind Coding Patterns

Stack

  • Runtime: Bun
  • Framework: Next.js 15 (App Router)
  • Database: PGlite (PostgreSQL) with pgvector for embeddings
  • ORM: Drizzle
  • Validation: Zod (preferred over type casting)
  • Formatting: Biome (2 spaces, organize imports)

Skills (Tools)

Skills are executable tools that Claude can call. They live in src/skills/.

Defining a Skill

import { z } from "zod";
import { defineSkill, type SkillResult } from "./types";

const MyParamsSchema = z.object({
  input: z.string().describe("Description for Claude"),
  optional: z.number().optional(),
});

type MyParams = z.infer<typeof MyParamsSchema>;

interface MyResult {
  // typed result
}

export const mySkill = defineSkill({
  name: "my_skill", // snake_case
  description: "What this skill does and when to use it",
  parameters: MyParamsSchema,

  async execute(params: MyParams): Promise<SkillResult<MyResult>> {
    try {
      // do the thing
      return {
        success: true,
        data: { /* result */ },
        message: "Human-readable success message",
      };
    } catch (error) {
      const message = error instanceof Error ? error.message : String(error);
      return {
        success: false,
        error: `Failed to do thing: ${message}`,
      };
    }
  },
});

export default mySkill;

Registering Skills

Add new skills to src/skills/index.ts:

import { mySkill } from "./my-skill";

const skills: Skill[] = [
  // ... existing
  mySkill,
];

export { mySkill } from "./my-skill";

Database Access

Always use withDb() wrapper - it handles connection lifecycle:

import { withDb } from "@/db/client";
import { items, tags } from "@/db/schema";
import { eq } from "drizzle-orm";

const result = await withDb(async ({ db }) => {
  const rows = await db
    .select()
    .from(items)
    .where(eq(items.type, "bookmark"))
    .limit(10);
  return rows;
});

Schema Types

Use Drizzle's inferred types:

import { type Item, type NewItem } from "@/db/schema";

// Item = select type (has id, createdAt, etc.)
// NewItem = insert type (id optional, etc.)

API Routes

Request Validation

Always use Zod .parse() - never type cast:

// ✅ Good
const params = MySchema.parse(await request.json());

// ❌ Bad - no runtime validation
const params = (await request.json()) as MyParams;

Response Shape

// Success
return NextResponse.json({
  success: true,
  items: result.data,
  total: result.total,
});

// Error
return NextResponse.json(
  { success: false, error: "What went wrong" },
  { status: 400 }
);

Zod Error Handling

try {
  const params = Schema.parse(body);
  // ...
} catch (error) {
  if (error instanceof z.ZodError) {
    return NextResponse.json(
      { success: false, error: error.issues },
      { status: 400 }
    );
  }
  throw error;
}

Imports

Use path alias for src:

// ✅ Good
import { withDb } from "@/db/client";
import { saveBookmark } from "@/skills";

// ❌ Avoid relative paths across directories
import { withDb } from "../../../db/client";

Naming Conventions

Thing Convention Example
Skill names snake_case save_bookmark, list_items
Functions camelCase scrapeUrl, extractText
Types/Interfaces PascalCase SkillResult, ItemMetadata
Files kebab-case save-bookmark.ts, list-items.ts
Zod schemas PascalCase + Schema SaveBookmarkSchema

Don't

  • Don't use type casting (as) for external data - validate with Zod
  • Don't create DB connections manually - use withDb()
  • Don't use any - prefer unknown with narrowing
  • Don't forget to add .describe() on Zod fields for tool schemas