| Dimension | Shared | Only in A | Only in B | Overlap |
|---|---|---|---|---|
| Sections | 1 | 0 | 24 | 4% |
| Commands | 0 | 0 | 0 | — |
| Section tags | 1 | 0 | 4 | 20% |
What each file covers
Sections
1 shared · 0 only in A · 24 only in B- + Project Instructions
- + Overview
- + Tech Stack
- + Project Structure
- + Rules
- + General Rules
- + Frontend Rules
- + Auth Rules
- + Payments Rules
- + Analytics Rules
- + Storage Rules
- + Organization
- + Buckets
- + File Structure
- + Actions
- + File Handling
- + Upload Rules
- + Download Rules
- + Delete Rules
- + Security
- + Bucket Policies
- + Access Control
- + Error Handling
- + Optimization
- Backend Rules
Commands
neither file has anySection tags
1 shared · 0 only in A · 4 only in B- + code-style
- + architecture
- + security
- + agent-behaviour
- do-not
Line diff
sportiz91/vibe-template · .cursor/rules/backend.mdc
@@ −1 @@
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.
@@ −11 @@
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
@@ −251 @@
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```
sportiz91/vibe-template · .cursorrules
@@ +1 @@
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.
@@ +236 @@
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
@@ +476 @@
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
@@ −1 +1 @@
1−---
2−description: Follow these rules when working on the backend.
3−globs:
4−alwaysApply: false
5−---
1+# Project Instructions
2+
3+Use specification and guidelines as you build the app.
4+
5+Write the complete code for every step. Do not get lazy.
6+
7+Your goal is to completely finish whatever I ask for.
8+
9+You 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+
13+This 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+
49+Follow 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+
67+Follow 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+
76+An example of a type:
77+
78+`types/actions-types.ts`
79+
80+```ts
81+export type ActionState<T> =
82+ | { isSuccess: true; message: string; data: T }
83+ | { isSuccess: false; message: string; data?: never }
84+```
85+
86+And exporting it:
87+
88+`types/index.ts`
89+
90+```ts
91+export * from "./actions-types"
92+```
93+
94+### Frontend Rules
95+
96+Follow these rules when working on the frontend.
97+
98+It 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+
131+Example of a server layout:
132+
133+```tsx
134+"use server"
135+
136+export default async function ExampleServerLayout({
137+ children
138+}: {
139+ children: React.ReactNode
140+}) {
141+ return children
142+}
143+```
144+
145+Example of a server page (with async logic):
146+
147+```tsx
148+"use server"
149+
150+import { Suspense } from "react"
151+import { SomeAction } from "@/actions/some-actions"
152+import SomeComponent from "./_components/some-component"
153+import SomeSkeleton from "./_components/some-skeleton"
154+
155+export default async function ExampleServerPage() {
156+ return (
157+ <Suspense fallback={<SomeSkeleton className="some-class" />}>
158+ <SomeComponentFetcher />
159+ </Suspense>
160+ )
161+}
162+
163+async function SomeComponentFetcher() {
164+ const { data } = await SomeAction()
165+ return <SomeComponent className="some-class" initialData={data || []} />
166+}
167+```
168+
169+Example of a server page (no async logic required):
170+
171+```tsx
172+"use server"
173+
174+import SomeClientComponent from "./_components/some-client-component"
175+
176+// In this case, no asynchronous work is being done, so no Suspense or fallback is required.
177+export default async function ExampleServerPage() {
178+ return <SomeClientComponent initialData={[]} />
179+}
180+```
181+
182+Example of a server component:
183+
184+```tsx
185+"use server"
186+
187+interface ExampleServerComponentProps {
188+ // Your props here
189+}
190+
191+export 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+
204+Example of a client page:
205+
206+```tsx
207+"use client"
208+
209+export default function ExampleClientPage() {
210+ // Your code here
211+}
212+```
213+
214+Example of a client component:
215+
216+```tsx
217+"use client"
218+
219+interface ExampleClientComponentProps {
220+ initialData: any[]
221+}
222+
223+export default function ExampleClientComponent({
224+ initialData
225+}: ExampleClientComponentProps) {
226+ // Client-side logic here
227+ return <div>{initialData.length} items</div>
228+}
229+```
230+
6231 ### Backend Rules
7232
8233 Follow these rules when working on the backend.
@@ −11 +236 @@
11236
12237 #### General Rules
13238
14−- Never generate migrations. You do not have to do anything in the `db/migrations` folder including migrations and metadata. Ignore it.
239+- Never generate migrations. You do not have to do anything in the `db/migrations` folder inluding migrations and metadata. Ignore it.
15240
16241 #### Organization
17242
@@ −251 +476 @@
251476 }
252477 ```
253478
254−#### Services
479+### Auth Rules
255480
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
481+Follow these rules when working on auth.
265482
266−Example of a service:
483+It uses Clerk for authentication.
267484
268−`lib/services/grammar-correction.ts`
485+#### General Rules
269486
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+
492+Follow these rules when working on payments.
493+
494+It uses Stripe for payments.
495+
496+### Analytics Rules
497+
498+Follow these rules when working on analytics.
499+
500+It uses PostHog for analytics.
501+
502+# Storage Rules
503+
504+Follow these rules when working with Supabase Storage.
505+
506+It 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+
544+Example of a storage action:
545+
270546 ```ts
271−import OpenAI from "openai"
272−import { getCompletion } from "@/lib/services/open-ai"
547+"use server"
273548
274−const SYSTEM_MESSAGE: string = `You are a grammar correction assistant...`
549+import { createClientComponentClient } from "@supabase/auth-helpers-nextjs"
550+import { ActionState } from "@/types"
275551
276−export 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− })
552+export async function uploadFileStorage(
553+ bucket: string,
554+ path: string,
555+ file: File
556+): Promise<ActionState<{ path: string }>> {
557+ try {
558+ const supabase = createClientComponentClient()
285559
286− return completion?.choices?.[0]?.message?.content?.trim()
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+ }
287578 }
288579 ```
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+
591+Example validation:
592+
593+```ts
594+const MAX_FILE_SIZE = 10 * 1024 * 1024 // 10MB
595+const ALLOWED_TYPES = ["image/jpeg", "image/png", "image/webp"]
596+
597+function 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
634+CREATE POLICY "Users can only access their own files"
635+ON storage.objects
636+FOR ALL
637+USING (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+
