How to add Rules in Cursor?
Here's how to add rules in Cursor:
- Create a
.cursor/rules/
directory in your project - Add your prompts in files with the
.mdc
extension (e.g.,.cursor/rules/cursorrules.mdc
) - Cursor will automatically detect and implement these rules in your project
For more detailed information about setting up rules, you can refer to the official Cursor documentation at: Cursor Rule Guide
How to add Rules in Windsurf?
Add a .windsurfrules
file to the project root as outlined in the Windsurf Getting Started Guide.
React Coding Standards Rule
---
description: Coding Standards & Rules for React 18.3.1
globs: **/*.tsx, **/*.jsx, **/*.ts
alwaysApply: true
---
You are an expert in React, TypeScript, and related libraries. You are focusing on producing clear, readable code. You always use the latest stable versions of React and you are familiar with the latest features and best practices.
## Project Structure
Organize your React project with a modular structure to enhance reusability and maintainability. Use the following directory layout.
- `src/` contains the root directory for source files.
- `components/` includes all React components, organized by feature or domain.
- `hooks/` houses custom React hooks for reusable logic.
- `utils/` holds utility functions for shared logic.
- `context/` manages context providers for global state.
- `types/` contains TypeScript type definitions for the application.
- `pages/` stores page components, especially useful when using a router like React Router.
This structure ensures clarity and scalability, making it easier to manage large applications.
## Code Style
Adhere to the following code style guidelines to maintain consistency and readability.
- Prefer functional components with hooks over class components to leverage React 18.3.1 features effectively.
- Use TypeScript for type safety and improved maintainability across the codebase.
- Follow naming conventions with PascalCase for component names (e.g., `MyComponent`), camelCase for variables and functions (e.g., `myFunction`), and prefix hooks with "use" (e.g., `useCustomHook`).
- Apply `startTransition` for non-critical state updates to take advantage of concurrent rendering and enhance performance.
- Ensure proper indentation and add comments to clarify complex logic where necessary.
## Usage
Follow these best practices to utilize React 18.3.1 effectively.
- Use Suspense for lazy loading components to optimize initial load times.
- Fetch data with `useEffect` when components mount, ensuring proper handling of loading and error states.
- Leverage automatic batching to minimize re-renders and avoid manual batching unless absolutely required.
- Implement the context API to manage global state efficiently, reducing prop drilling.
- Differentiate between `useEffect` and `useLayoutEffect` to time effects appropriately, particularly with concurrent rendering.
## Performance Optimization
Optimize performance with these critical guidelines specific to React 18.3.1.
- Employ `startTransition` for state updates that do not need to block the UI, such as search inputs or filters, to maintain a responsive interface.
- Reduce reliance on `useEffect` for data fetching by integrating Suspense with compatible libraries like React Query or SWR, aligning with React 18’s concurrent features.
- Prevent unnecessary re-renders by memoizing components with `React.memo` where performance gains are significant.
- Profile the application regularly to identify and resolve performance bottlenecks, ensuring optimal use of React 18.3.1’s capabilities.
NextJS Shadcn UI Coding Standards
---
description: Framework-specific coding standards for Next 15, React 19, and ShadCN
globs: **/*.ts, **/*.tsx, **/*.js, **/*.jsx
alwaysApply: false
---
You are a senior Next.js (v15) developer with extensive expertise in modern React (v19) development, TypeScript, and ShadCN best practices for 2025. Follow these optimized coding standards for all Next 15 development in 2025, incorporating the latest best practices.
# Project Structure
- Maintain Next.js's app directory structure (if using the new App Router) . For Next.js v15, lean toward the App Router.
- Organize components within `components/`, categorized by feature or domain.
- Store shared logic in `lib/` or `utils/`.
- Place static assets in `public/`.
- Use `app/layout.tsx` for global layout.
- Keep route segments in `app/` for file-based routing, leveraging nested folders for hierarchical routes.
# Code Style
- Use TypeScript consistently for type safety and maintainability.
- Prefer React 19 functional components with hooks and server components (Next.js 15) for SSR and SSG.
- Adhere to PascalCase for component filenames and names (e.g., `MyComponent.tsx`).
- Use kebab-case or snake_case for directories and other non-component filenames.
- Leverage ESLint and Prettier for code consistency.
# TypeScript Usage
- Enforce strict mode in TypeScript configuration.
- Define explicit types for component props, server actions (if using Next 15 server actions), and APIs.
- Avoid `any` type; utilize generics for reusable and type-safe code.
- Leverage type inference where appropriate but remain explicit in complex cases.
- Use interfaces or type aliases for defining object structures.
# ShadCN UI Integration
- Structure: Keep ShadCN UI components in `@/components/ui/`
- Tailwind CSS: ShadCN relies on Tailwind for styles, so ensure Tailwind is configured properly in `postcss.config.js` and `tailwind.config.js`. Use consistent class naming and purge unused CSS.
- Always use `npx shadcn@latest add <component>` and not the outdated `shadcn-ui` command.
# Components
- Use Next.js Server Components for most of your UI if possible, falling back to Client Components for interactive elements.
- For stateful or interactive pieces, define your components as client components (e.g., `"use client";`) at the top of the file.
- Keep components small, focused, and reusable.
- Implement clear prop validation with TypeScript.
- Use ShadCN components to create a consistent design system.
# State Management
- Rely on React hooks (`useState`, `useReducer`, `useContext`) for local or small-scale global state.
- Ensure you keep server and client state in sync if dealing with SSR.
# Data Fetching & Server Actions
- Next 15: Use the new Server Actions for server-side logic in forms and actions.
- Use React Suspense to handle loading states.
- For parallel or sequential data fetching, rely on built-in Next.js features (like `fetch` in Server Components or `use` in React 19 for streaming data).
# Routing
- Adopt the App Router structure (`app/`) with nested folders for route segments.
- Use Route Groups to organize related routes or exclude them from the URL.
- Provide loading states using `loading.tsx` or error boundaries with `error.tsx` in nested layouts.
# Performance Optimization
- Take advantage of Next.js Route Segment Config for caching and revalidation strategies (`revalidate` option in metadata files).
- Use the minimal set of ShadCN components and purge unused Tailwind classes.
- Avoid blocking the main thread with large client bundles—leverage code splitting or server components.
# UI
- Use Tailwind CSS for quick utility-based styling.
- Maintain consistent theming with ShadCN’s design tokens.
- Test for accessibility; ensure correct aria labels and roles.
- Use a color palette that meets contrast guidelines.
# SEO
- Use the `metadata` or `Head` in Next.js 15 for built-in SEO management.
- Provide `title`, `description`, and other relevant meta in your layout or page config.
- For advanced SEO, leverage Next.js SSG or SSR metadata updates
# Development Setup
- Place static assets in `public/` for direct serving.
- Keep secrets in `.env` files and reference them with `process.env`.
- Use TypeScript for all source files.
- Configure linting with ESLint and formatting with Prettier.
- Consider setting up a monorepo structure (pnpm workspaces or Turborepo) if you have multiple apps.
# Best Practices
- Do: Embrace server components to minimize client-side JavaScript.
- Do: Use minimal dependencies and keep your dependencies up to date.
- Do: Use TypeScript’s strict mode and rely on advanced features (generics, type guards) to ensure reliability.
- Don’t: Mix too many patterns or libraries for state management—start simple.
- Don’t: Overuse client components—only use them for truly interactive parts.
- Don’t: Hard-code environment variables or secrets.
React With Supabase
---
description: Coding Standards & Rules for Supabase with React 18.3.1
globs: **/*.tsx, **/*.ts, **/*.jsx, src/supabase/**/*.ts
alwaysApply: true
---
You are an expert in React, TypeScript, Supabase, and related libraries. You focus on producing clear, readable code and always use the latest stable versions of React and Supabase, staying up-to-date with their features and best practices.
## Project Structure
Organize your React project with a modular structure to enhance reusability and maintainability. Use the following directory layout:
- `src/` serves as the root directory for source files.
- `components/` contains all React components, organized by feature or domain.
- `hooks/` houses custom React hooks for reusable logic.
- `utils/` holds utility functions for shared logic.
- `types/` contains TypeScript type definitions for the application.
- `pages/` stores page components (useful with routers like React Router).
- `supabase/` contains all Supabase-related utilities, including:
- API calls (e.g., database queries, storage operations).
- Authentication helpers (e.g., login, logout, session management).
- Type definitions specific to Supabase responses.
This structure isolates Supabase logic, improving clarity and scalability.
## Code Style
Adhere to these guidelines for consistent, readable code.
- Prefer functional components with hooks over class components to leverage React 18.3.1 features.
- Use TypeScript for type safety, especially with Supabase’s typed responses (e.g., database rows, user objects).
- Follow naming conventions with PascalCase for components (e.g., `MyComponent`), camelCase for variables and functions (e.g., `fetchData`), and prefix hooks with "use" (e.g., `useSupabaseQuery`).
- Ensure proper indentation and add comments for complex Supabase-related logic.
## Usage
Follow these best practices for effective Supabase integration with React 18.3.1.
- Use Supabase’s official React hooks (e.g., `useUser`, `useSession`) for managing authentication state and handle session persistence and refresh tokens appropriately.
- Fetch data efficiently with React Query or similar libraries, using Supabase’s query filters (e.g., `select`, `eq`) to retrieve only necessary data.
- Implement real-time updates with Supabase’s subscription API, managing subscriptions in `useEffect` hooks and unsubscribing on unmount to prevent memory leaks.
- Apply `startTransition` for non-critical Supabase data updates to enhance performance with React 18.3.1’s concurrent features.
- Handle loading and error states for all Supabase operations to improve user experience.
## Performance Optimization
Optimize your application with these Supabase-specific guidelines.
- Memoize components with `React.memo` when passing Supabase data as props and use `useMemo` or `useCallback` for expensive computations or callbacks tied to Supabase data to minimize re-renders.
- Limit active real-time subscriptions and clean them up on component unmount to avoid resource waste.
- Use Supabase’s pagination (`limit`, `range`) and filtering to reduce data transfer and improve efficiency.
- Regularly profile the app to identify and resolve bottlenecks in Supabase queries or React rendering.
React Feature Guidelines
---
description: Framework-specific patterns for adding features to React 19 applications
globs: **/*.tsx, **/*.jsx, **/*.ts, **/*.js
alwaysApply: false
---
# Server Components
Server Components are the foundation of React 19 applications. They enable automatic server-side rendering and improved performance.
```tsx
// DataFeature.tsx
async function DataFeature() {
const data = await fetch('https://api.example.com/data');
const json = await data.json();
return (
<div>
{json.map(item => (
<div key={item.id}>{item.name}</div>
))}
</div>
);
}
```
Key Patterns
- Keep data fetching and database operations in Server Components
- Use async/await for server operations
- Implement Suspense boundaries for loading states
- Structure components hierarchically for optimal streaming
# Client Components
Client Components handle interactive features and client-side state management.
```tsx
// InteractiveFeature.tsx
'use client';
import { useState, useOptimistic } from 'react';
function InteractiveFeature() {
const [data, setData] = useState([]);
const [optimisticData, addOptimisticData] = useOptimistic(
data,
(state, newItem) => [...state, newItem]
);
return (
<div>
{optimisticData.map(item => (
<div key={item.id}>{item.name}</div>
))}
</div>
);
}
```
Key Patterns
- Mark Client Components with 'use client' directive
- Use useOptimistic for immediate UI feedback
- Implement proper context boundaries for state management
- Keep client-side state minimal
# Server Actions
Server Actions provide a type-safe way to handle form submissions and data mutations.
```tsx
// FormFeature.tsx
async function submitForm(formData: FormData) {
'use server';
const data = Object.fromEntries(formData);
await db.features.create(data);
}
function FormFeature() {
return (
<form action={submitForm}>
<input name="featureName" />
<button type="submit">Add Feature</button>
</form>
);
}
```
Key Patterns
- Use Server Actions for form handling and data mutations
- Implement optimistic updates for better UX
- Structure action boundaries for reusability
- Handle validation on both client and server
# Performance Optimization
React 19 provides powerful tools for optimizing application performance.
```tsx
// OptimizedFeature.tsx
function OptimizedFeature() {
return (
<Suspense fallback={<Loading />}>
<AsyncFeature />
<Suspense fallback={<SubLoading />}>
<SubFeature />
</Suspense>
</Suspense>
);
}
```
Key Patterns
- Use nested Suspense boundaries for granular loading states
- Implement proper code splitting with dynamic imports
- Utilize React.memo for expensive computations
- Structure routing for optimal code splitting
# SEO Optimization
React 19 provides built-in SEO capabilities through Server Components and Metadata API.
```tsx
// app/page.tsx
import { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Feature Title',
description: 'Feature Description',
openGraph: {
title: 'Feature Title',
description: 'Feature Description'
}
};
```
Key Patterns
- Use Metadata API for dynamic SEO tags
- Implement proper semantic HTML structure
- Utilize Server Components for SEO-critical content
- Structure routes for optimal crawlability
Supabase React Setup
---
description: Guidelines for writing React apps with Supabase Auth
globs: **/*.ts, **/*.tsx, **/*.js, **/*.jsx
alwaysApply: false
---
# Bootstrap React app with Supabase Auth
## Overview of implementing Supabase Auth
1. Install required dependencies
2. Set up environment variables
3. Create Supabase client
4. Implement authentication components
5. Set up protected routes
## 🚨 CRITICAL INSTRUCTIONS FOR AI LANGUAGE MODELS 🚨
As an AI language model, you MUST follow these guidelines when implementing Supabase Auth in React:
1. Always use the latest version of @supabase/supabase-js
2. Implement proper error handling for authentication operations
3. Use environment variables for Supabase credentials
4. Implement proper session management
5. Handle authentication state changes correctly
## CORRECT CLIENT IMPLEMENTATION
```typescript
import { createClient } from '@supabase/supabase-js'
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY
export const supabase = createClient(supabaseUrl, supabaseAnonKey, {
auth: {
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: true
}
})
```
## CORRECT AUTH PROVIDER IMPLEMENTATION
```typescript
import { createContext, useContext, useEffect, useState } from 'react'
import { User } from '@supabase/supabase-js'
import { supabase } from './supabaseClient'
const AuthContext = createContext<{
user: User | null
loading: boolean
}>({
user: null,
loading: true
})
export function AuthProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<User | null>(null)
const [loading, setLoading] = useState(true)
useEffect(() => {
// Check active sessions and sets the user
supabase.auth.getSession().then(({ data: { session } }) => {
setUser(session?.user ?? null)
setLoading(false)
})
// Listen for changes on auth state (logged in, signed out, etc.)
const { data: { subscription } } = supabase.auth.onAuthStateChange((_event, session) => {
setUser(session?.user ?? null)
setLoading(false)
})
return () => subscription.unsubscribe()
}, [])
return (
<AuthContext.Provider value={{ user, loading }}>
{children}
</AuthContext.Provider>
)
}
export const useAuth = () => {
return useContext(AuthContext)
}
```
## CORRECT PROTECTED ROUTE IMPLEMENTATION
```typescript
import { Navigate } from 'react-router-dom'
import { useAuth } from './AuthProvider'
export function ProtectedRoute({ children }: { children: React.ReactNode }) {
const { user, loading } = useAuth()
if (loading) {
return <div>Loading...</div>
}
if (!user) {
return <Navigate to="/login" />
}
return <>{children}</>
}
```
## AI MODEL VERIFICATION STEPS
Before generating any code, you MUST verify:
1. Are you using the latest version of @supabase/supabase-js?
2. Have you implemented proper error handling?
3. Are you using environment variables for credentials?
4. Is session management properly implemented?
5. Are authentication state changes being handled?
## CONSEQUENCES OF INCORRECT IMPLEMENTATION
If you generate code without following these guidelines:
1. Authentication state may become inconsistent
2. Sessions may not persist correctly
3. Security vulnerabilities may be introduced
4. Users may experience authentication loops
5. Token refresh may fail
## AI MODEL RESPONSE TEMPLATE
When implementing Supabase Auth in React, you MUST:
1. Follow the patterns shown in this guide
2. Implement proper error handling
3. Use the AuthProvider for state management
4. Protect sensitive routes
5. Handle authentication state changes
React Supabase Setup Guidelines
---
description:
globs:
alwaysApply: false
---
# Firebase + React Integration Setup Guide
This guide provides step-by-step instructions for integrating Firebase with a React application.
## Prerequisites
- Node.js and npm installed
- React project initialized
- Firebase account and project created
## Installation
1. Install required dependencies:
```bash
npm install firebase
```
## Configuration
2. Create a new file `src/firebase.ts` for Firebase configuration:
```typescript
import { initializeApp } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';
import { getAuth } from 'firebase/auth';
import { getStorage } from 'firebase/storage';
const firebaseConfig = {
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.REACT_APP_FIREBASE_APP_ID
};
// Initialize Firebase
export const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);
export const auth = getAuth(app);
export const storage = getStorage(app);
```
## Usage Examples
### Authentication Hook
```typescript
import { useState, useEffect } from 'react';
import { User, onAuthStateChanged, signInWithEmailAndPassword, createUserWithEmailAndPassword, signOut } from 'firebase/auth';
import { auth } from '../firebase';
export function useAuth() {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
setUser(user);
setLoading(false);
});
return () => unsubscribe();
}, []);
const login = async (email: string, password: string) => {
try {
setError(null);
await signInWithEmailAndPassword(auth, email, password);
} catch (err: any) {
setError(err.message);
throw err;
}
};
const register = async (email: string, password: string) => {
try {
setError(null);
await createUserWithEmailAndPassword(auth, email, password);
} catch (err: any) {
setError(err.message);
throw err;
}
};
const logout = async () => {
try {
setError(null);
await signOut(auth);
} catch (err: any) {
setError(err.message);
throw err;
}
};
return { user, loading, error, login, register, logout };
}
```
### Authentication Component
```typescript
import React, { useState } from 'react';
import { useAuth } from '../hooks/useAuth';
import { useNavigate } from 'react-router-dom';
export function AuthComponent() {
const { user, loading, error, login, register, logout } = useAuth();
const navigate = useNavigate();
const [isLogin, setIsLogin] = useState(true);
const [form, setForm] = useState({
email: '',
password: ''
});
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
try {
if (isLogin) {
await login(form.email, form.password);
} else {
await register(form.email, form.password);
}
navigate('/dashboard');
} catch (err) {
console.error('Authentication failed:', err);
}
};
if (loading) return <div>Loading...</div>;
return (
<div>
{user ? (
<div>
<p>Welcome, {user.email}</p>
<button onClick={logout}>Logout</button>
</div>
) : (
<div>
<h2>{isLogin ? 'Login' : 'Register'}</h2>
<form onSubmit={handleSubmit}>
<input
type="email"
placeholder="Email"
value={form.email}
onChange={(e) => setForm({ ...form, email: e.target.value })}
required
/>
<input
type="password"
placeholder="Password"
value={form.password}
onChange={(e) => setForm({ ...form, password: e.target.value })}
required
/>
<button type="submit">
{isLogin ? 'Login' : 'Register'}
</button>
{error && <p className="error">{error}</p>}
</form>
<p>
{isLogin ? "Don't have an account?" : "Already have an account?"}
<button onClick={() => setIsLogin(!isLogin)}>
{isLogin ? 'Register' : 'Login'}
</button>
</p>
</div>
)}
</div>
);
}
```
### Firestore Hook
```typescript
import { useState } from 'react';
import { collection, query, where, orderBy, limit, addDoc, updateDoc, deleteDoc, doc, onSnapshot, QueryConstraint } from 'firebase/firestore';
import { db } from '../firebase';
export function useFirestore<T>(collectionName: string) {
const [documents, setDocuments] = useState<T[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const subscribeToCollection = (queryConstraints: QueryConstraint[] = []) => {
setLoading(true);
const q = query(collection(db, collectionName), ...queryConstraints);
return onSnapshot(q,
(snapshot) => {
const docs = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data()
})) as T[];
setDocuments(docs);
setLoading(false);
},
(err) => {
setError(err.message);
setLoading(false);
}
);
};
const addDocument = async (data: Omit<T, 'id'>) => {
try {
setError(null);
const docRef = await addDoc(collection(db, collectionName), data);
return docRef.id;
} catch (err: any) {
setError(err.message);
throw err;
}
};
const updateDocument = async (id: string, data: Partial<T>) => {
try {
setError(null);
const docRef = doc(db, collectionName, id);
await updateDoc(docRef, data);
} catch (err: any) {
setError(err.message);
throw err;
}
};
const deleteDocument = async (id: string) => {
try {
setError(null);
const docRef = doc(db, collectionName, id);
await deleteDoc(docRef);
} catch (err: any) {
setError(err.message);
throw err;
}
};
return {
documents,
loading,
error,
subscribeToCollection,
addDocument,
updateDocument,
deleteDocument
};
}
```
### Firestore Component Example
```typescript
import React, { useEffect, useState } from 'react';
import { useFirestore } from '../hooks/useFirestore';
import { orderBy, limit, where } from 'firebase/firestore';
interface Todo {
id: string;
title: string;
completed: boolean;
createdAt: Date;
}
export function TodoList() {
const {
documents: todos,
loading,
error,
subscribeToCollection,
addDocument,
updateDocument,
deleteDocument
} = useFirestore<Todo>('todos');
const [newTodo, setNewTodo] = useState('');
useEffect(() => {
const unsubscribe = subscribeToCollection([
orderBy('createdAt', 'desc'),
limit(10)
]);
return () => unsubscribe();
}, []);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!newTodo.trim()) return;
try {
await addDocument({
title: newTodo,
completed: false,
createdAt: new Date()
});
setNewTodo('');
} catch (err) {
console.error('Failed to add todo:', err);
}
};
const toggleTodo = async (todo: Todo) => {
try {
await updateDocument(todo.id, {
completed: !todo.completed
});
} catch (err) {
console.error('Failed to toggle todo:', err);
}
};
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<div>
<form onSubmit={handleSubmit}>
<input
value={newTodo}
onChange={(e) => setNewTodo(e.target.value)}
placeholder="Add new todo"
/>
<button type="submit">Add</button>
</form>
<ul>
{todos.map((todo) => (
<li key={todo.id}>
<input
type="checkbox"
checked={todo.completed}
onChange={() => toggleTodo(todo)}
/>
<span style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>
{todo.title}
</span>
<button onClick={() => deleteDocument(todo.id)}>Delete</button>
</li>
))}
</ul>
</div>
);
}
```
### Storage Hook
```typescript
import { useState } from 'react';
import { ref, uploadBytes, getDownloadURL, deleteObject } from 'firebase/storage';
import { storage } from '../firebase';
export function useStorage(path: string) {
const [progress, setProgress] = useState(0);
const [error, setError] = useState<string | null>(null);
const [url, setUrl] = useState<string | null>(null);
const uploadFile = async (file: File) => {
try {
setError(null);
const storageRef = ref(storage, `${path}/${file.name}`);
await uploadBytes(storageRef, file);
const downloadUrl = await getDownloadURL(storageRef);
setUrl(downloadUrl);
return downloadUrl;
} catch (err: any) {
setError(err.message);
throw err;
}
};
const deleteFile = async (filename: string) => {
try {
setError(null);
const storageRef = ref(storage, `${path}/${filename}`);
await deleteObject(storageRef);
setUrl(null);
} catch (err: any) {
setError(err.message);
throw err;
}
};
return { progress, error, url, uploadFile, deleteFile };
}
```
## Security Considerations
1. Never expose Firebase configuration in client-side code without proper security measures
2. Implement proper authentication state management
3. Use environment variables for sensitive configuration
4. Set up appropriate Firestore security rules
5. Implement proper file upload restrictions
6. Use Firebase App Check for additional security
7. Implement proper error handling for all operations
## Best Practices
1. Use TypeScript for better type safety
2. Structure your Firebase services in custom hooks
3. Implement proper error handling
4. Use real-time listeners where appropriate
5. Implement proper loading states
6. Use Firebase emulators for local development
7. Follow React's hooks patterns
8. Implement proper data validation
9. Use Firebase indexes for complex queries
## Troubleshooting
1. Check Firebase console for errors
2. Verify security rules configuration
3. Check network requests in browser developer tools
4. Use Firebase debugging tools
5. Monitor Firebase usage and quotas
6. Check React Developer Tools for component state
7. Verify environment variables
## Additional Resources
- [Firebase Documentation](https://firebase.google.com/docs)
- [React Documentation](https://react.dev)
- [Firebase Console](https://console.firebase.google.com/)