RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/Cursor rules/sportiz91/vibe-template

Cursor rule

.cursor/rules/backend.mdc

Follow these rules when working on the backend.

Cursor rules

Quality

61/100

Scores the file, not the repository.

Length

949 words

6 headings · 11 code blocks

Repository

9

— · pushed 394 days ago

Last changed

3 days ago

First indexed 3 days ago.
sportiz91/vibe-template/.cursor/rules/backend.mdcRawGitHub
1---
2description: Follow these rules when working on the backend.
3globs:
4alwaysApply: false
5---
6### Backend Rules
7 
8Follow these rules when working on the backend.
9 
10It uses Postgres, Supabase, Drizzle ORM, and Server Actions.
11 
12#### General Rules
13 
14- Never generate migrations. You do not have to do anything in the `db/migrations` folder including migrations and metadata. Ignore it.
15 
16#### Organization
17 
18#### Schemas
19 
20- When importing schemas, use `@/db/schema`
21- Name files like `example-schema.ts`
22- All schemas should go in `db/schema`
23- Make sure to export the schema in `db/schema/index.ts`
24- Make sure to add the schema to the `schema` object in `db/db.ts`
25- If using a userId, always use `userId: text("user_id").notNull()`
26- Always include createdAt and updatedAt columns in all tables
27- Make sure to cascade delete when necessary
28- Use enums for columns that have a limited set of possible values such as:
29 
30```ts
31import { pgEnum } from "drizzle-orm/pg-core"
32 
33export const MEMBERSHIP: PgEnum<Membership> = pgEnum(
34 "membership",
35 MEMBERSHIP_VALUES
36)
37 
38membership: MEMBERSHIP("membership").notNull().default("free")
39```
40 
41Example of a schema:
42 
43`db/schema/todos-schema.ts`
44 
45```ts
46import { boolean, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core"
47 
48export const todosTable = pgTable("todos", {
49 id: uuid("id").defaultRandom().primaryKey(),
50 userId: text("user_id").notNull(),
51 content: text("content").notNull(),
52 completed: boolean("completed").default(false).notNull(),
53 createdAt: timestamp("created_at").defaultNow().notNull(),
54 updatedAt: timestamp("updated_at")
55 .defaultNow()
56 .notNull()
57 .$onUpdate(() => new Date())
58})
59 
60export type InsertTodo = typeof todosTable.$inferInsert
61export type SelectTodo = typeof todosTable.$inferSelect
62```
63 
64And exporting it:
65 
66`db/schema/index.ts`
67 
68```ts
69export * from "./todos-schema"
70```
71 
72And adding it to the schema in `db/db.ts`:
73 
74`db/db.ts`
75 
76```ts
77import { todosTable } from "@/db/schema"
78 
79const schema = {
80 todos: todosTable
81}
82```
83 
84And a more complex schema:
85 
86```ts
87import { pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core"
88 
89export const chatsTable = pgTable("chats", {
90 id: uuid("id").defaultRandom().primaryKey(),
91 userId: text("user_id").notNull(),
92 name: text("name").notNull(),
93 createdAt: timestamp("created_at").defaultNow().notNull(),
94 updatedAt: timestamp("updated_at")
95 .defaultNow()
96 .notNull()
97 .$onUpdate(() => new Date())
98})
99 
100export type InsertChat = typeof chatsTable.$inferInsert
101export type SelectChat = typeof chatsTable.$inferSelect
102```
103 
104```ts
105import { pgEnum, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core"
106import { chatsTable } from "./chats-schema"
107 
108export const roleEnum = pgEnum("role", ["assistant", "user"])
109 
110export const messagesTable = pgTable("messages", {
111 id: uuid("id").defaultRandom().primaryKey(),
112 chatId: uuid("chat_id")
113 .references(() => chatsTable.id, { onDelete: "cascade" })
114 .notNull(),
115 content: text("content").notNull(),
116 role: roleEnum("role").notNull(),
117 createdAt: timestamp("created_at").defaultNow().notNull(),
118 updatedAt: timestamp("updated_at")
119 .defaultNow()
120 .notNull()
121 .$onUpdate(() => new Date())
122})
123 
124export type InsertMessage = typeof messagesTable.$inferInsert
125export type SelectMessage = typeof messagesTable.$inferSelect
126```
127 
128And exporting it:
129 
130`db/schema/index.ts`
131 
132```ts
133export * from "./chats-schema"
134export * from "./messages-schema"
135```
136 
137And adding it to the schema in `db/db.ts`:
138 
139`db/db.ts`
140 
141```ts
142import { chatsTable, messagesTable } from "@/db/schema"
143 
144const schema = {
145 chats: chatsTable,
146 messages: messagesTable
147}
148```
149 
150#### Server Actions
151 
152- When importing actions, use `@/actions` or `@/actions/db` if db related
153- DB related actions should go in the `actions/db` folder
154- Other actions should go in the `actions` folder
155- Name files like `example-actions.ts`
156- All actions should go in the `actions` folder
157- Only write the needed actions
158- Return an ActionState with the needed data type from actions
159- Include Action at the end of function names `Ex: exampleFunction -> exampleFunctionAction`
160- Actions should return a Promise<ActionState<T>>
161- Sort in CRUD order: Create, Read, Update, Delete
162- Make sure to return undefined as the data type if the action is not supposed to return any data
163- **Date Handling:** For columns defined as `PgDateString` (or any date string type), always convert JavaScript `Date` objects to ISO strings using `.toISOString()` before performing operations (e.g., comparisons or insertions). This ensures value type consistency and prevents type errors.
164 
165```ts
166export type ActionState<T> =
167 | { isSuccess: true; message: string; data: T }
168 | { isSuccess: false; message: string; data?: never }
169```
170 
171Example of an action:
172 
173`actions/db/todos-actions.ts`
174 
175```ts
176"use server"
177 
178import { db } from "@/db/db"
179import { InsertTodo, SelectTodo, todosTable } from "@/db/schema/todos-schema"
180import { ActionState } from "@/types"
181import { eq } from "drizzle-orm"
182 
183export async function createTodoAction(
184 todo: InsertTodo
185): Promise<ActionState<SelectTodo>> {
186 try {
187 const [newTodo] = await db.insert(todosTable).values(todo).returning()
188 return {
189 isSuccess: true,
190 message: "Todo created successfully",
191 data: newTodo
192 }
193 } catch (error) {
194 console.error("Error creating todo:", error)
195 return { isSuccess: false, message: "Failed to create todo" }
196 }
197}
198 
199export async function getTodosAction(
200 userId: string
201): Promise<ActionState<SelectTodo[]>> {
202 try {
203 const todos = await db.query.todos.findMany({
204 where: eq(todosTable.userId, userId)
205 })
206 return {
207 isSuccess: true,
208 message: "Todos retrieved successfully",
209 data: todos
210 }
211 } catch (error) {
212 console.error("Error getting todos:", error)
213 return { isSuccess: false, message: "Failed to get todos" }
214 }
215}
216 
217export async function updateTodoAction(
218 id: string,
219 data: Partial<InsertTodo>
220): Promise<ActionState<SelectTodo>> {
221 try {
222 const [updatedTodo] = await db
223 .update(todosTable)
224 .set(data)
225 .where(eq(todosTable.id, id))
226 .returning()
227 
228 return {
229 isSuccess: true,
230 message: "Todo updated successfully",
231 data: updatedTodo
232 }
233 } catch (error) {
234 console.error("Error updating todo:", error)
235 return { isSuccess: false, message: "Failed to update todo" }
236 }
237}
238 
239export async function deleteTodoAction(id: string): Promise<ActionState<void>> {
240 try {
241 await db.delete(todosTable).where(eq(todosTable.id, id))
242 return {
243 isSuccess: true,
244 message: "Todo deleted successfully",
245 data: undefined
246 }
247 } catch (error) {
248 console.error("Error deleting todo:", error)
249 return { isSuccess: false, message: "Failed to delete todo" }
250 }
251}
252```
253 
254#### Services
255 
256- When importing services, use `@/lib/services`
257- Name files like `example-service.ts`
258- All services should go in the `lib/services` folder
259- Services handle complex business logic that would otherwise make server actions too large
260- Services should be pure functions that take inputs and return outputs
261- Services should not directly handle HTTP requests or database operations
262- Use services for external API integrations, complex calculations, and domain-specific logic
263- Follow the data flow: Components → Actions → Services
264- Export functions using named exports
265 
266Example of a service:
267 
268`lib/services/grammar-correction.ts`
269 
270```ts
271import OpenAI from "openai"
272import { getCompletion } from "@/lib/services/open-ai"
273 
274const SYSTEM_MESSAGE: string = `You are a grammar correction assistant...`
275 
276export const getPunchyText = async (
277 userMessage: string
278): Promise<string | undefined> => {
279 const completion: OpenAI.Chat.Completions.ChatCompletion =
280 await getCompletion(userMessage, {
281 systemMessage: SYSTEM_MESSAGE,
282 maxTokens: 280,
283 temperature: 0.7
284 })
285 
286 return completion?.choices?.[0]?.message?.content?.trim()
287}
288```

