---
description:
globs:
alwaysApply: true
---
# Code Guidelines for Influencer–Vendor Automation Platform

## 1. Project Overview  
A unified web platform to automate ordering, shipping, settlement, and notifications between influencers and vendors.  
Key architectural decisions:  
- Frontend: Vue 3 + Nuxt 3 (SSR/SSG), Composition API, TypeScript, Pinia, Vuetify, Axios  
- BFF: Node.js + Express (ES Modules), Socket.IO for real-time  
- Backend API: CodeIgniter 4 RESTful controllers, MySQL (RDS), Redis cache  
- Deployment: Docker → Kubernetes, CI/CD via GitHub Actions  
- Integrations: Google Cloud Vision OCR, Courier & ERP REST APIs, JWT/OAuth2 authentication  

---

## 2. Core Principles  
1. Single Responsibility: each function/module addresses one concern; max 200 lines.  
2. Strong Typing: avoid `any`; define interfaces for props, DTOs, API responses.  
3. Consistent Error Handling: centralize and standardize error responses and logs.  
4. DRY & Reusable: extract shared logic into composables, services, or utilities.  
5. Domain-Driven Modules: group files by business domain (order, shipping, finance).  

---

## 3. Language-Specific Guidelines  

### 3.1 Vue 3 + Nuxt 3 + TypeScript  
- File Organization:  
  - `/pages` → route pages  
  - `/components/{domain}` → feature components  
  - `/composables` → reusable logic hooks (prefixed `useXxx`)  
  - `/stores/{domain}` → Pinia modules (one per domain)  
  - `/plugins`, `/middleware`, `/assets`, `/layouts`  
- Imports & Aliases:  
  - Use Nuxt aliases: `import X from '~/components/order/OrderList.vue'`  
  - Group imports: external packages → aliased aliases → relative (sorted alphabetically)  
- Error Handling:  
  - Global error plugin `~/plugins/error.ts` to catch and display Axios errors  
  - In composable:  
    ```ts
    export async function useFetchOrders() {
      try {
        const { data } = await $axios.get<Order[]>('/api/orders')
        return data
      } catch (error: unknown) {
        throw new ApiError(error)
      }
    }
    ```  

### 3.2 Node.js + Express (BFF)  
- Folder Structure:  
  ```
  /src
    /controllers
    /services
    /routes
    /middlewares
    /utils
    app.js
  ```
- Dependency Management:  
  - Use ES Modules (`"type": "module"`) or TypeScript.  
  - Version-lock in `package.json`; run `npm audit` in CI.  
- Error Handling:  
  - Create `HttpError` class in `/utils/HttpError.js`  
  - Middleware `errorHandler.js` at the end:  
    ```js
    app.use((err, req, res, next) => {
      logger.error(err)
      res.status(err.statusCode || 500).json({
        success: false,
        message: err.message || 'Internal Server Error'
      })
    })
    ```  

### 3.3 CodeIgniter 4 (REST API)  
- Controllers: one per resource, extend `ResourceController`  
- Models: use Entities and Query Builder; keep business logic in Services  
- Validation & Responses:  
  ```php
  public function create()
  {
    $rules = ['order_id' => 'required|integer', /* ... */];
    if (! $this->validate($rules)) {
      return $this->fail($this->validator->getErrors());
    }
    $entity = new OrderEntity($this->request->getPost());
    $this->orderService->save($entity);
    return $this->respondCreated($entity);
  }
  ```
- Error Handling: use `HTTPException` for 404/403, global logging in `app/Filters`.  

---

## 4. Code Style Rules  

### 4.1 MUST Follow  
- **Use Strict Typescript**  
  Rationale: catch errors at compile time.  
  ```jsonc
  // tsconfig.json
  {
    "compilerOptions": {
      "strict": true,
      "noImplicitAny": true,
      "forceConsistentCasingInFileNames": true
    }
  }
  ```  
- **One Component per File**  
  Rationale: clarity, reusability, smaller diffs.  
- **Composition API & `<script setup>`**  
  Rationale: simpler syntax and tree-shaking.  
  ```vue
  <script setup lang="ts">
  import { ref } from 'vue'
  const count = ref(0)
  function increment() { count.value++ }
  </script>
  ```  
- **Pinia Stores for State**  
  Rationale: predictable global state with actions, getters.  
  ```ts
  import { defineStore } from 'pinia'
  export const useOrderStore = defineStore('order', {
    state: () => ({ list: [] as Order[] }),
    actions: {
      async fetch() { this.list = await fetchOrders() }
    }
  })
  ```  
