Skip to content
Back to skills

Add Domain Entity

ASecurity

Create domain layer components: models, repository interfaces, marshallers, and implementations. Use when: (1) adding domain model in internal/domain/model/, (2) creating repository interface in internal/domain/repository/, (3) implementing repository with marshaller in internal/infrastructure/{db}/. This is Step 2 of CRUD workflow (after add-database-table, before add-api-endpoint).

  • 666 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 2, 2026
ai-agentsgobashsqlapidatabase

Works with

  • api

Security analysis

A100/100

Scanned September 2, 2026

npx -y skills add majiayu000/claude-skill-registry --skill add-domain-entity --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Add Domain Entity?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Add Domain Entity
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/majiayu000-add-domain-entity-claude-skill-registry/badge)](https://www.skillsdirectory.com/skills/majiayu000-add-domain-entity-claude-skill-registry)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: add-domain-entity
description: |
  Create domain layer components: models, repository interfaces, marshallers, and implementations.
  Use when: (1) adding domain model in internal/domain/model/, (2) creating repository interface in internal/domain/repository/, (3) implementing repository with marshaller in internal/infrastructure/{db}/.
  This is Step 2 of CRUD workflow (after add-database-table, before add-api-endpoint).
---

# Add Domain Entity

Create domain layer components for a new entity following DDD patterns.

## Prerequisites

- Database table created (use **add-database-table** skill first)
- SQLBoiler model generated via `make migrate.up`

## Quick Workflow

```
1. Domain Model     → internal/domain/model/{entity}.go
2. Domain Error     → internal/domain/errors/errors.go
3. Repository Interface → internal/domain/repository/{entity}.go
4. Marshaller       → internal/infrastructure/{db}/internal/marshaller/{entity}.go
5. Repository Impl  → internal/infrastructure/{db}/repository/{entity}.go
6. Generate Mocks   → make generate.mock
```

## Step 1: Create Domain Model

Location: `internal/domain/model/{entity}.go`

Create the entity struct, constructor, update methods, and type aliases.

Key requirements:
- Use `id.New()` for ID generation in constructor
- Set both `CreatedAt` and `UpdatedAt` to the same time parameter
- Define `ReadonlyReference` for relations (always nil in constructor)
- Create slice type alias: `type Examples []*Example`

See: [references/domain-model-patterns.md](references/domain-model-patterns.md)

## Step 2: Add Domain Error

Location: `internal/domain/errors/errors.go`

Add a not-found error for the entity:

```go
ExampleNotFoundErr = NewNotFoundError("E2xxxxx", "Example not found")
```

Follow error code conventions from `.claude/rules/domain-errors.md`.

## Step 3: Create Repository Interface

Location: `internal/domain/repository/{entity}.go`

Define the repository interface with standard CRUD operations and query structs.

Key requirements:
- Add `//go:generate` directive for mock generation
- Use `nullable.Type[T]` for optional enum/custom type filter fields
- Embed `BaseGetOptions` / `BaseListOptions` in query structs

See: [references/repository-patterns.md](references/repository-patterns.md)

## Step 4: Create Marshaller

Location: `internal/infrastructure/{mysql|postgresql|spanner}/internal/marshaller/{entity}.go`

Convert between DB models and domain models.

Key requirements:
- Related entity's `ReadonlyReference` must remain nil (no recursive loading)
- Use var declaration pattern for nullable timestamp fields
- Include both `ToModel` and `ToDBModel` functions

See: [references/marshaller-patterns.md](references/marshaller-patterns.md)

## Step 5: Create Repository Implementation

Location: `internal/infrastructure/{mysql|postgresql|spanner}/repository/{entity}.go`

Implement the repository interface using SQLBoiler.

Key requirements:
- Use `transactable.GetContextExecutor(ctx)` for all DB operations
- Implement `buildListQuery` helper for reusable filter logic
- Implement `buildPreload` helper for relation loading
- Use base helper functions: `addForUpdateFromBaseGetOptions`, `addForUpdateFromBaseListOptions`

See: [references/repository-patterns.md](references/repository-patterns.md)

## Step 6: Generate Mocks

```bash
make generate.mock
```

This generates mock implementations in `internal/domain/repository/mock/`.

## Checklist

### Domain Model
- [ ] Entity struct with all fields
- [ ] `ReadonlyReference` for relations (if any)
- [ ] Constructor with `id.New()` and `ReadonlyReference: nil`
- [ ] Update method using `null.*` types for optional fields
- [ ] Slice type alias (`Examples []*Example`)
- [ ] Helper methods on slice (`IDs()`, `MapByID()`)

### Status/Enum Types (if needed)
- [ ] Type definition with `Unknown` as first constant
- [ ] `String()` and `Valid()` methods
- [ ] `New{Type}(str string)` constructor

### Repository
- [ ] Interface with `//go:generate` directive
- [ ] Query structs with `nullable.Type[T]` for optional enums
- [ ] Domain error added for not-found case

### Implementation
- [ ] Marshaller with `ToModel`, `ToDBModel`, `ToModels`, `ToDBModels`
- [ ] Marshaller handles `ReadonlyReference` correctly
- [ ] Repository implementation with all CRUD methods
- [ ] `buildListQuery` and `buildPreload` helpers
- [ ] Mocks generated

## Next Steps

After creating domain entity, use **add-api-endpoint** skill to create:
- Usecase input/output structs
- Interactor interface and implementation
- Protocol Buffers definition
- gRPC handler

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.