Bosternexus Cursor Rules — Cursor Rules | Neura Market
    Neura MarketNeura Market/Cursor
    ChatGPTChatGPTClaudeClaudeGeminiGeminiCursorCursorGrokGrokPerplexityPerplexityDeepSeekDeepSeek
    CoPilotCoPilotStable DiffusionStable DiffusionMidjourneyMidjourney
    View All Directories
    OverviewRulesPromptsMCPsAgentsBlogVideosGuidesCoursesCommunityExtensionsTrendingGenerate
    CursorRulesBosternexus Cursor Rules
    Back to Rules

    Bosternexus Cursor Rules

    boster00 April 15, 2026
    0 copies 0 downloads
    Rule Content
    You are an expert full-stack developer working on **Boster Nexus**, an internal operations and enablement web app for Bosterbio. This is a Next.js application built on the ShipFast boilerplate foundation.
    
    ## 🎯 Project Purpose
    
    Boster Nexus centralizes Boster's cross-system workflows across:
    - **Zoho Books** (source of truth for transactional data)
    - **Zoho CRM** (customer relationship management)
    - **Zoho Desk** (support tickets)
    - **Magento** (storefront/e-commerce)
    - **Marketing Analytics** (GA4/BigQuery)
    
    The app acts as a **cache/warehouse** and **system of record for derived/internal-only data**, not replacing source systems but enabling efficient operations and guardrails.
    
    ## 🚀 Tech Stack
    
    - **Next.js**: 15.1.9 with React 19 and Turbopack
    - **React**: 19.0.0 (latest stable)
    - **Tailwind CSS**: 4.0.0 (CSS-based configuration)
    - **DaisyUI**: 5.0.50 (latest with new component system)
    - **Supabase**: Latest SSR package with async cookies support (Auth + Postgres)
    - **Database**: Managed Postgres (Neon/Supabase) - primarily cache/warehouse
    - **Deployment**: Vercel
    
    ## 📊 Core Data Principles
    
    ### Source of Truth Hierarchy
    1. **Zoho Books** is the source of truth for:
       - Orders, invoices, POs, bills, inventory state
       - All transactional financial data
    2. **Nexus DB** stores:
       - **Raw entity caches** (structured tables from Books/CRM/Desk)
       - **Derived/computed state** that Zoho cannot represent cleanly:
         - Bill↔PO line matching
         - Guardrail exceptions
         - Dashboard layout config
         - Loyalty ledger
         - Wiki versions
    3. **BigQuery** remains the store for GA4-scale event data; Nexus pulls only what it needs on-demand
    
    ### Rate Limiting Constraints
    ⚠️ **CRITICAL**: Zoho API rate limit is **no more than 1 request per second**
    - The Zoho class (`@/libs/zoho.js`) handles rate limiting automatically
    - **Always use the Zoho class** - never make direct API calls
    - For long chains, prefer async jobs (Postgres job table)
    - Design must prevent parallel overload
    - The Zoho class ensures all requests respect the 1 req/sec limit
    
    ## 📁 File Structure & Organization
    
    ### Route Groups (Next.js App Router)
    ```
    app/
    ├── (public)/              # Public pages (no auth required)
    │   ├── layout.js         # Public layout wrapper
    │   ├── page.js           # Landing page
    │   ├── blog/             # Blog pages
    │   ├── privacy-policy/   # Legal pages
    │   └── tos/
    ├── (private)/            # Private pages (auth required)
    │   ├── layout.js         # Private layout with auth check
    │   ├── admin/            # Admin functions
    │   ├── freezer/          # Freezer label printer
    │   └── zoho-test/        # Zoho testing interface
    ├── api/                  # API routes
    │   ├── zoho/            # Zoho webhook ingestion and operations
    │   ├── auth/            # Authentication endpoints
    │   ├── stripe/          # Stripe payment endpoints
    │   ├── migrations/       # Database migration endpoints
    │   └── webhook/         # Webhook handlers
    ├── signin/              # Authentication pages
    ├── dashboard/           # Dashboard pages
    └── layout.js            # Root layout
    ```
    
    ### Service Layer Architecture
    ```
    libs/
    ├── zoho/                # Zoho integration
    │   ├── index.js         # CRITICAL: Central Zoho class for all Zoho operations
    │   ├── auth.js          # Zoho authentication service
    │   ├── config.js        # Zoho configuration
    │   ├── rate-limiter.js  # Rate limiting for Zoho API
    │   ├── entities/        # Entity classes for data transformation
    │   │   ├── books/       # Zoho Books entities
    │   │   └── index.js
    │   ├── orchestration/   # Orchestration services
    │   │   └── ZohoOrchestrator.js
    │   └── services/        # Business logic services
    │       └── books/       # Zoho Books services
    ├── supabase/            # Supabase client utilities
    │   ├── client.js        # Client-side Supabase client
    │   ├── server.js        # Server-side Supabase client
    │   ├── data-access-layer.js  # CRITICAL: Data Access Layer for all DB operations
    │   └── middleware.js    # Supabase middleware utilities
    ├── utils/               # Shared utilities
    │   └── logger.js        # Structured file logging utility
    ├── zoho.js              # Legacy export (re-exports from zoho/index.js)
    ├── stripe.js            # Stripe integration
    ├── api.js               # API client utilities
    └── [other]/             # Other utility libraries
    ```
    
    ### Database Organization
    ```
    Database Tables:
    - zoho_books_*           # Zoho Books data (e.g., zoho_books_items, zoho_books_invoices, zoho_books_salesorders, zoho_books_purchaseorders, zoho_books_bills)
    - zoho_books_*_items     # Line items (e.g., zoho_books_invoice_items, zoho_books_salesorder_items)
    - auth_tokens            # OAuth tokens for Zoho and other services
    - profiles               # User profiles
    - derived_*               # Computed/derived state (e.g., derived_bill_po_matches)
    - jobs_*                 # Async job queue (e.g., jobs_sync, jobs_reconciliation)
    - config_*               # Configuration (e.g., config_dashboard_layouts, config_report_definitions)
    - internal_*              # Internal-only data (e.g., internal_guardrail_exceptions, internal_loyalty_ledger)
    ```
    
    ## ⚠️ Critical Rules
    
    ### 1. **Zoho API Operations** (MANDATORY)
    **ALL Zoho-related operations MUST use the Zoho class from `@/libs/zoho.js`.**
    **NEVER code Zoho API calls from scratch or use vanilla fetch/axios directly.**
    
    ```javascript
    // ❌ WRONG - Direct API call without using Zoho class
    const response = await fetch('https://books.zoho.com/api/v3/items');
    const items = await axios.get('https://books.zoho.com/api/v3/items');
    
    // ❌ WRONG - Manual rate limiting (even if correct, violates class usage rule)
    import { zohoRateLimiter } from '@/libs/utils/rate-limiter';
    await zohoRateLimiter.acquire();
    try {
      const response = await fetch('https://books.zoho.com/api/v3/items');
    } finally {
      zohoRateLimiter.release();
    }
    
    // ✅ CORRECT - Always use the Zoho class (rate limiting is built-in)
    import zoho from '@/libs/zoho';
    
    // Zoho Books operations
    const items = await zoho.getBooksItems();
    const invoice = await zoho.getBooksInvoice('123456');
    const invoices = await zoho.getBooksInvoices({ page: 1, per_page: 25 });
    
    // Zoho CRM operations
    const contacts = await zoho.getCrmRecords('Contacts');
    const lead = await zoho.getCrmRecord('Leads', '123456');
    await zoho.createCrmRecord('Contacts', { First_Name: 'John', Last_Name: 'Doe' });
    
    // Zoho Desk operations
    const tickets = await zoho.getDeskTickets();
    const ticket = await zoho.getDeskTicket('123456');
    
    // Generic methods (if specific methods don't exist)
    const customData = await zoho.get('books', '/custom-endpoint', { param: 'value' });
    
    // ✅ CORRECT - For long workflows, use async jobs
    const dal = new DataAccessLayer({ useServiceRole: true });
    await dal.insert('jobs_sync', {
      type: 'items_refresh',
      payload: { /* ... */ },
      status: 'pending'
    });
    // The job processor will use zoho.getBooksItems() when executing
    ```
    
    **Key Points:**
    - The Zoho class handles rate limiting automatically (1 req/sec)
    - The Zoho class handles token refresh automatically
    - The Zoho class provides type-safe methods for common operations
    - All Zoho API calls must go through this class - no exceptions
    
    ### 2. **Data Access Layer (DAL) Pattern** (MANDATORY)
    **ALL database operations MUST use the Data Access Layer from `@/libs/supabase/data-access-layer.js`.**
    **NEVER use direct `supabase.from()` calls for database operations.**
    
    **Exception:** Auth operations (`supabase.auth.getUser()`, `supabase.auth.admin.*`) can remain direct, but use DAL's `getCurrentUser()` or `getCurrentUserId()` methods when possible.
    
    ```javascript
    // ❌ WRONG - Direct Supabase database operations
    const supabase = await createClient();
    await supabase.from('zoho_books_items').upsert({ zoho_id: '123', name: 'Item' });
    const { data } = await supabase.from('profiles').select().eq('id', userId);
    
    // ❌ WRONG - Direct Supabase client for auth when DAL method exists
    const supabase = await createClient();
    const { data: { user } } = await supabase.auth.getUser();
    
    // ✅ CORRECT - Use Data Access Layer for all database operations
    import { DataAccessLayer } from '@/libs/supabase/data-access-layer';
    
    // For system-level operations (Zoho syncs, webhooks, etc.)
    const dal = new DataAccessLayer({
      useServiceRole: true,    // Bypass RLS for system operations
      requireUserId: false,     // Zoho data is not user-specific
      autoTimestamps: true      // Auto-manage created_at/updated_at
    });
    
    await dal.upsert('zoho_books_items', {
      zoho_id: '123',
      name: 'Item Name',
      // user_id automatically injected if requireUserId: true
      // created_at/updated_at automatically managed if autoTimestamps: true
    }, { onConflict: 'zoho_id' });
    
    // For user-specific operations
    const dal = new DataAccessLayer({
      useServiceRole: false,    // Use authenticated client
      requireUserId: true,      // Enforce user_id injection
      autoTimestamps: true      // Auto-manage timestamps
    });
    
    const profile = await dal.getSingle('profiles', { id: userId });
    await dal.insert('user_preferences', { key: 'theme', value: 'dark' });
    
    // ✅ CORRECT - Use DAL for auth context (preferred over direct)
    const dal = new DataAccessLayer({
      useServiceRole: false,
      requireUserId: false,
      autoTimestamps: false,
    });
    
    // Get user ID
    const userId = await dal.getCurrentUserId();
    
    // Get full user object
    const user = await dal.getCurrentUser();
    
    // ✅ CORRECT - Direct Supabase client ONLY for auth operations not covered by DAL
    // (e.g., supabase.auth.admin.createUser, supabase.auth.exchangeCodeForSession)
    import { createClient } from '@/libs/supabase/server';
    const supabase = await createClient();
    await supabase.auth.admin.createUser({ email: '[email protected]' });
    ```
    
    **DAL Methods:**
    - `dal.insert(tableName, records, options)` - Insert records
    - `dal.upsert(tableName, records, options)` - Upsert records
    - `dal.update(tableName, updates, filters)` - Update records
    - `dal.select(tableName, options)` - Select records with filters, ordering, pagination
    - `dal.delete(tableName, filters)` - Delete records
    - `dal.getSingle(tableName, filters)` - Get single record
    - `dal.getCurrentUserId()` - Get current user ID from auth context
    - `dal.getCurrentUser()` - Get current user object from auth context
    
    **DAL Options:**
    - `useServiceRole: boolean` - Use service role client (bypasses RLS)
    - `requireUserId: boolean` - Automatically inject user_id from auth context
    - `autoTimestamps: boolean` - Automatically manage created_at/updated_at
    
    **Key Points:**
    - DAL ensures RLS compliance and validates user_id matches
    - DAL automatically injects user_id when requireUserId: true
    - DAL automatically manages timestamps when autoTimestamps: true
    - DAL provides better error messages for RLS failures
    - Use service role for system-level operations (Zoho syncs, webhooks)
    - Use authenticated client for user-specific operations
    
    ### 3. **Supabase Client Usage** (For Auth Operations Only)
    **Direct Supabase client should ONLY be used for auth operations not covered by DAL.**
    
    ```javascript
    // ❌ WRONG - Will cause async cookies warning
    const supabase = createClient();
    
    // ✅ CORRECT - Always await in server components
    const supabase = await createClient();
    
    // ✅ CORRECT - Client components use different import
    import { createClient } from "@/libs/supabase/client"; // For client components
    import { createClient } from "@/libs/supabase/server"; // For server components (async)
    
    // ✅ CORRECT - Use DAL for getting user context (preferred)
    const dal = new DataAccessLayer({ useServiceRole: false });
    const user = await dal.getCurrentUser();
    const userId = await dal.getCurrentUserId();
    
    // ✅ CORRECT - Direct client ONLY for auth operations not in DAL
    // (e.g., admin operations, code exchange)
    const supabase = await createClient();
    await supabase.auth.admin.createUser({ email: '[email protected]' });
    const { data } = await supabase.auth.exchangeCodeForSession(code);
    ```
    
    ### 4. **Next.js 15 Conventions**
    
    #### Headers API
    ```javascript
    // ❌ WRONG - Synchronous headers access
    const signature = headers().get("stripe-signature");
    
    // ✅ CORRECT - Always await headers in Next.js 15
    const signature = (await headers()).get("stripe-signature");
    ```
    
    #### Proxy File (Not Middleware)
    **Next.js 15 uses `proxy.js` instead of `middleware.js`.**
    
    ```javascript
    // ✅ CORRECT - Use proxy.js file in project root
    // proxy.js
    import { updateSession } from "@/libs/supabase/middleware";
    
    export async function proxy(request) {
      return await updateSession(request);
    }
    
    export const config = {
      matcher: [/* ... */],
    };
    ```
    
    **Key Points:**
    - File name: `proxy.js` (not `middleware.js`)
    - Export function: `proxy` (not `middleware`)
    - See `proxy.js` in project root for reference
    
    ### 5. **Service Layer Pattern**
    ```javascript
    // ❌ WRONG - Business logic in route handler
    // app/api/zoho/items/route.js
    export async function GET(req) {
      const items = await fetch('https://books.zoho.com/api/v3/items');
      const processed = items.map(/* complex logic */);
      return NextResponse.json(processed);
    }
    
    // ✅ CORRECT - Thin route handler → Service → Zoho Class
    // app/api/zoho/items/route.js
    import { ZohoItemsService } from '@/libs/services/zoho/items';
    
    export async function GET(req) {
      const service = new ZohoItemsService();
      const items = await service.getAllItems();
      return NextResponse.json(items);
    }
    
    // libs/services/zoho/items.js
    import zoho from '@/libs/zoho';
    import { DataAccessLayer } from '@/libs/supabase/data-access-layer';
    
    export class ZohoItemsService {
      constructor() {
        this.dal = new DataAccessLayer({
          useServiceRole: true,
          requireUserId: false,
          autoTimestamps: true,
        });
      }
    
      async getAllItems() {
        // Business logic here
        // MUST use zoho class - never direct API calls
        const itemsData = await zoho.getBooksItems();
        
        // Use DAL for database operations
        for (const item of itemsData) {
          await this.dal.upsert('zoho_books_items', {
            zoho_id: item.id,
            name: item.name,
            // ... other fields
          }, { onConflict: 'zoho_id' });
        }
        
        return itemsData;
      }
    }
    ```
    
    ### 6. **Data Synchronizer Storage Pattern**
    
    The `zoho_books_*` tables have been removed (migration 027). All Zoho Books data now lives in the lean `zb_*` tables created by migration 026. Each table has:
    - `external_id` — Zoho's native ID (e.g., `item_id`, `invoice_id`)
    - `source_system` — `'zoho_books'` or `'zoho_crm'`
    - `indexes` — JSONB with fields needed for fast lookups (defined in `libs/data-synchronizer/registry.js`)
    - `raw_json` — full Zoho payload for detail views
    - `remote_updated_at` — `last_modified_time` from Zoho; used for incremental sync decisions
    
    ```javascript
    // ❌ WRONG - old zoho_books_* tables no longer exist
    await dal.upsert('zoho_books_items', dbRecord, { onConflict: 'zoho_id' });
    
    // ✅ CORRECT - use SyncRecordRepository + adapter
    import '@/libs/data-synchronizer/index';          // registers all adapters
    import { SyncRecordRepository } from '@/libs/data-synchronizer/storage/SyncRecordRepository';
    import { getAdapterForTable }   from '@/libs/data-synchronizer/registry';
    
    const repo    = new SyncRecordRepository();
    const Adapter = getAdapterForTable('zb_items');
    
    await repo.upsertOne('zb_items', {
      external_id:       Adapter.extractExternalId(zohoItem),
      source_system:     'zoho_books',
      indexes:           Adapter.extractIndexes(zohoItem),
      raw_json:          zohoItem,
      remote_updated_at: Adapter.extractRemoteUpdatedAt(zohoItem),
    });
    
    // Reading items by SKU (preserves old response shape for consumers)
    const dal = new DataAccessLayer({ useServiceRole: true, requireUserId: false, autoTimestamps: false });
    const { data } = await dal.select('zb_items', {
      queryBuilder: q => q.select('external_id, indexes').in('indexes->>sku', skus),
    });
    const items = data.map(r => ({
      zoho_id:        r.external_id,
      sku:            r.indexes?.sku,
      name:           r.indexes?.name,
      reorder_level:  r.indexes?.reorder_level,
      stock_on_hand:  r.indexes?.qty,
      available_stock: r.indexes?.available_stock,
    }));
    ```
    
    **Current Table Names (zb_* = Zoho Books, zcrm_* = Zoho CRM):**
    - `zb_items` — items/products (replaces `zoho_books_items`)
    - `zb_invoices` — invoices (replaces `zoho_books_invoices`)
    - `zb_salesorders` — sales orders (replaces `zoho_books_salesorders`)
    - `zb_purchaseorders` — purchase orders (replaces `zoho_books_purchaseorders`)
    - `zb_bills` — bills (replaces `zoho_books_bills`)
    - `zb_contacts` — Books contacts
    - `zb_lineitems` — all line items (sales orders, invoices, POs, bills); has `parent_type`, `parent_external_id`
    - `zcrm_contacts` — Zoho CRM contacts
    
    Index fields per table are defined in `libs/data-synchronizer/registry.js`.
    
    ### 7. **File Upload Chunking** (For Large File Ingestion)
    
    **ALL file-based data ingestion features MUST use the shared chunking utilities** from `@/libs/upload-chunking.js` to avoid Next.js request body size limits (proxyClientMaxBodySize default ~10MB, configurable in `next.config.js`).
    
    - **`chunkCsv(csvText, options)`** — For CSV with header row. Splits by byte size; each chunk includes the header. Use for Antigen Designer ingestion, PIM CSV, etc.
    - **`chunkNdjson(text, options)`** — For NDJSON (one JSON per line). Splits by line count. Use for Data Synchronizer NDJSON uploads.
    
    ```javascript
    // ✅ CORRECT - Use shared chunking
    import { chunkCsv, chunkNdjson } from '@/libs/upload-chunking';
    
    // CSV with header
    const csvChunks = chunkCsv(await file.text(), { chunkBytes: 15 * 1024 * 1024 });
    for (let i = 0; i < csvChunks.length; i++) {
      const fd = new FormData();
      fd.append('file', new Blob([csvChunks[i]], { type: 'text/csv' }), file.name);
      const result = await apiClient.post(endpoint, fd);
      // aggregate result...
    }
    
    // NDJSON (no header)
    const ndjsonChunks = chunkNdjson(await file.text(), { linesPerChunk: 500 });
    for (const chunk of ndjsonChunks) {
      const fd = new FormData();
      fd.append('file', new Blob([chunk], { type: 'text/plain' }), 'chunk.ndjson');
      // ...
    }
    ```
    
    ```javascript
    // ❌ WRONG - Defining chunking logic inline per feature
    function myChunkCsv(text) { /* duplicate implementation */ }
    ```
    
    **Key points:**
    - Do NOT define chunking logic inline in individual pages/components
    - Use `chunkCsv` for header-preserving CSV splits; use `chunkNdjson` for line-based NDJSON
    - Upload chunks sequentially; aggregate results client-side
    - `next.config.js` sets `experimental.proxyClientMaxBodySize` for overall limit (e.g. 500mb)
    
    ## 🔐 Authentication & Authorization
    
    ### Route Protection
    - **Public routes**: Use `app/(public)/layout.js` - no auth check
    - **Private routes**: Use `app/(private)/layout.js` - checks Supabase auth, redirects to `/signin` if not logged in
    - **Admin routes**: Use `app/(private)/admin/layout.js` - checks auth, future: add role/permission checks
    
    ### Login Flow
    1. User visits protected route
    2. `(private)/layout.js` checks authentication using DAL
    3. If not authenticated → redirect to `/signin`
    4. After successful login → redirect to `config.auth.callbackUrl` (default: `/admin`)
    
    ### Auth Implementation Pattern
    ```javascript
    // ✅ CORRECT - Use DAL for auth checks in layouts
    import { DataAccessLayer } from '@/libs/supabase/data-access-layer';
    
    export default async function PrivateLayout({ children }) {
      const dal = new DataAccessLayer({
        useServiceRole: false,
        requireUserId: false,
        autoTimestamps: false,
      });
      
      const user = await dal.getCurrentUser();
      
      if (!user) {
        redirect(config.auth.loginUrl);
      }
      
      // ... rest of layout
    }
    ```
    
    ## 📦 Key Modules (Implementation Order)
    
    ### Phase 1: Foundation (Current)
    1. ✅ Authentication & login
    2. ✅ Folder structure (`(public)` and `(private)/admin`)
    3. ✅ Layout files with auth checks
    4. ✅ Logging system (Logger utility + log viewer scripts)
    5. ✅ Data Access Layer (DAL) implementation
    6. ✅ Zoho Books sync infrastructure
    
    ### Phase 2: Core Integration
    1. **Zoho Books sync + cache + reconciliation**
       - Webhook ingestion endpoints
       - Rate-limited sync jobs
       - Daily reconciliation
       - Historical sync service
    
    2. **Procurement & fulfillment operational signals**
       - PO quantity calculations
       - Backorder/on-the-way signals
       - SO guardrails
    
    ### Phase 3: Extended Features
    3. Zoho CRM ingestion + tools
    4. Quote lifecycle automation
    5. Customer portal widgets
    6. Zoho Desk sync
    7. Marketing attribution dashboards
    8. Sales analytics + AI curation
    9. PIM (Product Information Management)
    10. Loyalty system
    11. Notifications
    12. Monitoring/alerts framework
    
    ## 🎨 Styling Rules
    
    ### Tailwind CSS v4 Syntax
    ```css
    @import "tailwindcss";
    @plugin "daisyui";
    
    @theme {
      --color-primary: #570df8; /* Boster brand color - adjust as needed */
    }
    ```
    
    ### DaisyUI v5 Component Usage
    ```html
    <div class="card card-border"> <!-- v5: card-border instead of card-bordered -->
    <button class="btn btn-primary btn-sm">
    ```
    
    ## 🚫 Common Mistakes to Avoid
    
    1. **DON'T** make Zoho API calls without using the Zoho class from `@/libs/zoho.js`
    2. **DON'T** code Zoho API operations from scratch - always use zoho class methods
    3. **DON'T** use direct fetch/axios calls to Zoho APIs - use zoho.get(), zoho.post(), etc.
    4. **DON'T** use direct `supabase.from()` calls for database operations - use DAL
    5. **DON'T** store Zoho data as source of truth (it's a cache)
    6. **DON'T** use synchronous `headers()` or `cookies()` in Next.js 15
    7. **DON'T** put business logic directly in route handlers
    8. **DON'T** import unused dependencies
    9. **DON'T** use `createClient()` without await in server components
    10. **DON'T** replicate GA4-scale data into Nexus DB (pull on-demand from BigQuery)
    11. **DON'T** use `console.log/error/warn` for production logging - use `Logger` from `@/libs/utils/logger`
    12. **DON'T** use `middleware.js` - use `proxy.js` for Next.js 15
    13. **DON'T** use table names like `zoho_cache_*` - actual tables are `zoho_books_*`
    
    ## 🔧 Development Best Practices
    
    ### Async Jobs Pattern
    ```javascript
    // For long-running or rate-limited operations:
    // 1. Insert job into queue using DAL
    import { DataAccessLayer } from '@/libs/supabase/data-access-layer';
    
    const dal = new DataAccessLayer({ useServiceRole: true });
    await dal.insert('jobs_sync', {
      type: 'items_full_refresh',
      status: 'pending',
      payload: { /* ... */ }
    });
    
    // 2. Background worker processes jobs (separate process/cron)
    // Uses rate limiter, handles retries, updates status
    ```
    
    ### Error Handling
    ```javascript
    // Always handle Zoho API errors gracefully
    import zoho from '@/libs/zoho';
    import { Logger } from '@/libs/utils/logger';
    import { DataAccessLayer } from '@/libs/supabase/data-access-layer';
    
    try {
      const data = await zoho.getBooksItems();
    } catch (error) {
      if (error.message.includes('429')) {
        // Rate limited - should queue as job instead
        const dal = new DataAccessLayer({ useServiceRole: true });
        await dal.insert('jobs_sync', {
          type: 'items_refresh',
          status: 'pending',
          payload: { retryAfter: error.retryAfter }
        });
      }
      // Log errors using Logger (not console.error)
      Logger.error('Zoho API error', error, { 
        operation: 'getBooksItems',
        service: 'books'
      });
    }
    ```
    
    ### Logging System
    **ALWAYS use the Logger utility instead of console.log/error/warn for production code.**
    
    The project has a structured logging system that writes to files in the `logs/` directory. Logs are organized by level and are accessible to AI agents for debugging.
    
    **Logger Usage:**
    ```javascript
    // ✅ CORRECT - Use Logger utility
    import { Logger } from '@/libs/utils/logger';
    
    // Log errors (with error object and context)
    Logger.error('Operation failed', error, { 
      userId: '123',
      operation: 'syncItems',
      service: 'books'
    });
    
    // Log warnings
    Logger.warn('Rate limit approaching', { 
      remaining: 10,
      service: 'books'
    });
    
    // Log info messages
    Logger.info('Items synced successfully', { 
      count: 5,
      service: 'books'
    });
    
    // Log debug (only in development)
    Logger.debug('Processing batch', { 
      batchNumber: 1,
      size: 50
    });
    
    // ❌ WRONG - Don't use console methods for production logging
    console.error('Error:', error);
    console.log('Info:', data);
    console.warn('Warning:', message);
    ```
    
    **Log Files:**
    - Logs are written to `logs/` directory in the project root
    - Level-specific files: `error.log`, `warn.log`, `info.log`, `debug.log`
    - Combined file: `combined.log` (all levels)
    - Log files are JSON-formatted, one entry per line
    - Log files are git-ignored (see `.gitignore`)
    
    **Checking Logs:**
    ```bash
    # View recent error logs (default: last 50)
    npm run logs:error
    
    # View recent info logs
    npm run logs:info
    
    # View all recent logs (combined)
    npm run logs:combined
    
    # Or use the script directly with custom parameters
    node scripts/check-logs.js error 20   # Last 20 error logs
    node scripts/check-logs.js info 100   # Last 100 info logs
    node scripts/check-logs.js warn 30    # Last 30 warning logs
    ```
    
    **When to Use Logging:**
    - **Error**: Always log errors with full context (error object, operation, relevant IDs)
    - **Warn**: Use for recoverable issues, rate limit warnings, validation failures
    - **Info**: Use for important operations (syncs, API calls, state changes)
    - **Debug**: Use for detailed debugging info (only in development)
    
    **Best Practices:**
    - Always include context data (service, operation, IDs, counts)
    - Use structured data objects, not string concatenation
    - Log at appropriate levels (don't log everything as error)
    - Include error objects when logging errors
    - Log important state changes and sync operations
    
    ## 🎯 Commit Message Format
    Use Conventional Commits:
    - `feat:` for new features
    - `fix:` for bug fixes  
    - `refactor:` for code refactoring
    - `style:` for formatting changes
    - `docs:` for documentation
    - `perf:` for performance improvements
    - `chore:` for maintenance tasks
    
    ## 🔍 Before Committing Checklist
    - [ ] No unused imports
    - [ ] All async functions properly awaited
    - [ ] **All Zoho API calls use zoho class from `@/libs/zoho.js`** (MANDATORY)
    - [ ] No direct fetch/axios calls to Zoho APIs
    - [ ] **All database operations use DAL from `@/libs/supabase/data-access-layer.js`** (MANDATORY)
    - [ ] No direct `supabase.from()` calls for database operations
    - [ ] **Use Logger utility instead of console methods for production logging**
    - [ ] No ESLint warnings
    - [ ] Build passes (`npm run build`)
    - [ ] All environment variables checked
    - [ ] Proper error handling in API routes
    - [ ] Server/client components used correctly
    - [ ] Business logic in service layer, not route handlers
    - [ ] Using `proxy.js` (not `middleware.js`) for Next.js 15
    
    ## 🛠️ Development Commands
    ```bash
    npm run dev          # Development with Turbopack
    npm run build        # Production build
    npm run lint         # ESLint check
    npm run lint:fix     # Auto-fix ESLint issues
    
    # Log viewing commands
    npm run logs         # View recent error logs (default)
    npm run logs:error   # View recent error logs
    npm run logs:info    # View recent info logs
    npm run logs:combined # View all recent logs
    ```
    
    ## 📝 Environment Variables
    
    Required environment variables (see `.env.local`):
    - `NEXT_PUBLIC_SUPABASE_URL`
    - `NEXT_PUBLIC_SUPABASE_ANON_KEY`
    - `SUPABASE_SERVICE_ROLE_KEY`
    - `ZOHO_BOOKS_CLIENT_ID`
    - `ZOHO_BOOKS_CLIENT_SECRET`
    - `ZOHO_BOOKS_ACCESS_TOKEN` (or refresh token flow)
    - `ZOHO_CRM_CLIENT_ID` (similar pattern)
    - `ZOHO_CRM_CLIENT_SECRET`
    - `ZOHO_DESK_CLIENT_ID` (similar pattern)
    - `ZOHO_DESK_CLIENT_SECRET`
    - `DATABASE_URL` or `SUPABASE_DB_URL` or `SUPABASE_DB_PASSWORD` (for migrations)
    
    Remember: This is an **internal operations tool**. Focus on reliability, data accuracy, and efficient cross-system workflows. Always respect rate limits and maintain clean separation between cache and source of truth.

    Comments

    More Rules

    View all
    Web Development

    Next.js 15 + TypeScript Cursor Rules

    Comprehensive .cursorrules file for Next.js 15 App Router projects with TypeScript, enforcing server components by default, proper use of "use client" directive, and App Router conventions.

    C
    Community
    Backend Development

    Python FastAPI Best Practices Rules

    Cursor rules for Python FastAPI projects enforcing async patterns, Pydantic v2 models, dependency injection, and proper error handling.

    C
    Community
    Frontend Development

    React + TypeScript Component Rules

    Rules for consistent React component development with TypeScript interfaces, proper hook patterns, and component composition.

    C
    Community
    AI/ML

    Cursor Agent Mode Configuration

    Rules optimizing Cursor Agent mode behavior including multi-file editing context, session management, and autonomous task completion patterns.

    C
    Cursor Team
    Frontend Development

    Tailwind CSS + shadcn/ui Rules

    Cursor rules for projects using Tailwind CSS with shadcn/ui component library, enforcing consistent utility class usage and component patterns.

    C
    Community
    Backend Development

    Go Backend Service Rules

    Rules for Go backend services enforcing idiomatic Go patterns, proper error handling, and clean architecture conventions.

    C
    Community

    Stay up to date

    Get the latest Cursor prompts, rules, and resources delivered to your inbox weekly.

    Neura Market LogoNeura Market

    Discover the best AI prompts, plugins, and resources for Cursor and more.

    Content Types

    • Rules
    • Prompts
    • MCPs
    • Agents
    • Guides

    Platforms

    • ChatGPT Directory
    • Claude Directory
    • Gemini Directory
    • Cursor Directory
    • Grok Directory
    • Perplexity Directory
    • DeepSeek Directory
    • CoPilot Directory
    • Stable Diffusion Directory
    • Midjourney Directory
    • All Directories

    Resources

    • Blog
    • Documentation
    • Help Center
    • Marketplace

    Legal

    • Privacy Policy
    • Terms of Service

    © 2026 Neura Market. All rights reserved.

    |

    Not affiliated with any AI platform vendors.