Best Practices
Guidelines for building production-ready apps with Prompt To App.
Project Organization
File Structure
Keep your project organized:
src/
├── components/ # Reusable UI components
├── pages/ # Page components
├── hooks/ # Custom React hooks
├── lib/ # Utilities and helpers
├── contexts/ # React contexts
└── types/ # TypeScript types
Naming Conventions
- Components: PascalCase (
UserProfile.tsx) - Hooks: camelCase with "use" prefix (
useAuth.ts) - Utilities: camelCase (
formatDate.ts) - Constants: UPPER_SNAKE_CASE (
API_URL)
Code Quality
TypeScript
Always use TypeScript for type safety:
// ✅ Good
interface User {
id: string;
email: string;
name: string;
}
// ❌ Bad
const user: any = { ... };
Error Handling
Handle errors gracefully:
try {
const data = await fetchData();
setData(data);
} catch (error) {
console.error('Failed to fetch:', error);
setError('Something went wrong');
}
Loading States
Always show loading indicators:
const [loading, setLoading] = useState(false);
const handleSubmit = async () => {
setLoading(true);
try {
await submitForm();
} finally {
setLoading(false);
}
};
Security
Environment Variables
Never commit secrets:
# .env
VITE_SUPABASE_URL=https://xxx.supabase.co
VITE_SUPABASE_ANON_KEY=eyJxxx # Public key only!
SUPABASE_SERVICE_ROLE_KEY=xxx # Server-side only!
Input Validation
Validate all user input:
import { z } from 'zod';
const schema = z.object({
email: z.string().email(),
password: z.string().min(8),
});
const result = schema.safeParse(formData);
if (!result.success) {
// Handle validation errors
}
Authentication
Use Supabase RLS for database security:
-- Only users can read their own data
CREATE POLICY "Users can read own data"
ON users FOR SELECT
USING (auth.uid() = id);
Performance
Code Splitting
Split large bundles:
const Dashboard = lazy(() => import('./pages/Dashboard'));
Memoization
Prevent unnecessary re-renders:
const memoizedValue = useMemo(() =>
expensiveCalculation(data),
[data]
);