← Back to list

convex-patterns
by Atemndobs
⭐ 0🍴 0📅 Jan 16, 2026
SKILL.md
name: convex-patterns description: Backend patterns for Convex serverless database including schema definitions, queries, mutations, indexes, and Clerk authentication integration. Use for database operations, API endpoints, auth checks. allowed-tools: Read, Grep, Glob, Edit, Write
Convex Patterns Skill
Guidance for implementing Convex backend patterns in Fireside Tribe.
Schema Definition
Define tables in convex/schema.ts:
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
export default defineSchema({
episodes: defineTable({
title: v.string(),
description: v.optional(v.string()),
youtubeId: v.string(),
thumbnail: v.optional(v.string()),
publishedAt: v.string(),
duration: v.optional(v.string()),
autoSynced: v.optional(v.boolean()),
}).index("by_youtube_id", ["youtubeId"]),
artists: defineTable({
name: v.string(),
bio: v.optional(v.string()),
image: v.optional(v.string()),
socialLinks: v.optional(v.object({
instagram: v.optional(v.string()),
spotify: v.optional(v.string()),
youtube: v.optional(v.string()),
})),
}),
});
Query Patterns
Public Query (No Auth)
import { query } from "./_generated/server";
export const listEpisodes = query({
args: {},
handler: async (ctx) => {
return await ctx.db
.query("episodes")
.order("desc")
.take(20);
},
});
Query with Arguments
export const getEpisodeByYoutubeId = query({
args: { youtubeId: v.string() },
handler: async (ctx, args) => {
return await ctx.db
.query("episodes")
.withIndex("by_youtube_id", (q) => q.eq("youtubeId", args.youtubeId))
.first();
},
});
Protected Query (Requires Auth)
export const getAdminStats = query({
args: {},
handler: async (ctx) => {
const identity = await ctx.auth.getUserIdentity();
if (!identity) {
throw new Error("Unauthorized");
}
// Admin-only logic
},
});
Mutation Patterns
Basic Mutation
import { mutation } from "./_generated/server";
export const createEpisode = mutation({
args: {
title: v.string(),
youtubeId: v.string(),
description: v.optional(v.string()),
},
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();
if (!identity) throw new Error("Unauthorized");
return await ctx.db.insert("episodes", {
...args,
publishedAt: new Date().toISOString(),
autoSynced: false,
});
},
});
Update Mutation
export const updateEpisode = mutation({
args: {
id: v.id("episodes"),
title: v.optional(v.string()),
description: v.optional(v.string()),
},
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();
if (!identity) throw new Error("Unauthorized");
const { id, ...updates } = args;
const filtered = Object.fromEntries(
Object.entries(updates).filter(([_, v]) => v !== undefined)
);
await ctx.db.patch(id, filtered);
return id;
},
});
Delete Mutation
export const deleteEpisode = mutation({
args: { id: v.id("episodes") },
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();
if (!identity) throw new Error("Unauthorized");
await ctx.db.delete(args.id);
},
});
Frontend Integration
Using Queries
import { useQuery } from "convex/react";
import { api } from "@/convex/_generated/api";
export function EpisodesList() {
const episodes = useQuery(api.episodes.listEpisodes);
if (episodes === undefined) return <Loading />;
if (episodes.length === 0) return <EmptyState />;
return episodes.map((ep) => <EpisodeCard key={ep._id} episode={ep} />);
}
Using Mutations
import { useMutation } from "convex/react";
import { api } from "@/convex/_generated/api";
export function CreateEpisodeForm() {
const createEpisode = useMutation(api.episodes.createEpisode);
const handleSubmit = async (data: FormData) => {
await createEpisode({
title: data.title,
youtubeId: data.youtubeId,
});
};
}
Clerk Auth Integration
Convex is configured with Clerk in convex/auth.config.ts. The ctx.auth.getUserIdentity() call returns the Clerk user identity with fields:
tokenIdentifier- Unique user IDname- User's nameemail- User's email (if available)
Score
Total Score
50/100
Based on repository quality metrics
✓SKILL.md
SKILL.mdファイルが含まれている
+20
○LICENSE
ライセンスが設定されている
0/10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
○最近の活動
3ヶ月以内に更新がある
0/10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
○タグ
1つ以上のタグが設定されている
0/5
Reviews
💬
Reviews coming soon