RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/.cursorrules/sportiz91/vibe-template

.cursorrules (deprecated)

.cursorrules
.cursorrulesroot

Quality

49/100

Scores the file, not the repository.

Length

2,516 words

39 headings · 21 code blocks

Repository

9

— · pushed 394 days ago

Last changed

3 days ago

First indexed 3 days ago.
sportiz91/vibe-template/.cursorrulesRawGitHub
1# Project Instructions
2 
3Use specification and guidelines as you build the app.
4 
5Write the complete code for every step. Do not get lazy.
6 
7Your goal is to completely finish whatever I ask for.
8 
9You will see <ai_context> tags in the code. These are context tags that you should use to help you understand the codebase.
10 
11## Overview
12 
13This is a web app template.
14 
15## Tech Stack
16 
17- Frontend: Next.js, Tailwind, Shadcn, Framer Motion
18- Backend: Postgres, Supabase, Drizzle ORM, Server Actions
19- Auth: Clerk
20- Payments: Stripe
21- Analytics: PostHog
22- Deployment: Vercel
23 
24## Project Structure
25 
26- `actions` - Server actions
27 - `db` - Database related actions
28 - Other actions
29- `app` - Next.js app router
30 - `api` - API routes
31 - `route` - An example route
32 - `_components` - One-off components for the route
33 - `layout.tsx` - Layout for the route
34 - `page.tsx` - Page for the route
35- `components` - Shared components
36 - `ui` - UI components
37 - `utilities` - Utility components
38- `db` - Database
39 - `schema` - Database schemas
40- `lib` - Library code
41 - `hooks` - Custom hooks
42 - `services` - Business logic services
43- `prompts` - Prompt files
44- `public` - Static assets
45- `types` - Type definitions
46 
47## Rules
48 
49Follow these rules when building the app.
50 
51### General Rules
52 
53- Use `@` to import anything from the app unless otherwise specified
54- Use kebab case for all files and folders unless otherwise specified
55- Don't update shadcn components unless otherwise specified
56 
57#### Env Rules
58 
59- If you update environment variables, update the `.env.example` file
60- All environment variables should go in `.env.local`
61- Do not expose environment variables to the frontend
62- Use `NEXT_PUBLIC_` prefix for environment variables that need to be accessed from the frontend
63- Always access environment variables via the centralized config module (`serverConfig` and `publicEnv` from `@/lib/config`). Do not use `process.env` directly in application code.
64 
65#### Type Rules
66 
67Follow these rules when working with types.
68 
69- When importing types, use `@/types`
70- Name files like `example-types.ts`
71- All types should go in `types`
72- Make sure to export the types in `types/index.ts`
73- Prefer interfaces over type aliases
74- If referring to db types, use `@/db/schema` such as `SelectTodo` from `todos-schema.ts`
75 
76An example of a type:
77 
78`types/actions-types.ts`
79 
80```ts
81export type ActionState<T> =
82 | { isSuccess: true; message: string; data: T }
83 | { isSuccess: false; message: string; data?: never }
84```
85 
86And exporting it:
87 
88`types/index.ts`
89 
90```ts
91export * from "./actions-types"
92```
93 
94### Frontend Rules
95 
96Follow these rules when working on the frontend.
97 
98It uses Next.js, Tailwind, Shadcn, and Framer Motion.
99 
100#### General Rules
101 
102- Use `lucide-react` for icons
103- useSidebar must be used within a SidebarProvider
104 
105#### Components
106 
107- Use divs instead of other html tags unless otherwise specified
108- Separate the main parts of a component's html with an extra blank line for visual spacing
109- Always tag a component with either `use server` or `use client` at the top, including layouts and pages
110 
111##### Organization
112 
113- All components be named using kebab case like `example-component.tsx` unless otherwise specified
114- Put components in `/_components` in the route if one-off components
115- Put components in `/components` from the root if shared components
116 
117##### Data Fetching
118 
119- Fetch data in server components and pass the data down as props to client components.
120- Use server actions from `/actions` to mutate data.
121 
122##### Server Components
123 
124- Use `"use server"` at the top of the file.
125- Implement Suspense for asynchronous data fetching to show loading states while data is being fetched.
126- If no asynchronous logic is required for a given server component, you do not need to wrap the component in `<Suspense>`. You can simply return the final UI directly since there is no async boundary needed.
127- If asynchronous fetching is required, you can use a `<Suspense>` boundary and a fallback to indicate a loading state while data is loading.
128- Server components cannot be imported into client components. If you want to use a server component in a client component, you must pass the as props using the "children" prop
129- params in server pages should be awaited such as `const { courseId } = await params` where the type is `params: Promise<{ courseId: string }>`
130 
131Example of a server layout:
132 
133```tsx
134"use server"
135 
136export default async function ExampleServerLayout({
137 children
138}: {
139 children: React.ReactNode
140}) {
141 return children
142}
143```
144 
145Example of a server page (with async logic):
146 
147```tsx
148"use server"
149 
150import { Suspense } from "react"
151import { SomeAction } from "@/actions/some-actions"
152import SomeComponent from "./_components/some-component"
153import SomeSkeleton from "./_components/some-skeleton"
154 
155export default async function ExampleServerPage() {
156 return (
157 <Suspense fallback={<SomeSkeleton className="some-class" />}>
158 <SomeComponentFetcher />
159 </Suspense>
160 )
161}
162 
163async function SomeComponentFetcher() {
164 const { data } = await SomeAction()
165 return <SomeComponent className="some-class" initialData={data || []} />
166}
167```
168 
169Example of a server page (no async logic required):
170 
171```tsx
172"use server"
173 
174import SomeClientComponent from "./_components/some-client-component"
175 
176// In this case, no asynchronous work is being done, so no Suspense or fallback is required.
177export default async function ExampleServerPage() {
178 return <SomeClientComponent initialData={[]} />
179}
180```
181 
182Example of a server component:
183 
184```tsx
185"use server"
186 
187interface ExampleServerComponentProps {
188 // Your props here
189}
190 
191export async function ExampleServerComponent({
192 props
193}: ExampleServerComponentProps) {
194 // Your code here
195}
196```
197 
198##### Client Components
199 
200- Use `"use client"` at the top of the file
201- Client components can safely rely on props passed down from server components, or handle UI interactions without needing <Suspense> if there's no async logic.
202- Never use server actions in client components. If you need to create a new server action, create it in `/actions`
203 
204Example of a client page:
205 
206```tsx
207"use client"
208 
209export default function ExampleClientPage() {
210 // Your code here
211}
212```
213 
214Example of a client component:
215 
216```tsx
217"use client"
218 
219interface ExampleClientComponentProps {
220 initialData: any[]
221}
222 
223export default function ExampleClientComponent({
224 initialData
225}: ExampleClientComponentProps) {
226 // Client-side logic here
227 return <div>{initialData.length} items</div>
228}
229```
230 
231### Backend Rules
232 
233Follow these rules when working on the backend.
234 
235It uses Postgres, Supabase, Drizzle ORM, and Server Actions.
236 
237#### General Rules
238 
239- Never generate migrations. You do not have to do anything in the `db/migrations` folder inluding migrations and metadata. Ignore it.
240 
241#### Organization
242 
243#### Schemas
244 
245- When importing schemas, use `@/db/schema`
246- Name files like `example-schema.ts`
247- All schemas should go in `db/schema`
248- Make sure to export the schema in `db/schema/index.ts`
249- Make sure to add the schema to the `schema` object in `db/db.ts`
250- If using a userId, always use `userId: text("user_id").notNull()`
251- Always include createdAt and updatedAt columns in all tables
252- Make sure to cascade delete when necessary
253- Use enums for columns that have a limited set of possible values such as:
254 
255```ts
256import { pgEnum } from "drizzle-orm/pg-core"
257 
258export const MEMBERSHIP: PgEnum<Membership> = pgEnum(
259 "membership",
260 MEMBERSHIP_VALUES
261)
262 
263membership: MEMBERSHIP("membership").notNull().default("free")
264```
265 
266Example of a schema:
267 
268`db/schema/todos-schema.ts`
269 
270```ts
271import { boolean, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core"
272 
273export const todosTable = pgTable("todos", {
274 id: uuid("id").defaultRandom().primaryKey(),
275 userId: text("user_id").notNull(),
276 content: text("content").notNull(),
277 completed: boolean("completed").default(false).notNull(),
278 createdAt: timestamp("created_at").defaultNow().notNull(),
279 updatedAt: timestamp("updated_at")
280 .defaultNow()
281 .notNull()
282 .$onUpdate(() => new Date())
283})
284 
285export type InsertTodo = typeof todosTable.$inferInsert
286export type SelectTodo = typeof todosTable.$inferSelect
287```
288 
289And exporting it:
290 
291`db/schema/index.ts`
292 
293```ts
294export * from "./todos-schema"
295```
296 
297And adding it to the schema in `db/db.ts`:
298 
299`db/db.ts`
300 
301```ts
302import { todosTable } from "@/db/schema"
303 
304const schema = {
305 todos: todosTable
306}
307```
308 
309And a more complex schema:
310 
311```ts
312import { pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core"
313 
314export const chatsTable = pgTable("chats", {
315 id: uuid("id").defaultRandom().primaryKey(),
316 userId: text("user_id").notNull(),
317 name: text("name").notNull(),
318 createdAt: timestamp("created_at").defaultNow().notNull(),
319 updatedAt: timestamp("updated_at")
320 .defaultNow()
321 .notNull()
322 .$onUpdate(() => new Date())
323})
324 
325export type InsertChat = typeof chatsTable.$inferInsert
326export type SelectChat = typeof chatsTable.$inferSelect
327```
328 
329```ts
330import { pgEnum, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core"
331import { chatsTable } from "./chats-schema"
332 
333export const roleEnum = pgEnum("role", ["assistant", "user"])
334 
335export const messagesTable = pgTable("messages", {
336 id: uuid("id").defaultRandom().primaryKey(),
337 chatId: uuid("chat_id")
338 .references(() => chatsTable.id, { onDelete: "cascade" })
339 .notNull(),
340 content: text("content").notNull(),
341 role: roleEnum("role").notNull(),
342 createdAt: timestamp("created_at").defaultNow().notNull(),
343 updatedAt: timestamp("updated_at")
344 .defaultNow()
345 .notNull()
346 .$onUpdate(() => new Date())
347})
348 
349export type InsertMessage = typeof messagesTable.$inferInsert
350export type SelectMessage = typeof messagesTable.$inferSelect
351```
352 
353And exporting it:
354 
355`db/schema/index.ts`
356 
357```ts
358export * from "./chats-schema"
359export * from "./messages-schema"
360```
361 
362And adding it to the schema in `db/db.ts`:
363 
364`db/db.ts`
365 
366```ts
367import { chatsTable, messagesTable } from "@/db/schema"
368 
369const schema = {
370 chats: chatsTable,
371 messages: messagesTable
372}
373```
374 
375#### Server Actions
376 
377- When importing actions, use `@/actions` or `@/actions/db` if db related
378- DB related actions should go in the `actions/db` folder
379- Other actions should go in the `actions` folder
380- Name files like `example-actions.ts`
381- All actions should go in the `actions` folder
382- Only write the needed actions
383- Return an ActionState with the needed data type from actions
384- Include Action at the end of function names `Ex: exampleFunction -> exampleFunctionAction`
385- Actions should return a Promise<ActionState<T>>
386- Sort in CRUD order: Create, Read, Update, Delete
387- Make sure to return undefined as the data type if the action is not supposed to return any data
388- **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.
389 
390```ts
391export type ActionState<T> =
392 | { isSuccess: true; message: string; data: T }
393 | { isSuccess: false; message: string; data?: never }
394```
395 
396Example of an action:
397 
398`actions/db/todos-actions.ts`
399 
400```ts
401"use server"
402 
403import { db } from "@/db/db"
404import { InsertTodo, SelectTodo, todosTable } from "@/db/schema/todos-schema"
405import { ActionState } from "@/types"
406import { eq } from "drizzle-orm"
407 
408export async function createTodoAction(
409 todo: InsertTodo
410): Promise<ActionState<SelectTodo>> {
411 try {
412 const [newTodo] = await db.insert(todosTable).values(todo).returning()
413 return {
414 isSuccess: true,
415 message: "Todo created successfully",
416 data: newTodo
417 }
418 } catch (error) {
419 console.error("Error creating todo:", error)
420 return { isSuccess: false, message: "Failed to create todo" }
421 }
422}
423 
424export async function getTodosAction(
425 userId: string
426): Promise<ActionState<SelectTodo[]>> {
427 try {
428 const todos = await db.query.todos.findMany({
429 where: eq(todosTable.userId, userId)
430 })
431 return {
432 isSuccess: true,
433 message: "Todos retrieved successfully",
434 data: todos
435 }
436 } catch (error) {
437 console.error("Error getting todos:", error)
438 return { isSuccess: false, message: "Failed to get todos" }
439 }
440}
441 
442export async function updateTodoAction(
443 id: string,
444 data: Partial<InsertTodo>
445): Promise<ActionState<SelectTodo>> {
446 try {
447 const [updatedTodo] = await db
448 .update(todosTable)
449 .set(data)
450 .where(eq(todosTable.id, id))
451 .returning()
452 
453 return {
454 isSuccess: true,
455 message: "Todo updated successfully",
456 data: updatedTodo
457 }
458 } catch (error) {
459 console.error("Error updating todo:", error)
460 return { isSuccess: false, message: "Failed to update todo" }
461 }
462}
463 
464export async function deleteTodoAction(id: string): Promise<ActionState<void>> {
465 try {
466 await db.delete(todosTable).where(eq(todosTable.id, id))
467 return {
468 isSuccess: true,
469 message: "Todo deleted successfully",
470 data: undefined
471 }
472 } catch (error) {
473 console.error("Error deleting todo:", error)
474 return { isSuccess: false, message: "Failed to delete todo" }
475 }
476}
477```
478 
479### Auth Rules
480 
481Follow these rules when working on auth.
482 
483It uses Clerk for authentication.
484 
485#### General Rules
486 
487- Import the auth helper with `import { auth } from "@clerk/nextjs/server"` in server components
488- await the auth helper in server actions
489 
490### Payments Rules
491 
492Follow these rules when working on payments.
493 
494It uses Stripe for payments.
495 
496### Analytics Rules
497 
498Follow these rules when working on analytics.
499 
500It uses PostHog for analytics.
501 
502# Storage Rules
503 
504Follow these rules when working with Supabase Storage.
505 
506It uses Supabase Storage for file uploads, downloads, and management.
507 
508## General Rules
509 
510- Always use environment variables for bucket names to maintain consistency across environments
511- Never hardcode bucket names in the application code
512- Always handle file size limits and allowed file types at the application level
513- Use the `upsert` method instead of `upload` when you want to replace existing files
514- Always implement proper error handling for storage operations
515- Use content-type headers when uploading files to ensure proper file handling
516 
517## Organization
518 
519### Buckets
520 
521- Name buckets in kebab-case: `user-uploads`, `profile-images`
522- Create separate buckets for different types of files (e.g., `profile-images`, `documents`, `attachments`)
523- Document bucket purposes in a central location
524- Set appropriate bucket policies (public/private) based on access requirements
525- Implement RLS (Row Level Security) policies for buckets that need user-specific access
526- Make sure to let me know instructions for setting up RLS policies on Supabase since you can't do this yourself, including the SQL scripts I need to run in the editor
527 
528### File Structure
529 
530- Organize files in folders based on their purpose and ownership
531- Use predictable, collision-resistant naming patterns
532- Structure: `{bucket}/{userId}/{purpose}/{filename}`
533- Example: `profile-images/123e4567-e89b/avatar/profile.jpg`
534- Include timestamps in filenames when version history is important
535- Example: `documents/123e4567-e89b/contracts/2024-02-13-contract.pdf`
536 
537## Actions
538 
539- When importing storage actions, use `@/actions/storage`
540- Name files like `example-storage-actions.ts`
541- Include Storage at the end of function names `Ex: uploadFile -> uploadFileStorage`
542- Follow the same ActionState pattern as DB actions
543 
544Example of a storage action:
545 
546```ts
547"use server"
548 
549import { createClientComponentClient } from "@supabase/auth-helpers-nextjs"
550import { ActionState } from "@/types"
551 
552export async function uploadFileStorage(
553 bucket: string,
554 path: string,
555 file: File
556): Promise<ActionState<{ path: string }>> {
557 try {
558 const supabase = createClientComponentClient()
559 
560 const { data, error } = await supabase.storage
561 .from(bucket)
562 .upload(path, file, {
563 upsert: false,
564 contentType: file.type
565 })
566 
567 if (error) throw error
568 
569 return {
570 isSuccess: true,
571 message: "File uploaded successfully",
572 data: { path: data.path }
573 }
574 } catch (error) {
575 console.error("Error uploading file:", error)
576 return { isSuccess: false, message: "Failed to upload file" }
577 }
578}
579```
580 
581## File Handling
582 
583### Upload Rules
584 
585- Always validate file size before upload
586- Implement file type validation using both extension and MIME type
587- Generate unique filenames to prevent collisions
588- Set appropriate content-type headers
589- Handle existing files appropriately (error or upsert)
590 
591Example validation:
592 
593```ts
594const MAX_FILE_SIZE = 10 * 1024 * 1024 // 10MB
595const ALLOWED_TYPES = ["image/jpeg", "image/png", "image/webp"]
596 
597function validateFile(file: File): boolean {
598 if (file.size > MAX_FILE_SIZE) {
599 throw new Error("File size exceeds limit")
600 }
601 
602 if (!ALLOWED_TYPES.includes(file.type)) {
603 throw new Error("File type not allowed")
604 }
605 
606 return true
607}
608```
609 
610### Download Rules
611 
612- Always handle missing files gracefully
613- Implement proper error handling for failed downloads
614- Use signed URLs for private files
615 
616### Delete Rules
617 
618- Implement soft deletes when appropriate
619- Clean up related database records when deleting files
620- Handle bulk deletions carefully
621- Verify ownership before deletion
622- Always delete all versions/transforms of a file
623 
624## Security
625 
626### Bucket Policies
627 
628- Make buckets private by default
629- Only make buckets public when absolutely necessary
630- Use RLS policies to restrict access to authorized users
631- Example RLS policy:
632 
633```sql
634CREATE POLICY "Users can only access their own files"
635ON storage.objects
636FOR ALL
637USING (auth.uid()::text = (storage.foldername(name))[1]);
638```
639 
640### Access Control
641 
642- Generate short-lived signed URLs for private files
643- Implement proper CORS policies
644- Use separate buckets for public and private files
645- Never expose internal file paths
646- Validate user permissions before any operation
647 
648## Error Handling
649 
650- Implement specific error types for common storage issues
651- Always provide meaningful error messages
652- Implement retry logic for transient failures
653- Log storage errors separately for monitoring
654 
655## Optimization
656 
657- Implement progressive upload for large files
658- Clean up temporary files and failed uploads
659- Use batch operations when handling multiple files
660 

