Skip to main content

kitcn

Use for Convex/kitcn setup and feature work: cRPC, ORM, auth, React.

소스 정보

저장소
udecode/kitcn
최근 소스 활동
2026년 10월 10일 22:26
감지된 SKILL.md 언어
영어
스타
452
포크
35

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
23 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
kitcn
description
Use for Convex/kitcn setup and feature work: cRPC, ORM, auth, React.
sources
["www/content/docs/concepts.mdx","www/content/docs/orm/index.mdx","www/content/docs/orm/schema/relations.mdx","www/content/docs/orm/schema/triggers.mdx","www/content/docs/orm/queries/aggregates.mdx","www/content/docs/orm/queries/pagination.mdx","www/content/docs/server/error-handling.mdx","www/content/docs/server/http.mdx","www/content/docs/server/middlewares.mdx","www/content/docs/server/procedures.mdx","www/content/docs/server/server-side-calls.mdx","www/content/docs/react/queries.mdx","www/content/docs/react/mutations.mdx","www/content/docs/react/infinite-queries.mdx","www/content/docs/auth/client.mdx","www/content/docs/auth/server.mdx"]
# kitcn Core Skill (80% Path) Use this file first for everyday feature delivery in an already configured kitcn app. - If setup/bootstrap/env/auth wiring or project structure mirroring is missing, use `references/setup/index.md` (then the relevant setup file). - If the task is advanced or niche, load only the specific feature reference listed at the end. ## Scope In scope: - Add or update schema tables, indexes, relations, and triggers. - Implement cRPC procedures (`query`, `mutation`, `action`, `httpAction`) with runtime auth + rate limits. - Implement feature UI with `useCRPC()` + TanStack Query. - Add minimal high-value tests for auth, errors, and side effects. Out of scope: - Greenfield setup/install/env/bootstrap. - Full plugin deep-dives (admin/organizations/polar). - Internal package-level parity testing. ## Skill Contract 1. Favor `ctx.orm` for app data access. 2. Keep list/read paths bounded and index-aware. 3. Use cRPC builders and middleware; avoid raw handler objects for new feature code. 4. Use `CRPCError` for expected failures. 5. Prefer schema triggers for cross-row invariants, but move invariant maintenance to explicit mutation helpers if trigger execution is unstable (for example init/seed hangs or recursive write paths). 6. Keep auth/rate-limit checks server-side. 7. **Inter-procedure calls**: use generated runtime helpers: `create<Module>Handler(ctx)` in queries/mutations, `create<Module>Caller(ctx)` in actions/HTTP routes, `caller.actions.*` for action procedures, and `caller.schedule.*` for scheduling. Never call `ctx.runQuery`/`ctx.runMutation`/`ctx.runAction` directly for module procedures. ## Shortcut Mode (tRPC + Drizzle Mental Model) Default assumption: - cRPC behavior is tRPC-like (builder chain + middleware + TanStack options). - ORM behavior is Drizzle-like (schema, relations, `findMany/findFirst`, `insert/update/delete`). Only remember these non-parity deltas: 1. Procedure input root must be `z.object(...)` (no primitive root args). 2. No `z.void()` outputs; omit `.output(...)` for no-value mutations. 3. `.output(...)` parses the handler's value as-is and substitutes nothing: a handler must return the schema's *input* type, so `z.string().nullable()` needs an explicit `null` (`?? null`), not `undefined`. Model absent values as `.nullable()`, never a top-level `.optional()` — Convex wires `undefined` as `null` and cannot express top-level optionality, so `.output(z.string().optional())` publishes `v.string()` and the deployment rejects the `null` whenever the handler returns `undefined`. `.optional()` inside an object is fine. The low-level `returns:` option on `zCustomQuery`/`zCustomMutation`/`zCustomAction` differs — it substitutes `null` for `undefined` before parsing. 4. Stacked `.input(...)` calls merge input shapes. 5. `.paginated({ limit, item })` must be before `.query()` and adds `input.cursor`, `input.endCursor`, and `input.limit`; pass all three to ORM cursor queries so live splits stay bounded. 6. Metadata is codegen’d onto `@convex/api` leaves (`api.namespace.fn.meta`) so never put secrets in `.meta(...)`; chaining `.meta(...)` is shallow merge and supports `defaultMeta`. 7. Auth metadata drives client behavior: `auth: "optional"` waits for auth load then runs, `auth: "required"` waits then skips when logged out. 8. `ctx.orm` enforces constraints + RLS; `ctx.db` bypasses them. 9. Non-paginated `findMany()` must be explicitly sized (`limit`, cursor mode, schema `defaultLimit`, or explicit `allowFullScan`). 10. Predicate `where` requires explicit `.withIndex(...)`; no implicit full scan fallback. 11. Cursor pagination uses the first `orderBy` field; index that field for stable paging. 12. `maxScan` applies to cursor mode only; `allowFullScan` is for non-cursor full-scan opt-in. 13. String operators / `columns` projection / many-relation subfilters can run post-fetch; bound result size early. 14. Search mode is relevance-ordered and does not support `orderBy`; vector mode has stricter limits (no cursor/offset/top-level where/order). 15. Update/delete without `where` throws unless `allowFullScan()`. 16. `count()`, `aggregate()`, and `groupBy()` require a matching `aggregateIndex`. Use `groupBy({ by, _count, _sum })` instead of multiple `.count()` calls or `findMany` + manual JS grouping. Every `by` field must be finite-constrained (`eq`/`in`/`isNull`) in `where`. See `references/features/aggregates.md`. 17. cRPC React queries are real-time by default (`subscribe: true`); never use `queryClient.invalidateQueries` for these subscribed paths. 18. In RSC, `prefetch` hydrates client, `caller` is server-only and not hydrated, `preloadQuery` hydrates but can cause stale split ownership if also rendered client-side. 19. Better Auth Next.js shortcut is `convexBetterAuth(...)`; generic server-only shortcut is `createCallerFactory(...)`. 20. On the kitcn auth client path, use `createAuthMutations(authClient)` wrappers so logout unsubscribes auth queries before sign out. Raw Convex preset keeps a smaller plain `authClient`. 21. **NEVER** use `ctx.runQuery`/`ctx.runMutation`/`ctx.runAction` directly for module-to-module calls. Use the generated runtime helpers from `convex/functions/generated/<module>.runtime`. 22. **`create<Module>Handler(ctx)`** is the default in queries/mutations: zero overhead, query/mutation ctx only, and no redundant validation or middleware. 23. **`create<Module>Caller(ctx)`** is for actions and HTTP routes. Action procedures live under `caller.actions.*`; scheduling lives under `caller.schedule.now|after|at|cancel`. Use `requireActionCtx(ctx)` only for true `ActionCtx` callbacks; use `requireSchedulerCtx(ctx)` when mutation or action contexts can schedule. Each caller/handler eagerly loads its module, so split large modules. 24. API types (`Api`, `ApiInputs`, `ApiOutputs`, `Select`, `Insert`, `TableName`) import from `@convex/api` — no manual `inferApiInputs<typeof api>`. 25. HTTP router must export as `httpRouter` (not `appRouter`) for codegen. 26. Server wiring imports come from `convex/functions/generated/` directory: `getAuth`, `defineAuth` from `generated/auth`; `initCRPC`, `QueryCtx`, `MutationCtx`, `OrmCtx` from `generated/server`; `create<Module>Caller`, `create<Module>Handler` from `generated/<module>.runtime`. No manual `convex/lib/orm.ts`. 27. `defineAuth(() => ({ ...options, triggers }))` replaces split `getAuthOptions` + `authTriggers`. Trigger callbacks are doc-first: `beforeCreate(data)`, `onCreate(doc)`, `onUpdate(newDoc, oldDoc)` — no `ctx` first param. 28. Internal auth functions at `internal.generated.*` (not `internal.auth.*`). 29. Async mutation batching is the default (codegen wires it). Customize per call: `execute({ batchSize, delayMs })`. Opt into sync: `execute({ mode: 'sync' })` or `defineSchema(..., { defaults: { mutationExecutionMode: 'sync' } })`. Relevant defaults: `mutationBatchSize`, `mutationLeafBatchSize`, `mutationMaxRows`, `mutationScheduleCallCap`. 30. Polymorphic unions are schema-first: use `actionType: discriminator({ variants, as? })` in `convexTable(...)`. Query config does not include a `polymorphic` option. Writes stay flat; reads synthesize nested `details` (or custom alias). Use `withVariants: true` to auto-load all `one()` relations on discriminator tables. 31. Do not add manual ORM mutation batching loops in app/plugin code by default. Convex runtime batching already handles mutation execution. Prefer set-based deletes/updates over per-row loops. Only add explicit chunking when batching external side effects (for example Resend API calls) or bounded cleanup sweeps. ## Directory Boundary Use `references/setup/` when the task needs: 1. Project/file structure setup → `setup/index.md` + `setup/server.md` 2. Auth bootstrap → `setup/auth.md` 3. Client/provider wiring → `setup/react.md` 4. Framework-specific setup → `setup/next.md` or `setup/start.md` For full template-level recreation: start with `setup/index.md`, then load relevant setup files, then load selected feature refs. ## First-Pass Feature Intake (Do This Before Edits) Lock these decisions first: 1. Auth level per endpoint: `public` / `optionalAuth` / `auth` / `private`. 2. Data invariants: what must always be true after writes? 3. Query shape: list, detail, relation-loaded, search, or stream composition. 4. Pagination mode: offset, cursor, infinite. 5. Side effects: trigger vs scheduled function vs inline mutation. 6. UI consumption: client hook only, RSC prefetch, or server-only caller. 7. Risk paths: unauthorized, forbidden, not found, conflicts, rate limit. ## Canonical File Targets Typical feature touches: - `convex/functions/schema.ts` - `convex/functions/<feature>.ts` - `convex/lib/crpc.ts` (only if middleware/procedure builder changes) - `src/lib/convex/crpc.tsx` (only if cRPC context/meta wiring changes) - `src/**` feature UI files - `convex/functions/http.ts` or `convex/routers/**` for HTTP endpoints - `convex/functions/crons.ts` or scheduled handlers if needed ## E2E Build Order (Default) 1. Schema + indexes + relations. 2. Trigger hooks for cross-row invariants (or explicit mutation-side sync if trigger path is unstable). 3. Procedures with strict input/output + auth + rate limits. 4. React hooks (query/mutation/infinite) using cRPC options. 5. Optional: HTTP route(s), scheduling hooks. 6. Tests for auth/error/trigger behavior. ## Core Patterns ### 1) Schema + Relations + Trigger ```ts import { convexTable, defineSchema, id, integer, index, text, timestamp, } from "kitcn/orm"; export const project = convexTable( "project", { name: text().notNull(), ownerId: id("user").notNull(), updatedAt: timestamp() .notNull() .defaultNow() .$onUpdateFn(() => new Date()), }, (t) => [index("ownerId_updatedAt").on(t.ownerId, t.updatedAt)] ); export const task = convexTable( "task", { projectId: id("project").notNull(), title: text().notNull(), status: text().notNull().default("open"), updatedAt: timestamp() .notNull() .defaultNow() .$onUpdateFn(() => new Date()), }, (t) => [index("projectId_updatedAt").on(t.projectId, t.updatedAt)] ); export default defineSchema({ project, task }) .relations((r) => ({ project: { tasks: r.many.task(), }, task: { project: r.one.project({ from: r.task.projectId, to: r.project.id }), }, })) .triggers({ task: { change: async (change, ctx) => { const projectId = change.newDoc?.projectId ?? change.oldDoc?.projectId; if (!projectId) return; const open = await ctx.orm.query.task.findMany({ where: { projectId, status: "open" }, columns: { id: true }, limit: 500, }); await ctx.orm.update(project).set({ openTaskCount: open.length }); }, }, }); ``` Schema rules that matter: 1. Index fields that power filters/order/search. 2. `many()` relation paths need child FK indexes. 3. Trigger logic must be bounded and non-recursive. 4. Use table defaults for consistent write behavior. 5. Keep full ORM/query edge cases in `references/features/orm.md`. ### 2) Procedure Builders + Middleware ```ts import { getSession } from "kitcn/auth"; import { CRPCError } from "kitcn/server"; import { initCRPC, type QueryCtx } from "../functions/generated/server"; const c = initCRPC .meta<{ auth?: "optional" | "required"; role?: "admin"; ratelimit?: string; }>() .create(); function requireAuth<T>(user: T | null): T { if (!user) { throw new CRPCError({ code: "UNAUTHORIZED", message: "Not authenticated" }); } return user; } async function getSessionUser(ctx: QueryCtx) { const session = await getSession(ctx); if (!session) return null; return await ctx.orm.query.user.findFirst({ where: { id: { eq: session.userId } }, }); } export const publicQuery = c.query.meta({ auth: "optional" }); export const authQuery = c.query .meta({ auth: "required" }) .use(async ({ ctx, next }) => { const user = requireAuth(await getSessionUser(ctx)); return next({ ctx: { ...ctx, user, userId: user.id } }); }); export const authMutation = c.mutation .meta({ auth: "optional" }) .use(async ({ ctx, next }) => { const user = await getSessionUser(ctx); return next({ ctx: { ...ctx, user, userId: user?.id ?? null }, }); }); ``` Builder rules that matter: 1. Build `public`, `optional`, `auth`, and `private` procedure families once in `convex/lib/crpc.ts`. Authenticated action builders live in `convex/lib/crpc-action.ts`, the only builder module that imports `getAuth`. 2. `.meta(...)` is client-visible via generated API metadata. Never put secrets there. 3. Middleware receives server-only `procedure` info. When procedures are built from your app `generated/server` helper, standard `export const` queries, mutations, and actions infer `module:function` automatically from file path + export name. Use `.name("module:function")` only to override or cover unusual export shapes. 4. Resolve session/user once in middleware. Do not re-fetch auth state in every procedure. Query/mutation middleware uses `getSession(ctx)` from `kitcn/auth`, which reads the session row directly. Keep `getAuth(ctx)` out of `convex/lib/crpc.ts`: it pulls the whole Better Auth definition and every auth plugin into the static import closure of every procedure module, and Convex has no dynamic `import()` to escape it. Import `getAuth` only in the modules that call `auth.api.*` — `convex/lib/crpc-action.ts`, HTTP routes, and organization/admin mutations.
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기