# Frontend Vite Create Feature

> Create a new Vite admin CRUD feature module: pages, api layer, types, routes, sidebar entry. Use when adding categories, products, coupons, or any admin resource.

- Skill: `xmuhameed/frontend-vite-create-feature` (Agent Skill)
- Install (CLI): `npx skillmds@latest add xmuhameed/frontend-vite-create-feature`
- Raw SKILL.md: https://api.skillmd.com/api/skills/xmuhameed/frontend-vite-create-feature/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: xmuhameed (https://skillmd.com/u/xmuhameed)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/xmuhameed/frontend-vite-create-feature

---


# Create Admin Feature

## Checklist

```
[ ] 1. src/features/{name}/ with pages/, api/, types/
[ ] 2. api/keys.ts, api.ts, queries.ts, mutations.ts
[ ] 3. List page + Create/Edit page (or inline dialog for simple entities)
[ ] 4. Route in router (wrapped RequireRole)
[ ] 5. Sidebar entry in config/sidebar.ts with matching roles
[ ] 6. Bilingual form fields (_en/_ar) if catalog entity
```

## Folder Structure

```
features/product-tag/
├── pages/
│   ├── ProductTagListPage.tsx
│   └── CreateProductTagPage.tsx   # create + edit via useParams().id
├── components/                    # optional
├── api/
│   ├── keys.ts
│   ├── api.ts
│   ├── queries.ts
│   └── mutations.ts
└── types/index.ts
```

## CRUD Patterns

| Complexity | Pattern |
|------------|---------|
| Standard catalog | List page + shared Create/Edit page |
| Simple lookup table | Inline Dialog on list page (box-color, coupon) |
| Nested resource | `/parent/:id/child` + Breadcrumbs |
| Reusable form | Extract `FeatureForm.tsx`, parent owns mutation |

## Routes

```typescript
{ path: '/dashboard/product-tags', element: <RequireRole roles={['ADMIN','EDITOR']}><ListPage /></RequireRole> },
{ path: '/dashboard/product-tags/create', element: <CreatePage /> },
{ path: '/dashboard/product-tags/edit/:id', element: <CreatePage /> },
```

## Sidebar Entry

```typescript
{ title: 'Product Tags', href: '/dashboard/product-tags', roles: ['ADMIN', 'EDITOR'] }
```

## API Functions

```typescript
// api/api.ts
export const getProductTags = async (filters) => {
  const params = new URLSearchParams();
  params.append('page', String(filters.page ?? 1));
  params.append('pageItemsCount', String(filters.pageItemsCount ?? 10));
  if (filters.search) params.append('search', filters.search);
  return (await api.get(`/product-tag/get-all-product-tags?${params}`)).data;
};
```

Backend URLs: `get-all-X`, `create-X`, `update-X?id=`, `delete-X?id=`

## Mutations

```typescript
export const useCreateProductTag = () => {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: createProductTag,
    onSuccess: () => { qc.invalidateQueries({ queryKey: productTagKeys.all }); toast.success('Created'); },
    onError: (e) => toast.error(e?.response?.data?.message || 'Failed'),
  });
};
```

See also: `@frontend-vite/list-pages`, `@frontend-vite/forms`, `@frontend-vite/file-upload`