Sections

  • Project Instructions
  • Overview
  • Tech Stack
  • Project Structure
  • Rules
  • General Rules
  • Frontend Rules
  • Backend Rules
  • Auth Rules
  • Payments Rules
  • Analytics Rules
  • Storage Rules
  • General Rules
  • Organization
  • Buckets
  • File Structure
  • Actions
  • File Handling
  • Upload Rules
  • Download Rules
  • Delete Rules
  • Security
  • Bucket Policies
  • Access Control
  • Error Handling
  • Optimization

What it covers

code-stylearchitecturesecuritydo-notagent-behaviour

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)

Format

.cursorrules

Cursor's original single-file format, superseded by .cursor/rules/*.mdc. Tracked here precisely because it is dead: how much of the ecosystem is still shipping a deprecated file is a measurable answer, and a large share of the "best cursor rules" pages on the web still teach this format.

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/backend.mdc · 9Cursor rulestypescriptnode+7do-not61/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-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/backend.mdc Diff against .cursor/rules/coding-standards.mdc Diff against .cursor/rules/frontend.mdc Diff against .cursor/rules/general.mdc Diff against CLAUDE.md

Similar configs

Same format, overlapping stack, ranked by quality.

Same format, overlapping stack, ranked by quality
RepositoryFormatStackCoversScoreChanged
HerringtonDarkholme/megarepo.cursorrules · 17.cursorrulesnodejavascriptsetupbuildtestlint-format+1396/1003 days ago
survivorforge/cursor-rulesrules/devops-infrastructure/.cursorrules · 16.cursorrulesnodejavascriptbuildteststylesecurity+393/1002 days ago
survivorforge/cursor-rulesrules/devops-docker/.cursorrules · 16.cursorrulesnodejavascriptsetupbuildteststyle+493/1002 days ago
survivorforge/cursor-rulesrules/api-microservices/.cursorrules · 16.cursorrulesnodejavascriptbuildteststylearch+592/1002 days ago
fall-out-bug/sdp_lab.cursorrules · 0.cursorrulesgodocker+3setupbuildtestlint-format+386/1003 days ago
bashdeban/fastmind.cursorrules · 5.cursorrulestypescriptnode+8buildtestlint-formattypes+581/1003 days ago
storybookjs/storybook.cursorrules · 91k.cursorrulestypescriptjavascript+6teststylearchdo-not+178/1003 days ago
forem/forem.cursorrules · 23k.cursorrulesrubyrails+9teststyletypesdatabase+471/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