원클릭으로
convex-crud-page
Scaffold a full CRUD page with Convex schema, queries/mutations, API proxy route, and shadcn/ui React components.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Scaffold a full CRUD page with Convex schema, queries/mutations, API proxy route, and shadcn/ui React components.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.
Build a full eve agent with tools, connections, skills, channels, subagents, sandbox — systematic scaffolding with known gotchas.
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.
Refactor bloated AGENTS.md, CLAUDE.md, or similar agent instruction files to follow progressive disclosure principles. Splits monolithic files into organized, linked documentation.
Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
| name | convex-crud-page |
| description | Scaffold a full CRUD page with Convex schema, queries/mutations, API proxy route, and shadcn/ui React components. |
| source | auto-skill |
Create a complete CRUD feature page in a Next.js + Convex + shadcn/ui app. Follows the proxy pattern: Client → API route → Convex HTTP endpoint.
convex/
schema.ts — add table definition
<entity>.ts — queries + mutations
src/app/api/<entity>/route.ts — API proxy
src/components/<entity>/ — React UI components
src/app/<entity>/page.tsx — page route
Add a table to convex/schema.ts:
<entity>: defineTable({
field1: v.string(),
field2: v.number(),
// ...
createdAt: v.number(),
updatedAt: v.number(),
}).index("by_createdAt", ["createdAt"])
Use v.id("otherTable") for foreign keys, v.optional() for nullable fields.
Create convex/<entity>.ts:
import { query, mutation } from "./_generated/server";
import { v } from "convex/values";
// Queries (read, no side effects)
export const list = query({ args: {}, handler: async (ctx) => { ... } });
export const get = query({ args: { id: v.id("<entity>") }, handler: async (ctx, args) => { ... } });
export const search = query({ args: { query: v.string() }, handler: async (ctx, args) => { ... } });
// Mutations (write)
export const save = mutation({ args: { ... }, handler: async (ctx, args) => { ... } });
export const remove = mutation({ args: { id: v.id("<entity>") }, handler: async (ctx, args) => { ... } });
Key: The function name (e.g., list) maps to the Convex HTTP endpoint path (/api/list). The full path used in the proxy is /api/<entity>FunctionName.
Create src/app/api/<entity>/route.ts:
import { NextRequest, NextResponse } from "next/server";
import { CONVEX_URL } from "@/lib/agent/lib/env";
const ACTION_ENDPOINTS = {
list: "/api/list",
get: "/api/get",
search: "/api/search",
save: "/api/save",
remove: "/api/delete",
} as const;
type Action = keyof typeof ACTION_ENDPOINTS;
export async function POST(request: NextRequest) {
try {
const { action, args } = await request.json();
if (!CONVEX_URL) return NextResponse.json({ error: "CONVEX_URL not configured" }, { status: 500 });
if (!(action in ACTION_ENDPOINTS)) return NextResponse.json({ error: "Unsupported action" }, { status: 400 });
const res = await fetch(new URL(ACTION_ENDPOINTS[action as Action], CONVEX_URL), {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(args),
});
if (!res.ok) return NextResponse.json({ error: `Convex error: ${await res.text()}` }, { status: res.status });
return NextResponse.json(await res.json());
} catch (error) {
return NextResponse.json({ error: "Internal server error" }, { status: 500 });
}
}
Naming: The action keys in ACTION_ENDPOINTS must match the query/mutation function names in convex/<entity>.ts. The endpoint URL format is {CONVEX_URL}/api/<functionName>.
Create src/components/<entity>/. Common patterns:
<entity>-list.tsx)useEffect(() => { fetch("/api/<entity>", { method: "POST", body: JSON.stringify({ action: "list", args: {} }) }) }, [])animate-pulse<entity>-card.tsx)lucide-react)<entity>-uploader.tsx)onDragEnter/onDragLeave/onDrop<input type="file">Use Tailwind classes from the dark theme:
rounded-xl border border-glass-border bg-glasshover:border-neutral-700 transition-allbg-accent-teal text-black hover:bg-accent-teal-dimborder border-glass-bordertext-white, text-neutral-300, text-neutral-400, text-neutral-500hover:text-aurora-redCreate src/app/<entity>/page.tsx:
"use client";
export default function EntityPage() {
// State: items[], loading, showUpload
// fetchItems() via /api/<entity> POST
// handleCreate/Update/Delete wrappers
// return full-page layout with header + content
}
Include a back button (Link href="/" with ArrowLeft icon) in the header.
Add a link to the new page from the main page:
<Link href="/<entity>" className="..." aria-label="<Entity>">
<Icon className="size-4" />
</Link>
CONVEX_URL must be set — the proxy returns 500 if missing. Set NEXT_PUBLIC_CONVEX_URL in env.ACTION_ENDPOINTS must be the exact Convex function name (e.g., listFiles not list if that's what's in convex/files.ts).npx tsc won't work on Android ARM64. Validate by running bun typecheck on a real machine.