Skip to main content

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:

DomainRoutesDescription
/api/stickies6CRUD + versions + restore
/api/links8CRUD + folders + tagging
/api/inbox6Email/storage management
/api/pm8Wrike integration
/api/fireflies3Meeting transcripts
/api/chat2AI chat with tools
/api/news3Article management
/api/generate2AI 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
}