Sections

  • Backend Rules

What it covers

do-not

Stack — with the evidence

typescript

(1.00)

node

(1.00)

nextjs

(1.00)

drizzle

(1.00)

tailwind

(1.00)

eslint

(1.00)

react

(0.70)

postgres

(0.70)

javascript

(0.60)

Glob targeting

  • [object Object]

Format

Cursor rules

The most expressive format here. Many small .mdc files, each with frontmatter declaring when it should load, so a rule about migrations only enters context when a migration is open. Costs the most to maintain and only one editor reads it.

What the corpus says about it

Repository

Owner
sportiz91
Language
—
License
—
Archived
no

All configs in this repo

Also in sportiz91/vibe-template

Diff this repo’s formats

One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?

The other instruction files in this repository
RepositoryFormatStackCoversScoreChanged
sportiz91/vibe-template.cursor/rules/auth.mdc · 9Cursor rulestypescriptnode+7securitydo-not32/1003 days ago
sportiz91/vibe-template.cursor/rules/storage.mdc · 9Cursor rulestypescriptnode+7archsecuritydo-not65/1003 days ago
sportiz91/vibe-template.cursor/rules/coding-standards.mdc · 9Cursor rulestypescriptnode+7styletypesui36/1003 days ago
sportiz91/vibe-template.cursor/rules/frontend.mdc · 9Cursor rulestypescriptnode+7do-not61/1003 days ago
sportiz91/vibe-template.cursor/rules/general.mdc · 9Cursor rulestypescriptnode+7stylearchsecuritydo-not+169/1003 days ago
sportiz91/vibe-template.cursorrules · 9.cursorrulestypescriptnode+7stylearchsecuritydo-not+149/1003 days ago
sportiz91/vibe-templateCLAUDE.md · 9CLAUDE.mdtypescriptnode+7setuptestlint-formatstyle+788/1003 days ago
Diff against .cursor/rules/auth.mdc Diff against .cursor/rules/storage.mdc Diff against .cursor/rules/coding-standards.mdc Diff against .cursor/rules/frontend.mdc Diff against .cursor/rules/general.mdc Diff against .cursorrules Diff against CLAUDE.md

Similar configs

Same format, overlapping stack, ranked by quality.

Same format, overlapping stack, ranked by quality
RepositoryFormatStackCoversScoreChanged
hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126Cursor rulesgobun+5setupbuildtestlint-format+6100/1003 days ago
TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 45Cursor rulestypescriptpytest+15testlint-formatstylearch+5100/1003 days ago
markstev/mark-starter.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+14setuptestlint-formatstyle+699/1003 days ago
Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+13setuptestlint-formatstyle+799/1003 days ago
dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+15setuptestlint-formatstyle+799/1003 days ago
deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1Cursor rulestypescriptnextjs+5setuptestlint-formatstyle+799/1003 days ago
langflow-ai/langflow.cursor/rules/docs_development.mdc · 153kCursor rulespythonnode+16setupbuildtestlint-format+797/1003 days ago
TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 45Cursor rulestypescriptpytest+15teststyletesting-strategysecurity+397/1003 days ago
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack