diff --git a/.claude/skills/api/SKILL.md b/.claude/skills/api/SKILL.md new file mode 100644 index 0000000..5e15d9a --- /dev/null +++ b/.claude/skills/api/SKILL.md @@ -0,0 +1,98 @@ +--- +name: api +description: "Next.js API route handler olusturur (App Router). Triggers: api, endpoint, route handler, REST, GET, POST, PUT, DELETE, CRUD, backend, server action." +argument-hint: route-yolu - Aciklama ve HTTP metodlari +--- + +Asagidaki bilgilere gore bir Next.js API route handler olustur: + +$ARGUMENTS + +## Kurallar + +### Dosya Konumu +- Route handler: `app/api/[route-yolu]/route.ts` +- Ic ice route: `app/api/[ust]/[alt]/route.ts` +- Dinamik route: `app/api/[route]/[id]/route.ts` + +### Route Handler Yapisi +```ts +import { NextRequest, NextResponse } from "next/server"; + +export async function GET(request: NextRequest) { + try { + return NextResponse.json({ data }, { status: 200 }); + } catch (error) { + console.error("[GET /api/route]:", error); + return NextResponse.json({ error: "Sunucu hatasi" }, { status: 500 }); + } +} + +export async function POST(request: NextRequest) { + try { + const body = await request.json(); + return NextResponse.json({ data }, { status: 201 }); + } catch (error) { + console.error("[POST /api/route]:", error); + return NextResponse.json({ error: "Sunucu hatasi" }, { status: 500 }); + } +} +``` + +### Dinamik Route Handler +```ts +import { NextRequest, NextResponse } from "next/server"; + +interface RouteParams { + params: Promise<{ id: string }>; +} + +export async function GET(request: NextRequest, { params }: RouteParams) { + const { id } = await params; + try { + return NextResponse.json({ data }, { status: 200 }); + } catch (error) { + console.error(`[GET /api/route/${id}]:`, error); + return NextResponse.json({ error: "Kayit bulunamadi" }, { status: 404 }); + } +} + +export async function PUT(request: NextRequest, { params }: RouteParams) { + const { id } = await params; + const body = await request.json(); + try { + return NextResponse.json({ data }, { status: 200 }); + } catch (error) { + console.error(`[PUT /api/route/${id}]:`, error); + return NextResponse.json({ error: "Sunucu hatasi" }, { status: 500 }); + } +} + +export async function DELETE(request: NextRequest, { params }: RouteParams) { + const { id } = await params; + try { + return NextResponse.json({ message: "Basariyla silindi" }, { status: 200 }); + } catch (error) { + console.error(`[DELETE /api/route/${id}]:`, error); + return NextResponse.json({ error: "Sunucu hatasi" }, { status: 500 }); + } +} +``` + +### Zorunlu Kurallar +1. **Server-only**: `"use client"` KULLANMA +2. **TypeScript**: Request body, response ve params icin tip tanimla +3. **Next.js 16 params**: `params` artik `Promise` - `await` ile eris +4. **Hata yonetimi**: Her handleri try/catch ile sar +5. **HTTP status kodlari**: Dogru kodlari kullan (200, 201, 400, 404, 500) +6. **Loglama**: Hatalarda `console.error` ile endpoint bilgisini logla +7. **Validasyon**: POST/PUT bodysini islemeden once dogrula + +### Query Parameter Okuma +```ts +export async function GET(request: NextRequest) { + const searchParams = request.nextUrl.searchParams; + const page = parseInt(searchParams.get("page") || "1", 10); + const limit = parseInt(searchParams.get("limit") || "10", 10); +} +``` diff --git a/.claude/skills/component/SKILL.md b/.claude/skills/component/SKILL.md new file mode 100644 index 0000000..df3e253 --- /dev/null +++ b/.claude/skills/component/SKILL.md @@ -0,0 +1,105 @@ +--- +name: component +description: "React component olusturur. Triggers: component, button, card, modal, input, badge, sidebar, navbar, header, footer, UI element, widget, bilesen olustur." +argument-hint: ComponentAdi - Kisa aciklama +--- + +Asagidaki bilgilere gore bir React component olustur: + +$ARGUMENTS + +## Kurallar + +### Dosya Konumu +- Temel UI componenti ise (Button, Input, Card, Modal, Badge...): `components/ui/ComponentAdi.tsx` +- Ozellige ozel component ise: `components/ComponentAdi.tsx` +- Eger aciklamada farkli bir konum belirtilmisse, onu kullan + +### Component Yapisi +```tsx +// Gerekli ise "use client" en uste ekle (useState, useEffect, event handler varsa) + +interface ComponentAdiProps { + // Props tanimla +} + +export default function ComponentAdi({ ...props }: ComponentAdiProps) { + return ( + // JSX + ); +} +``` + +### Zorunlu Kurallar +1. **TypeScript**: Props icin interface tanimla, `any` kullanma +2. **Tailwind CSS**: Stil icin sadece Tailwind classlari kullan, inline style veya CSS module kullanma +3. **Server Component varsayilan**: `"use client"` sadece interaktivite gerekiyorsa ekle +4. **Default export** kullan +5. **Dosya adi** PascalCase olmali +6. **Responsive**: Mobile-first yaklasim, `sm:`, `md:`, `lg:` breakpointleri kullan +7. **Dark mode**: `dark:` prefix ile karanlik tema destegi ekle +8. **Erisilebilirlik**: Uygun ARIA attributeleri, semantik HTML etiketleri kullan +9. **Import path**: `@/` alias kullan (ornek: `@/components/ui/Button`) + +### Props Tasarimi +- Opsiyonel proplar icin `?` kullan +- `className` propu kabul et (kullanicinin stil ekleyebilmesi icin) +- Event handlerlar icin uygun React tipi kullan (`React.MouseEvent`, `React.ChangeEvent` vb.) +- children propu gerekliyse `React.ReactNode` tipinde tanimla + +### Ornek Cikti Yapisi +Eger `/component Button - Tiklanabilir buton componenti, variant ve size destegi` yazildiysa: + +```tsx +"use client"; + +interface ButtonProps { + children: React.ReactNode; + variant?: "primary" | "secondary" | "outline" | "ghost"; + size?: "sm" | "md" | "lg"; + disabled?: boolean; + className?: string; + onClick?: React.MouseEventHandler; +} + +export default function Button({ + children, + variant = "primary", + size = "md", + disabled = false, + className = "", + onClick, +}: ButtonProps) { + const baseStyles = + "inline-flex items-center justify-center rounded-lg font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none"; + + const variants = { + primary: "bg-foreground text-background hover:bg-foreground/90 focus:ring-foreground", + secondary: + "bg-zinc-100 text-zinc-900 hover:bg-zinc-200 dark:bg-zinc-800 dark:text-zinc-100 dark:hover:bg-zinc-700", + outline: "border border-zinc-300 hover:bg-zinc-100 dark:border-zinc-700 dark:hover:bg-zinc-800", + ghost: "hover:bg-zinc-100 dark:hover:bg-zinc-800", + }; + + const sizes = { + sm: "h-8 px-3 text-sm", + md: "h-10 px-4 text-base", + lg: "h-12 px-6 text-lg", + }; + + return ( + + ); +} +``` + +Dosyayi olusturduktan sonra kullaniciya bilgi ver: +- Dosya yolu +- Kullanim ornegi (import + JSX) +- Eklenen proplarin listesi diff --git a/.claude/skills/form/SKILL.md b/.claude/skills/form/SKILL.md new file mode 100644 index 0000000..7332fcb --- /dev/null +++ b/.claude/skills/form/SKILL.md @@ -0,0 +1,105 @@ +--- +name: form +description: "Validasyonlu form componenti olusturur. Triggers: form, login, register, signup, giris, kayit, contact form, input, validasyon, submit, form olustur." +argument-hint: FormAdi - Form alanlari ve aciklama +--- + +Asagidaki bilgilere gore validasyonlu bir form componenti olustur: + +$ARGUMENTS + +## Kurallar + +### Dosya Konumu +- Form componentleri: `components/forms/FormAdi.tsx` + +### Form Yapisi +```tsx +"use client"; + +import { useState, type FormEvent } from "react"; + +interface FormAdiData { + // Form alanlari +} + +interface FormAdiErrors { + // Hata alanlari (her alan opsiyonel string) +} + +interface FormAdiProps { + onSubmit: (data: FormAdiData) => void | Promise; + className?: string; +} + +export default function FormAdi({ onSubmit, className = "" }: FormAdiProps) { + const [formData, setFormData] = useState({}); + const [errors, setErrors] = useState({}); + const [isSubmitting, setIsSubmitting] = useState(false); + + function validate(data: FormAdiData): FormAdiErrors { + const newErrors: FormAdiErrors = {}; + return newErrors; + } + + async function handleSubmit(e: FormEvent) { + e.preventDefault(); + const validationErrors = validate(formData); + setErrors(validationErrors); + if (Object.keys(validationErrors).length > 0) return; + setIsSubmitting(true); + try { + await onSubmit(formData); + } catch { + } finally { + setIsSubmitting(false); + } + } + + return ( +
+ {/* Form alanlari */} +
+ ); +} +``` + +### Zorunlu Kurallar +1. **"use client"**: Formlar her zaman client component +2. **TypeScript**: Form data ve error tipleri icin interface tanimla +3. **Tailwind CSS**: Tum stiller Tailwind ile +4. **Validasyon**: Client-side validasyon ZORUNLU +5. **Hata gosterimi**: Her alanin altinda hata mesaji goster +6. **Loading durumu**: Submit sirasinda buton disabled + yukleniyor gostergesi +7. **Erisilebilirlik**: `