Files
myeasycms-v2/apps/web/CLAUDE.md
Giancarlo Buomprisco 533dfba5b9 Optimized agents rules subfolders, dependencies updates (#355)
* Update AGENTS.md and CLAUDE.md for improved clarity and structure
* Added MCP Server
* Added missing triggers to tables that should have used them
* Updated all dependencies
* Fixed rare bug in React present in the Admin layout which prevents navigating to pages (sometimes...)
2025-09-17 11:36:02 +08:00

265 lines
7.1 KiB
Markdown

# Web Application Instructions
This file contains instructions specific to the main Next.js web application.
## Application Structure
### Route Organization
```
app/
├── (marketing)/ # Public pages (landing, blog, docs)
├── (auth)/ # Authentication pages
├── home/
│ ├── (user)/ # Personal account context
│ └── [account]/ # Team account context ([account] = team slug)
├── admin/ # Super admin section
└── api/ # API routes
```
Key Examples:
- Marketing layout: `app/(marketing)/layout.tsx`
- Personal dashboard: `app/home/(user)/page.tsx`
- Team workspace: `app/home/[account]/page.tsx`
- Admin section: `app/admin/page.tsx`
### Component Organization
- **Route-specific**: Use `_components/` directories
- **Route utilities**: Use `_lib/` for client, `_lib/server/` for server-side
- **Global components**: Root-level directories
Example:
- Team components: `app/home/[account]/_components/`
- Team server utils: `app/home/[account]/_lib/server/`
- Marketing components: `app/(marketing)/_components/`
## Data Fetching Strategy
**Quick Decision Framework:**
- **Server Components**: Default choice for initial data loading
- **Client Components**: For interactive features requiring hooks or real-time updates
- **Admin Client**: Only for bypassing RLS (rare cases - requires manual auth/authorization)
### Server Components (Preferred) ✅
```typescript
import { getSupabaseServerClient } from '@kit/supabase/server-client';
async function NotesPage() {
const client = getSupabaseServerClient();
const { data, error } = await client.from('notes').select('*');
if (error) return <ErrorMessage error={error} />;
return <NotesList notes={data} />;
}
```
**Key Insight**: Server Components automatically inherit RLS protection - no additional authorization checks needed!
### Client Components (Interactive) 🖱️
```typescript
'use client';
import { useSupabase } from '@kit/supabase/hooks/use-supabase';
import { useQuery } from '@tanstack/react-query';
function InteractiveNotes() {
const supabase = useSupabase();
const { data, isLoading } = useQuery({
queryKey: ['notes'],
queryFn: () => supabase.from('notes').select('*')
});
if (isLoading) return <Spinner />;
return <NotesList notes={data} />;
}
```
### Performance Optimization - Parallel Data Fetching 🚀
**Sequential (Slow) Pattern ❌**
```typescript
async function SlowDashboard() {
const userData = await loadUserData();
const notifications = await loadNotifications();
const metrics = await loadMetrics();
// Total time: sum of all requests
}
```
**Parallel (Optimized) Pattern ✅**
```typescript
async function FastDashboard() {
// Execute all requests simultaneously
const [userData, notifications, metrics] = await Promise.all([
loadUserData(),
loadNotifications(),
loadMetrics()
]);
// Total time: longest single request
return <Dashboard user={userData} notifications={notifications} metrics={metrics} />;
}
```
**Performance Impact**: Parallel fetching can reduce page load time by 60-80% for multi-data pages!
## Authorization Patterns - Critical Understanding 🔐
### RLS-Protected Data Fetching (Standard) ✅
```typescript
async function getUserNotes(userId: string) {
const client = getSupabaseServerClient();
// RLS automatically ensures user can only access their own notes
// NO additional authorization checks needed!
const { data } = await client.from('notes').select('*').eq('user_id', userId); // RLS validates this automatically
return data;
}
```
### Admin Client Usage (Dangerous - Rare Cases Only) ⚠️
```typescript
async function adminGetUserNotes(userId: string) {
const adminClient = getSupabaseServerAdminClient();
// CRITICAL: Manual authorization required - bypasses RLS!
const currentUser = await getCurrentUser();
if (!(await isSuperAdmin(currentUser))) {
throw new Error('Unauthorized: Admin access required');
}
// Additional validation: ensure current admin isn't targeting themselves
if (currentUser.id === userId) {
throw new Error('Cannot perform admin action on own account');
}
// Now safe to proceed with admin privileges
const { data } = await adminClient
.from('notes')
.select('*')
.eq('user_id', userId);
return data;
}
```
**Rule of thumb**: If using standard Supabase client, trust RLS. If using admin client, validate everything manually.
## Internationalization
Always use `Trans` component from `@kit/ui/trans`:
```tsx
import { Trans } from '@kit/ui/trans';
<Trans
i18nKey="user:welcomeMessage"
values={{ name: user.name }}
/>
// With HTML elements
<Trans
i18nKey="terms:agreement"
components={{
TermsLink: <a href="/terms" className="underline" />,
}}
/>
```
### Adding New Languages
1. Add language code to `lib/i18n/i18n.settings.ts`
2. Create translation files in `public/locales/[new-language]/`
3. Copy structure from English files
Translation files: `public/locales/<locale>/<namespace>.json`
## Workspace Contexts 🏢
### Personal Account Context (`app/home/(user)`)
```tsx
import { useUserWorkspace } from '@kit/accounts/hooks/use-user-workspace';
function PersonalComponent() {
const { user, account } = useUserWorkspace();
// Personal account data
}
```
Context provider: `@packages/features/accounts/src/components/user-workspace-context-provider.tsx`
### Team Account Context (`app/home/[account]`)
```tsx
import { useTeamAccountWorkspace } from '@kit/team-accounts/hooks/use-team-account-workspace';
function TeamComponent() {
const { account, user, accounts } = useTeamAccountWorkspace();
// Team account data with permissions
}
```
Context provider: `@packages/features/team-accounts/src/components/team-account-workspace-context-provider.tsx`
## Key Configuration Files
- **Feature flags**: `config/feature-flags.config.ts`
- **i18n settings**: `lib/i18n/i18n.settings.ts`
- **Supabase config**: `supabase/config.toml`
- **Middleware**: `middleware.ts`
## Route Handlers (API Routes)
Use `enhanceRouteHandler` from `@packages/next/src/routes/index.ts`:
```typescript
import { enhanceRouteHandler } from '@kit/next/routes';
export const POST = enhanceRouteHandler(
async function ({ body, user, request }) {
// body is validated, user available if auth: true
return NextResponse.json({ success: true });
},
{
auth: true,
schema: ZodSchema,
},
);
```
## Security Guidelines 🛡️
### Authentication & Authorization
- Authentication already enforced by middleware
- Authorization handled by RLS at database level (in most cases)
- Avoid defensive code - use RLS instead
- When using the Supabase admin client, must enforce both authentication and authorization
### Passing data to the client
- **Never pass sensitive data** to Client Components
- **Never expose server environment variables** to client (unless prefixed with NEXT_PUBLIC)
- Always validate user input
### Super Admin Protection
For admin routes, use `AdminGuard` from `@packages/features/admin/src/components/admin-guard.tsx`:
```tsx
import { AdminGuard } from '@kit/admin/components/admin-guard';
export default AdminGuard(AdminPageComponent);
```