> ## Documentation Index
> Fetch the complete documentation index at: https://docs.commentify.pro/llms.txt
> Use this file to discover all available pages before exploring further.

# Make a model commentable

> Add the Commentable trait, drop the Livewire thread, and map aliases for the Pro API.

## 1. Trait on the model

```php theme={null}
use Usamamuneerchaudhary\Commentify\Traits\Commentable;

class Article extends Model
{
    use Commentable;
}
```

That is the whole backend integration for Livewire. Comments are a polymorphic `comments()` relation on any Eloquent model.

## 2. Show the thread (Livewire)

```blade theme={null}
<livewire:comments :model="$article" />
```

Pro's spam pipeline, approval, webhooks, and broadcasts apply automatically because they run on the `Comment` model, not in the Livewire class.

For React and Vue, pass the **alias** and id, not the class name. See [React](/react) and [Vue](/vue).

## 3. Register an alias (Pro API / SDKs)

The API never accepts raw class names from the URL. Map a URL-safe alias in `config/commentify-pro.php`:

```php theme={null}
'commentables' => [
    'articles' => \App\Models\Article::class,
],
```

The installer derives aliases as the plural kebab of the class basename (`Article` → `articles`, `BlogPost` → `blog-posts`). Laravel `Relation::morphMap()` entries are honoured as a fallback if the alias is missing from this array.

Then the React/Vue thread is:

```tsx theme={null}
<CommentThread type="articles" id={article.id} />
```

## 4. Avatars

Add `HasUserAvatar` on your user model and point `core.user_model` at it:

```php theme={null}
use Usamamuneerchaudhary\Commentify\Traits\HasUserAvatar;

class User extends Authenticatable
{
    use HasUserAvatar;
}
```

```php theme={null}
'core' => [
    'user_model' => \App\Models\User::class,
],
```

The API's `UserResource` calls `avatar()` or `avatarUrl()` on that model so Blade and the SDKs show the same picture.

## 5. Permalinks for mail and notifications

Implement `commentifyUrl()` on the commentable, or register a global resolver:

```php theme={null}
public function commentifyUrl(): string
{
    return route('articles.show', $this);
}
```

```php theme={null}
use Usamamuneerchaudhary\Commentify\Commentify;
use Usamamuneerchaudhary\Commentify\Models\Comment;

Commentify::resolveCommentUrlUsing(function (Comment $comment) {
    return route('articles.show', $comment->commentable);
});
```

Mail CTAs append `#comment-{id}`. If neither is set, Commentify falls back to the previous URL, then `/`.

## Relabel the UI

Threads are "comments" until you say otherwise. Every string goes through `commentify::commentify.comments.*`. Publish lang files and rename the surface to "Reviews", "Cook's notes", or "Ask the hiring team" without forking views:

```bash theme={null}
php artisan vendor:publish --tag=commentify-lang
```

`GET ui` returns those translations to React and Vue, so one language file drives all three stacks.

## What you get from core on day one

These are MIT features. Turn them on under `core` (see [Configuration](/configuration)):

* Nested replies (`comment_nesting`)
* Sort: newest, oldest, most liked, most replied
* Reports with configurable reasons
* Markdown toolbar + Write/Preview
* Emoji picker
* Light / dark / auto theme
* Tailwind or Bootstrap 5 views
* `require_approval` — pending stays off the public thread
* Guest name + email posting (`allow_guests`) — [Guests](/guests)
* Read-only mode (`read_only` → API writes return `423` / `read_only`)
* Comment bans via `HasCommentBan` — [Authorization](/authorization)
