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]
);
Image Optimization
Use optimized images:
<img
src="/image.jpg"
alt="Description"
loading="lazy"
width={800}
height={600}
/>
Accessibility
Semantic HTML
Use proper HTML elements:
// ✅ Good
<button onClick={handleClick}>Click me</button>
// ❌ Bad
<div onClick={handleClick}>Click me</div>
ARIA Labels
Add labels for screen readers:
<button aria-label="Close modal">
<X />
</button>
Keyboard Navigation
Ensure keyboard accessibility:
<div
role="button"
tabIndex={0}
onKeyDown={(e) => e.key === 'Enter' && handleClick()}
>
Testing
Manual Testing
Before deploying:
- Test all features
- Check responsive design
- Verify forms submit correctly
- Test error states
- Check loading states
Browser Testing
Test in multiple browsers:
- Chrome
- Firefox
- Safari
- Edge
Deployment
Pre-Deployment Checklist
- Remove console.logs
- Update environment variables
- Test production build locally
- Verify all API endpoints work
- Check mobile responsiveness
- Test authentication flow
- Verify payment integration (if applicable)
Post-Deployment
- Monitor error logs
- Check analytics
- Test critical user flows
- Verify SSL certificate
- Test custom domain (if configured)
Maintenance
Regular Updates
- Update dependencies monthly
- Review security advisories
- Test after updates
- Keep documentation current
Monitoring
- Set up error tracking (Sentry, LogRocket)
- Monitor performance (Lighthouse)
- Track user analytics (Google Analytics)
- Monitor uptime (UptimeRobot)
Common Pitfalls
Avoid
- Hardcoding API keys in frontend
- Ignoring TypeScript errors
- Not handling loading/error states
- Skipping input validation
- Not testing on mobile
- Committing .env files
- Using
anytype everywhere - Not optimizing images
Do
- Use environment variables
- Fix all TypeScript errors
- Handle all async states
- Validate all inputs
- Test responsive design
- Use .gitignore properly
- Define proper types
- Optimize assets