Frontend development standards for Next.js 15, React 19, TypeScript, Tailwind CSS, Cmx Design System. Use when creating components, pages, forms, or frontend code.
components/ folder - use src/ui/ or src/features/*/ui/app/ # Next.js App Router (routing only - page.tsx, layout.tsx)
src/
ui/ # Global Cmx Design System (Cmx* prefix REQUIRED)
primitives/ # CmxButton, CmxInput, CmxCard
data-display/ # CmxDataTable, CmxKpiCard
forms/ # CmxForm, CmxFormField
navigation/ # CmxAppShell, CmxBreadcrumbs
features/ # Feature modules (domain-specific)
orders/
ui/ # OrderListScreen, OrderFilters
api/ # orders-api.ts
hooks/ # use-orders.ts
model/ # order-types.ts
lib/ # Shared infrastructure (api, supabase, hooks, utils)
import { CmxButton } from '@ui/primitives/cmx-button'
import { OrderListScreen } from '@features/orders/ui/order-list-screen'
import { apiClient } from '@lib/api/client'
DO NOT create other paths like @/components or @/core.
src/ui/ with Cmx prefixComponents that are:
Examples: CmxButton, CmxInput, CmxForm, CmxDataTable, CmxPageHeader
src/features/<module>/uiComponents containing business/domain logic:
OrderStatusBadgeCustomerTierBadgeOrderListScreenTenantSettingsFormapp/Only use for routing and composition:
// app/dashboard/orders/page.tsx
import { OrderListScreen } from '@features/orders/ui/order-list-screen'
export default async function OrdersPage() {
return <OrderListScreen />
}
rgb(var(--cmx-primary-rgb))flex, grid, gap-4, p-4ml-4 rtl:ml-0 rtl:mr-4text-blue-500, bg-red-500#1d4ed8, #ef4444src/ui first)import { useTranslations } from 'next-intl';
export default function OrdersPage() {
const tCommon = useTranslations('common'); // For common keys
const t = useTranslations('orders'); // For feature keys
return (
<div>
<h1>{t('title')}</h1>
<button>{tCommon('save')}</button>
</div>
);
}
CRITICAL:
tCommon() for common keys like save, cancel, deleteen.json and ar.json when adding translations// Direction-aware spacing
<div className="ml-4 rtl:ml-0 rtl:mr-4">Content</div>
// Direction-aware icons
<ChevronRight className="rtl:rotate-180" />
import { CmxButton } from '@ui/primitives'
import { CmxCard, CmxCardHeader, CmxCardContent } from '@ui/primitives/cmx-card'
import { CmxDialog, CmxDialogContent, CmxDialogHeader, CmxDialogTitle, CmxDialogFooter } from '@ui/overlays'
import { CmxTabsPanel } from '@ui/navigation'
import { CmxDataTable } from '@ui/data-display'
import { CmxProgressBar, CmxSummaryMessage } from '@ui/feedback'
import { CmxSelectDropdown, CmxSelectDropdownTrigger, CmxSelectDropdownContent, CmxSelectDropdownItem } from '@ui/forms'
import { OrderListScreen } from '@features/orders/ui/order-list-screen'
import { supabaseClient } from '@lib/supabase/client'
npm run build)import X from '@ui/compat' // NO - removed, causes build failure
import Y from '@/components/ui' // NO - doesn't exist
import Z from '@/components/ui/*' // NO - doesn't exist
import W from '@/app/components/...' // NO - never import from app
import V from '@/components/...' // NO - components folder doesn't exist
Full import snippets per component type: see
.claude/docs/web-admin-ui-imports.md
// API endpoint returns paginated data
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const page = parseInt(searchParams.get('page') || '1');
const pageSize = parseInt(searchParams.get('pageSize') || '20');
const { data, total } = await getOrders({ page, pageSize });
return Response.json({ data, total, page, pageSize });
}
import { CmxDataTable } from '@ui/data-display/cmx-datatable';
<CmxDataTable
columns={columns}
data={data}
pagination="server" // REQUIRED for server-side
totalRows={total}
onPageChange={handlePageChange}
/>
When building or implementing a report (screen, component, page, tool):
{feature}-{report-name}-rprtorders-payments-print-rprt.tsx, customers-summary-rprt.tsx, financial-monthly-rprt.tsx-rprt suffix identifies it as a report and separates it from regular UI components❌ orders-payments-print.tsx — missing suffix
✅ orders-payments-print-rprt.tsx — correct