# Backend Create Module

> Step-by-step workflow to create a new NestJS backend feature module: Prisma model, DTOs, controller, service, file uploads, auth guards, pagination, soft delete, app.module registration. Use when adding products, categories, coupons, or any new backend resource/module.

- Skill: `xmuhameed/backend-create-module` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add xmuhameed/backend-create-module`
- Raw SKILL.md: https://api.skillmd.com/api/skills/xmuhameed/backend-create-module/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: xmuhameed (https://skillmd.com/u/xmuhameed)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/xmuhameed/backend-create-module

---


# Create Backend Module

**Reference:** `category` module — full CRUD + files + soft delete + audit logs.

## Checklist

```
[ ] 1. Prisma model + migrate
[ ] 2. src/modules/{feature}/ — module, controller, service, dto/
[ ] 3. Register in app.module.ts
[ ] 4. DTOs with global decorators
[ ] 5. Controller endpoints + guards
[ ] 6. Service methods with try/catch
[ ] 7. File upload (if needed) — see @backend-nest/file-upload
[ ] 8. Auth per endpoint — see @backend-nest/auth
```

## Step 1 — Prisma

```prisma
model product_tag {
  id        String    @id @default(uuid())
  name_en   String
  name_ar   String
  slug      String    @unique
  imageUrl  String?
  sort      Int       @default(0)
  deleted   DateTime?
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
  @@index([deleted])
}
```

`npx prisma migrate dev --name add-product-tag`

## Step 2 — Files

```
src/modules/product-tag/
├── product-tag.module.ts
├── product-tag.controller.ts
├── product-tag.service.ts
└── dto/
    ├── index.ts
    ├── create-product-tag.dto.ts
    ├── update-product-tag.dto.ts
    └── get-all-product-tags.dto.ts
```

## Step 3 — Standard Endpoints

| Route | Guard | Notes |
|-------|-------|-------|
| GET `get-all-{features}` | Public | pagination + search + filters |
| GET `get-{feature}` | OptionalJwtGuard | `?id=` or `?slug=` |
| POST `create-{feature}` | Admin+Editor | multipart if files |
| PATCH `update-{feature}` | Admin+Editor | `?id=` |
| DELETE `delete-{feature}` | Admin+Editor | soft → hard on second call |
| PATCH `update-{feature}-sort` | Admin+Editor | if sortable |

## Step 4 — Controller

```typescript
@Get('get-all-product-tags')
async getAll(@Query() pagination: GlobalPaginationDto, @Query() search: GlobalSearchDto, @Query() dto: GetAllDto) {
  const data = await this.service.getAll(pagination, search, dto);
  return sendCustomResponse({ data: data.requests, count: data.count });
}

@UseGuards(JwtGuard, AuthorizeCoreUsersGuard)
@ApiBearerAuth()
@CoreUserType([CoreUserEnum.ADMIN, CoreUserEnum.EDITOR])
@Post('create-product-tag')
@HttpCode(200)
async create(@Body() dto: CreateDto, @GetUser() user: user) {
  return sendSuccessfulResponse(await this.service.create(dto, user));
}
```

## Step 5 — Service getAll

```typescript
async getAll(pagination, search, dto) {
  try {
    const where: Prisma.product_tagWhereInput = {};
    if (search?.search) {
      where.OR = [
        { name_en: { contains: search.search, mode: 'insensitive' } },
        { name_ar: { contains: search.search, mode: 'insensitive' } },
      ];
    }
    const [count, requests] = await Promise.all([
      this.prisma.product_tag.count({ where }),
      this.prisma.product_tag.findMany({ where, ...checkPagination(pagination), orderBy: { sort: 'asc' } }),
    ]);
    return { count, requests };
  } catch (error) { handleException(error, false, {}); }
}
```

## Step 6 — Delete (soft then hard)

```typescript
if (existing.deleted) {
  await this.prisma.junction.deleteMany({ where: { tagId: id } });
  return this.prisma.product_tag.delete({ where: { id } });
}
return this.prisma.product_tag.update({ where: { id }, data: { deleted: new Date() } });
```

## Step 7 — Module

```typescript
@Module({
  imports: [LogModule, StorageModule], // if needed
  controllers: [ProductTagController],
  providers: [ProductTagService, PerformanceTrackerService],
})
export class ProductTagModule {}
```

## Complexity Guide

| Type | Extra |
|------|-------|
| Simple CRUD | 5 endpoints |
| + files | Two-phase upload, `@backend-nest/file-upload` |
| + relations | Junction tables, complex includes |
| + sort | `update-X-sort` endpoint |
| + audit | `LogService.createLogSafely()` |

Templates: [templates.md](templates.md)

