Cync Architecture
Directory Structure
aicync/
├── web/ # Next.js application
│ ├── app/ # App Router
│ │ ├── (features)/ # Feature modules
│ │ │ └── stickies/ # Stickies feature (isolated)
│ │ ├── api/ # API routes (50+)
│ │ ├── protected/ # Auth-protected pages
│ │ └── public/ # Public pages
│ ├── components/ # Shared React components
│ ├── lib/ # Shared utilities
│ │ ├── supabase/ # Database client
│ │ ├── wrike/ # Wrike integration
│ │ ├── services/ # Business logic
│ │ ├── api/ # API clients
│ │ └── mcp/ # MCP tool definitions
│ ├── services/ # External integrations
│ └── supabase/ # Database migrations
├── src/ # Python utilities
│ ├── config/ # Configuration
│ ├── integrations/ # External integrations
│ └── summarizers/ # AI summarization
└── docs/ # Nextra docs (legacy)
Feature Module Pattern
The codebase is migrating to a feature-module architecture. The stickies feature demonstrates the pattern:
app/(features)/stickies/
├── components/ # Feature-specific components
├── lib/
│ ├── services/ # Service layer
│ ├── api/ # API client
│ └── utils/ # Utilities
├── types/ # TypeScript types
└── index.ts # Barrel exports
Benefits
- Isolation: Features are self-contained
- Colocation: Related code lives together
- Testability: Easy to test in isolation
- Scalability: Add features without bloating shared folders
API Routes Organization
API routes are organized by domain:
| Domain | Routes | Description |
|---|---|---|
/api/stickies | 6 | CRUD + versions + restore |
/api/links | 8 | CRUD + folders + tagging |
/api/inbox | 6 | Email/storage management |
/api/pm | 8 | Wrike integration |
/api/fireflies | 3 | Meeting transcripts |
/api/chat | 2 | AI chat with tools |
/api/news | 3 | Article management |
/api/generate | 2 | AI summarization |
Data Flow
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Fireflies │────▶│ Cync API │────▶│ Supabase │
└─────────────┘ └──────────────┘ └─────────────┘
│
▼
┌─────────────┐ ┌──────────────┐
│ Wrike │────▶│ OpenRouter │
└─────────────┘ └──────────────┘
Authentication
- Supabase Auth for user authentication
- Row-Level Security (RLS) on all tables
- Service role client for admin operations (use carefully)
- ABAC (Attribute-Based Access Control) for fine-grained permissions
Auth Flow
User → Supabase Auth → Session Cookie → RLS Policies
Soft Delete Pattern
All deletable entities use a tag-based soft delete:
// Delete: Add trash tag
await supabase.from('stickies').update({
tags: [...existing, 'trash'],
deleted_at: new Date()
}).eq('id', id);
// Restore: Remove trash tag
await supabase.from('stickies').update({
tags: tags.filter(t => t !== 'trash'),
deleted_at: null
}).eq('id', id);
Legacy Compatibility
For backward compatibility with old soft-deleted items:
// Check BOTH for trash items
const isTrash = item.tags.includes('trash') ||
item.deleted_at !== null;
// When restoring, clear BOTH
await supabase.update({
tags: tags.filter(t => t !== 'trash'),
deleted_at: null
});
State Management
- React Server Components for data fetching
- Client Components for interactivity
- URL state for filters and pagination
- Local state for UI interactions
Component Patterns
Page Components
// app/protected/stickies/page.tsx
export default async function StickiesPage() {
const stickies = await fetchStickies();
return <StickiesList initialData={stickies} />;
}
Interactive Components
// components/StickiesList.tsx
'use client';
export function StickiesList({ initialData }) {
const [stickies, setStickies] = useState(initialData);
// Client-side interactivity
}