← Back to list
Use

create-model
by tech-with-seth
React Router 7 starter with Polar.sh, BetterAuth, Prisma, and Tailwind
⭐ 1🍴 0📅 Jan 25, 2026
SKILL.md
name: create-model description: Create Prisma model layer functions. Use when adding database operations. Never call Prisma directly in routes.
Create Model
Creates model layer functions for database operations. All database access MUST go through the model layer.
When to Use
- Adding any database operations
- Creating, reading, updating, or deleting data
- User asks to "add database functions" or "create model"
Critical Rules
1. Never Call Prisma Directly in Routes
// ❌ NEVER do this in routes
const user = await prisma.user.findUnique({ where: { id } });
// ✅ ALWAYS do this
import { getUserById } from '~/models/user.server';
const user = await getUserById(id);
2. Use Correct Import Paths
// ✅ CORRECT
import { prisma } from '~/db.server';
import type { User, Role } from '~/generated/prisma/client';
// ❌ NEVER
import { PrismaClient } from '@prisma/client';
3. File Naming
app/models/[feature].server.ts
The .server.ts suffix ensures the code only runs on the server.
Model Layer Template
Location: app/models/[feature].server.ts
import { prisma } from '~/db.server';
import type { Item } from '~/generated/prisma/client';
// ============================================
// READ Operations
// ============================================
/**
* Get a single item by ID
*/
export function getItem(id: string) {
return prisma.item.findUnique({
where: { id },
select: {
id: true,
name: true,
description: true,
userId: true,
createdAt: true,
updatedAt: true,
},
});
}
/**
* Get all items for a user
*/
export function getItemsByUser(userId: string) {
return prisma.item.findMany({
where: { userId },
orderBy: { createdAt: 'desc' },
});
}
/**
* Get items with pagination
*/
export async function getItemsPaginated(
userId: string,
page: number = 1,
pageSize: number = 10
) {
const [items, total] = await Promise.all([
prisma.item.findMany({
where: { userId },
skip: (page - 1) * pageSize,
take: pageSize,
orderBy: { createdAt: 'desc' },
}),
prisma.item.count({ where: { userId } }),
]);
return {
items,
pagination: {
page,
pageSize,
total,
totalPages: Math.ceil(total / pageSize),
},
};
}
// ============================================
// CREATE Operations
// ============================================
/**
* Create a new item
*/
export function createItem(
userId: string,
data: { name: string; description?: string }
) {
return prisma.item.create({
data: {
...data,
userId,
},
});
}
// ============================================
// UPDATE Operations
// ============================================
/**
* Update an existing item
*/
export function updateItem(
id: string,
data: Partial<{ name: string; description: string }>
) {
return prisma.item.update({
where: { id },
data,
});
}
// ============================================
// DELETE Operations
// ============================================
/**
* Delete an item
*/
export function deleteItem(id: string) {
return prisma.item.delete({
where: { id },
});
}
/**
* Delete all items for a user
*/
export function deleteItemsByUser(userId: string) {
return prisma.item.deleteMany({
where: { userId },
});
}
Common Patterns
Use select for Type Safety
export function getUser(id: string) {
return prisma.user.findUnique({
where: { id },
select: {
id: true,
email: true,
name: true,
// Exclude sensitive fields like password
},
});
}
Include Related Data
export function getPostWithComments(id: string) {
return prisma.post.findUnique({
where: { id },
include: {
author: true,
comments: {
include: { author: true },
orderBy: { createdAt: 'desc' },
},
},
});
}
Transactions
export async function transferCredits(fromId: string, toId: string, amount: number) {
return prisma.$transaction(async (tx) => {
await tx.user.update({
where: { id: fromId },
data: { credits: { decrement: amount } },
});
await tx.user.update({
where: { id: toId },
data: { credits: { increment: amount } },
});
});
}
Upsert
export function upsertSettings(userId: string, data: SettingsData) {
return prisma.settings.upsert({
where: { userId },
update: data,
create: { ...data, userId },
});
}
After Schema Changes
- Run
npx prisma migrate dev --name description - Run
npx prisma generate - Restart dev server
Anti-Patterns
- ❌ Calling Prisma directly in routes
- ❌ Importing from
@prisma/client - ❌ Creating new PrismaClient instances
- ❌ N+1 queries (fetching in loops)
- ❌ Exposing sensitive data
- ❌ Missing
.server.tssuffix
Templates
Full Reference
See .github/instructions/prisma.instructions.md for comprehensive documentation.
Score
Total Score
65/100
Based on repository quality metrics
✓SKILL.md
SKILL.mdファイルが含まれている
+20
✓LICENSE
ライセンスが設定されている
+10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
✓最近の活動
1ヶ月以内に更新
+10
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
✓タグ
1つ以上のタグが設定されている
+5
Reviews
💬
Reviews coming soon

