Always organize imports with proper comment headers and spacing:
// ** import types
import type { TypeName, AnotherType } from "@/types/module";
// ** import utils
import { utilFunction } from "wxt/utils/module";
// ** import lib
import { LibClass } from "@/lib/module";
import { AnotherClass } from "./localModule";
// ** import apis
import { apiFunction } from "@/api/module";
// ** import constants
import { CONSTANT_VALUE } from "./constants";
// ** import styles
import "@/entrypoints/style.css";- Always add 1 line space between different import sections
- Use exact comment format:
// ** import [category] - Group related imports under the same comment section
- Order from abstract to concrete: types → utils → lib → apis → constants → styles
- No additional descriptive text in comments - just the category name
// ** import types- TypeScript type imports only// ** import utils- Utility functions and helpers// ** import lib- Library/class imports from local modules// ** import apis- API-related imports// ** import constants- Constant/configuration imports// ** import styles- CSS/style imports
✅ Good:
// ** import types
import type { FormField } from "@/types/extension";
// ** import lib
import { ElementUtils } from "./elementUtils";
import { SoundManager } from "@/lib/utils/soundManager";❌ Bad:
import type { FormField } from "@/types/extension";
import { ElementUtils } from "./elementUtils";
import { SoundManager } from "@/lib/utils/soundManager";❌ Bad:
// ** import types
import type { FormField } from "@/types/extension";
// ** import lib utilities
import { ElementUtils } from "./elementUtils";This pattern ensures consistent, readable import organization across the entire codebase.
- Separation of Concerns: Keep API functions completely separate from React components
- Centralized Configuration: Use a single axios instance configuration for all API calls
- Domain-Based Organization: Group API functions by feature/domain in dedicated folders
- Single Source of Truth: Centralize reusable UI configurations and shared resources
- Consistent File Structure: Follow established patterns for predictable code organization
apps/admin-cms/src/api/
├── config/
│ └── axios.ts # Centralized axios configuration
├── onboarding/
│ ├── signup.ts # Onboarding-specific API calls
│ └── verification.ts
├── upload/
│ ├── get-signed-upload-url.ts
│ ├── delete-file.ts
│ └── index.ts # Export all upload functions
└── products/
├── create-product.ts
└── get-products.ts
// ** import config
import axiosInstance from "@/config/axios";
// ** import types
import type { RequestType, ResponseType } from "@/types/feature";
/**
* Brief description of what this API function does
*
* @param data - Description of input parameter
* @returns Promise with response type
*/
export const functionName = async (
data: RequestType,
): Promise<ResponseType> => {
const response = await axiosInstance.post<ResponseType>("/endpoint", data);
return response.data;
};- Central Configuration: All upload destinations defined in
src/config/upload-paths.ts - Path Consistency: Use predefined constants instead of hardcoded strings
- Feature-Based Paths: Organize upload paths by application feature
// ✅ Good: Using centralized upload paths
import { UPLOAD_PATHS } from "@/config/upload-paths";
const path = UPLOAD_PATHS.ONBOARDING.BANK_DOCUMENTS;
// ❌ Bad: Hardcoded upload paths
const path = "bank-documents";- Dedicated Folder: All upload-related APIs in
src/api/upload/ - Function Separation: One API function per file for upload operations
- Consistent Naming: Use descriptive, action-based file names
apps/admin-cms/src/data/
├── dropdown-options.ts # Global dropdown configurations
└── products/
├── status-options.ts # Product-specific status options
├── category.ts # Product categories
└── index.ts # Export all product data
// ** Centralized dropdown options
export interface StatusOption {
value: string;
label: string;
color?: string;
}
export const STATUS_OPTIONS: StatusOption[] = [
{ value: "active", label: "Active", color: "green" },
{ value: "inactive", label: "Inactive", color: "red" },
];// ✅ Good: Import API functions, keep components clean
import { submitOnboardingSignup } from "@/api/onboarding/signup";
import { STATUS_OPTIONS } from "@/data/products/status-options";
const MyComponent = () => {
const handleSubmit = async (data) => {
try {
const result = await submitOnboardingSignup(data);
// Handle success
} catch (error) {
// Handle error
}
};
};
// ❌ Bad: Inline API calls in components
const MyComponent = () => {
const handleSubmit = async (data) => {
const response = await axios.post("/onboarding/signup", data);
};
};- Maintainability: Easy to locate and update API logic
- Reusability: API functions can be shared across components
- Testing: API functions can be unit tested independently
- Type Safety: Centralized type definitions ensure consistency
- Configuration Management: Single source of truth for shared resources
Before implementing new API functionality:
- API function is in appropriate domain folder
- Uses centralized axios configuration
- Follows established naming conventions
- Includes proper TypeScript types
- Upload paths use centralized configuration
- Reusable data is centralized in
/datafolder - Component remains focused on UI logic only
When API files become large or contain multiple endpoints, follow these splitting rules:
- One API endpoint per file
- One schema per file
- Each file should handle exactly one operation
apps/gcr-server/src/routes/products/
├── brand/ # Brand domain
│ ├── index.ts # Domain router
│ ├── get-brands.ts # GET /products/brands
│ └── get-brand-details.ts # GET /products/brands/:id
├── org-defaults/ # Organization defaults domain
│ ├── index.ts
│ ├── get-colors.ts # GET /products/org-colors
│ └── get-sizes.ts # GET /products/org-sizes
└── product/ # Product CRUD domain
├── index.ts
├── create-product.ts # POST /products
├── get-products.ts # GET /products
└── update-product.ts # PATCH /products/:id
apps/gcr-server/src/schema/products/
├── brand/
│ └── index.ts
├── org-defaults/
│ └── index.ts
└── product/
├── index.ts
├── create-product.schema.ts
└── update-product.schema.ts
- Use kebab-case for file names
- Use descriptive action-resource naming:
get-products.ts- List productsget-product-details.ts- Single productcreate-product.ts- Create productupdate-product-status.ts- Update specific fieldbulk-delete-products.ts- Bulk operations
Each domain folder must have an index.ts that exports the domain router:
// apps/gcr-server/src/routes/products/product/index.ts
import { Hono } from "hono";
import { createProductRoute } from "./create-product";
import { getProductsRoute } from "./get-products";
export const productRoutes = new Hono();
productRoutes.route("/", createProductRoute);
productRoutes.route("/", getProductsRoute);// apps/gcr-server/src/routes/products/index.ts
import { Hono } from "hono";
import { productRoutes } from "./product";
import { brandRoutes } from "./brand";
const products = new Hono();
products.route("/", productRoutes);
products.route("/", brandRoutes);
export { products };- Individual files: Export named route constants
- Index files: Export domain routers
- Schema files: Export individual schemas
- Schema index: Re-export all schemas from domain
- Files under 150 lines
- Single endpoint with minimal logic
- Tightly coupled operations that share significant logic
Before splitting files, ensure:
- Each file has single responsibility
- Proper middleware usage maintained
- Import paths updated correctly
- Schema organization mirrors API structure
- Index files properly export routes
- TypeScript compilation passes
- Consistent naming conventions used
This organized approach ensures maintainable, scalable API development with clear separation of concerns.