- **RESTful API Design**  
  Rationale: consistency and predictability.  
  - Use resource paths: `/vendors/{id}/orders`  
  - HTTP verbs: GET/POST/PUT/DELETE  
  - Standard response envelope:  
    ```json
    { "success": true, "data": {...}, "error": null }
    ```  
- **Centralized Error Handler**  
  Rationale: unified logging and client messages.  

### 4.2 MUST NOT Do  
- **Avoid `any` or disabling lint rules**  
  Rationale: loses type-safety.  
- **No Large “God” Modules**  
  Rationale: hard to test and maintain.  
- **No Inline Styles or Scripts**  
  Rationale: separates concerns; use Vuetify theme or SCSS.  
- **No Nested Callbacks (Callback Hell)**  
  Rationale: use async/await or Promises.  
- **No Direct DOM Manipulation**  
  Rationale: Vue manages DOM; use refs or directives.  

---

## 5. Architecture Patterns  

### 5.1 Component & Module Structure  
- Domain-Driven Folders:  
  ```
  /components/order
  /components/shipping
  /composables/order
  /stores/order
  /services/api/order.ts
  ```  
- Layers in BFF:  
  - **Routes** → **Controllers** → **Services** → **Data Access**  

### 5.2 Data Flow  
- **Frontend**: Props ↓, Events ↑, Store (Pinia) for shared state, Composables for side-effects.  
- **API Calls**: Axios interceptors attach JWT, handle 401 globally, retry logic for idempotent GETs.  
- **Real-time**: Socket.IO client in plugin; update Pinia store on events.  

### 5.3 State Management  
- Local state in component for UI-only values (`ref`, `reactive`).  
- Global state in Pinia: one store per domain; expose typed actions/getters.  
- Keep store actions async, commit minimal state changes.  

### 5.4 API Design Standards  
- Base URL per domain: `/api/v1/orders`, `/api/v1/vendors`  
- Pagination: standard query `?page=1&limit=20`, return `{ items, total, page, limit }`.  
- Filtering & Sorting: query params `?status=shipped&sort=-date`.  
- Consistent Error Payload:  
  ```json
  {
    "success": false,
    "error": {
      "code": "VALIDATION_FAILED",
      "message": "Invalid field: quantity"
    }
  }
  ```  

---

## 6. Example Code Snippets  

### 6.1 Vue Composition & API Call  
```ts
// MUST: composable with typed response and error handling
import { ref } from 'vue'
import { Order } from '~/types'
import { useApi } from '~/composables/useApi'

export function useOrders() {
  const list = ref<Order[]>([])
  const error = ref<string | null>(null)
  async function fetchOrders() {
    try {
      const res = await useApi().get<Order[]>('/orders')
      list.value = res.data
    } catch (e) {
      error.value = e.message
    }
  }
  return { list, error, fetchOrders }
}
```

```ts
// MUST NOT: direct Axios calls in component, untyped any
setup() {
  axios.get('/orders').then(res => {
    this.orders = res.data
  })
}
```

### 6.2 Node.js Express Route & Error  
```js
// MUST: clean controller and error propagation
// src/routes/order.js
import { Router } from 'express'
import { listOrders } from '../controllers/order.js'
const router = Router()
router.get('/', listOrders)
export default router

// src/controllers/order.js
export async function listOrders(req, res, next) {
  try {
    const orders = await OrderService.fetchAll()
    res.json({ success: true, data: orders })
  } catch (err) {
    next(new HttpError(500, 'Failed to fetch orders'))
  }
}
```

```js
// MUST NOT: catch without forwarding or unstructured response
app.get('/orders', async (req, res) => {
  try {
    const orders = await OrderService.fetchAll()
    res.send(orders)
  } catch (err) {
    res.status(500).send('Error')
  }
})
```

### 6.3 CodeIgniter4 Controller  
```php
// MUST: validate, use entity, consistent response
class OrderController extends ResourceController
{
  public function create()
  {
    $rules = ['vendor_id'=>'required|integer', 'items'=>'required|array'];
    if (! $this->validate($rules)) {
      return $this->failValidationErrors($this->validator->getErrors());
    }
    $order = new OrderEntity($this->request->getPost());
    $this->orderService->create($order);
    return $this->respondCreated(['order' => $order]);
  }
}
```

```php
// MUST NOT: raw SQL in controller, no validation
class OrderController extends BaseController
{
  public function create()
  {
    $db->query("INSERT INTO orders ..."); // anti-pattern
  }
}
```

---

End of Guidelines.  
Follow these rules as the single source of truth for code quality, maintainability, and consistency.
