.cursor/skills/nazim-platform-admin/SKILL.md
Enforces patterns for creating and maintaining platform admin pages in Nazim. Use when adding new platform management pages, routes, or API endpoints. Covers 5-step checklist, platformApi, usePlatformAdminPermissions, no organization_id.
npx skillsauth add AHMADJAN-New/nazim-web nazim-platform-adminInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The Platform Admin app is separate from the main Nazim app. Platform admins manage the entire platform (all organizations). Use this skill when creating new platform management pages or API endpoints.
subscription.admin (global, organization_id = NULL)platformApi from @/platform/lib/platformApi (not apiClient)usePlatformAdminPermissions() (not useHasPermission())Location: frontend/src/platform/pages/admin/YourManagementPage.tsx
import { Navigate } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import { usePlatformAdminPermissions } from '@/platform/hooks/usePlatformAdminPermissions';
import { platformApi } from '@/platform/lib/platformApi';
import { RefreshCw } from 'lucide-react';
export default function YourManagementPage() {
const { data: permissions, isLoading: permissionsLoading } = usePlatformAdminPermissions();
const hasAdminPermission = Array.isArray(permissions) && permissions.includes('subscription.admin');
const { data: items = [], isLoading: itemsLoading } = useQuery({
queryKey: ['platform-your-resource'],
enabled: !permissionsLoading && hasAdminPermission,
queryFn: async () => {
const response = await platformApi.yourResource.list();
return Array.isArray(response) ? response : (response?.data || []);
},
staleTime: 5 * 60 * 1000,
refetchOnWindowFocus: false,
});
if (permissionsLoading) {
return (
<div className="flex h-[50vh] items-center justify-center">
<RefreshCw className="h-8 w-8 animate-spin text-muted-foreground" />
</div>
);
}
if (!hasAdminPermission) {
return <Navigate to="/platform/dashboard" replace />;
}
return <div className="space-y-6 p-6">{/* content */}</div>;
}
In frontend/src/components/LazyComponents.tsx:
export const YourManagementPage = lazy(() =>
import('@/platform/pages/admin/YourManagementPage').then(module => ({ default: module.default }))
);
Place in "Subscription admin pages" section.
Where routes live: Platform routes are defined in root frontend/src/App.tsx under <Route path="/platform">, using components from LazyComponents (with Suspense). The file frontend/src/platform/App.tsx is an alternative router (PlatformAdminApp); follow the same pattern as existing platform pages.
In frontend/src/App.tsx (under the /platform route block):
// Ensure YourManagementPage is in LazyComponents (Step 2), then:
<Route path="your-resource" element={
<Suspense fallback={<PageSkeleton />}>
<YourManagementPage />
</Suspense>
} />
Use kebab-case for path. Place specific routes before wildcards.
In frontend/src/platform/lib/platformApi.ts:
yourResource: {
list: async (params?) => apiClient.get('/platform/your-resource', params),
get: async (id: string) => apiClient.get(`/platform/your-resource/${id}`),
create: async (data) => apiClient.post('/platform/your-resource', data),
update: async (id: string, data) => apiClient.put(`/platform/your-resource/${id}`, data),
delete: async (id: string) => apiClient.delete(`/platform/your-resource/${id}`),
},
All endpoints must use /platform/* prefix. Handle both array and { data: [] } responses.
In backend/routes/api.php:
Route::middleware(['auth:sanctum', 'platform.admin'])->prefix('platform')->group(function () {
Route::get('/your-resource', [YourResourceController::class, 'index']);
Route::get('/your-resource/{id}', [YourResourceController::class, 'show']);
Route::post('/your-resource', [YourResourceController::class, 'store']);
Route::put('/your-resource/{id}', [YourResourceController::class, 'update']);
Route::delete('/your-resource/{id}', [YourResourceController::class, 'destroy']);
});
Backend controller must use platform.admin middleware and check subscription.admin; do not filter by organization_id.
platform/pages/admin/usePlatformAdminPermissions(), not useHasPermission()enabled: !permissionsLoading && hasAdminPermission/platform/dashboard if no permission/platform/*platform.admin middlewareapiClient instead of platformApiuseHasPermission() (main-app hook)tools
Toast notifications for Nazim. Use when showing success/error/info messages. ALWAYS use showToast from @/lib/toast with translation keys; never toast from sonner directly. RTL positioning is automatic.
tools
Enforces status badge patterns for Nazim UI. Use when displaying status in tables, cards, or dialogs. Covers Badge variants, semantic colors, statusBadgeVariant, statusOptions with color.
development
Enforces mobile-first responsive patterns for Nazim UI. Use when building pages, tables, forms, charts, or buttons. Covers page container, FilterPanel, tabs, grids, tables, charts, cards, buttons.
development
PDF and Excel report generation for Nazim. Use when adding or changing reports. Backend uses ReportService and ReportConfig; frontend uses useServerReport. Covers branding, DateConversionService, RTL, acceptance criteria.