> ## 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.

# Configuration

> The single published file config/commentify-pro.php: core overlay, commentables, API, spam, media, and more.

Pro publishes **one** file:

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

That creates `config/commentify-pro.php`. Values under `core` are copied onto `config('commentify')` at boot so the free package keeps reading the keys it already knows.

<Warning>
  Do not also keep a published `config/commentify.php` unless you installed core first and have not merged yet. If that file exists, the overlay is skipped and `core` has no effect until you delete it.
</Warning>

## `core`

Mirrors the free package's `config/commentify.php`.

```php theme={null}
'core' => [
    'users_route_prefix' => 'users',
    'user_model' => \Usamamuneerchaudhary\Commentify\Models\User::class, // set to App\Models\User::class
    'pagination_count' => 10,
    'css_framework' => 'tailwind', // tailwind | bootstrap
    'comment_nesting' => true,
    'read_only' => false,
    'default_sort' => 'newest', // newest | oldest | most_liked | most_replied
    'enable_sorting' => true,
    'enable_reporting' => true,
    'report_reasons' => ['spam', 'inappropriate', 'offensive', 'other'],
    'theme' => 'auto', // light | dark | auto
    'enable_emoji_picker' => true,
    'enable_markdown_toolbar' => true,
    'enable_markdown_preview' => true,
    'enable_notifications' => false,
    'notification_channels' => ['database'], // database, mail, broadcast
    'require_approval' => false,
    'allow_guests' => false,
    'guest' => [
        'require_email' => true,
        'show_gravatar' => true,
    ],
],
```

`GET /commentify/api/v1/ui` exposes the flags and translated labels to the SDKs, so toggling sorting or reporting here changes Livewire, React, and Vue together.

### Theme and CSS

* **Tailwind v4:** include `@custom-variant dark (&:where(.dark, .dark *));` in your CSS (Livewire Flux already does).
* **Bootstrap 5:** dark mode uses `data-bs-theme="dark"`.
* Publish views only if you must customize them. Published views override package views and will not pick up later markup changes automatically.

## `commentables`

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

See [Usage](/usage). Empty by default until the installer or you fill it.

## `api`

```php theme={null}
'api' => [
    'prefix' => 'commentify/api/v1',
    'middleware' => ['web'], // must match guard: web => ['web'], sanctum => ['api']
    'guard' => 'web',
    'rate_limit' => 60,          // legacy fallback
    'rate_limit_read' => 300,    // per minute, user id or IP
    'rate_limit_write' => 60,
    'guest_likes' => true,
    'guest_reports' => true,
    'guest_comments' => true,    // API posting when core.allow_guests is on
    'replies_per_parent' => 3,   // nested replies eager-loaded with each parent
],
```

`guest_comments => false` keeps guests on Livewire but locks the JSON API. Pair `guard` and `middleware` or every browser write is an unauthenticated 401. Full detail: [Authentication](/authentication) and [API](/api).

`per_page` on list endpoints is capped at **50**. Cursor pagination (`?cursor=`) is available for `newest` and `oldest` sorts.

## `spam`

```php theme={null}
'spam' => [
    'checkers' => ['heuristic'], // heuristic, akismet, toxicity, or FQCN
    'fail_mode' => 'allow',      // allow | review — when an external checker throws
    'log' => true,
    'heuristic' => [
        'max_links' => 2,        // more than this => review; more than double => deny
        'blocked_terms' => [],
        'blocked_domains' => [],
        'duplicate_window' => 300,
        'trusted_after' => 3,    // approved comments before links are trusted
    ],
    'akismet' => [
        'key' => env('AKISMET_KEY'),
        'blog' => env('APP_URL', ''),
    ],
],
```

Worst verdict wins: deny > review > allow. See [Spam pipeline](/spam).

## `guests`

```php theme={null}
'guests' => [
    'stricter_spam' => true, // extra heuristic rules for guest-authored comments
],
```

## `notifications`

```php theme={null}
'notifications' => [
    'subscriptions_enabled' => true,
    'moderators' => array_filter(array_map('trim', explode(',', (string) env('COMMENTIFY_MODERATORS', '')))),
    'digest' => [
        'interval' => env('COMMENTIFY_DIGEST_INTERVAL', 'daily'), // daily, hourly, off
    ],
],
```

See [Notifications](/notifications).

## `media`

```php theme={null}
'media' => [
    'enabled' => (bool) env('COMMENTIFY_MEDIA_ENABLED', false),
    'disk' => env('COMMENTIFY_MEDIA_DISK', 's3'),
    'bucket' => env('COMMENTIFY_MEDIA_BUCKET'),
    'path' => 'commentify',
    'visibility' => 'public',
    'max_kb' => 2048,
    'mimes' => ['image/gif', 'image/jpeg', 'image/png', 'image/webp'],
    'thumbnail_max' => 320,
    'guests' => 'allow', // allow, review, deny
    'limits' => [
        'guest' => ['max_kb' => 512, 'per_minute' => 2],
        'user' => ['max_kb' => 2048, 'per_minute' => 6],
        'moderator' => ['max_kb' => 5120, 'per_minute' => 20],
    ],
],
```

See [Image uploads](/media). If `bucket` is set, Pro registers a `commentify-media` disk cloned from `filesystems.disks.{disk}` with that bucket.

## `realtime`

```php theme={null}
'realtime' => [
    'enabled' => (bool) env('COMMENTIFY_REALTIME', false),
],
```

See [Realtime](/realtime).

## `webhooks`

```php theme={null}
'webhooks' => [
    'enabled' => (bool) env('COMMENTIFY_WEBHOOKS', false),
    'urls' => array_values(array_filter(array_map('trim', explode(',', (string) env('COMMENTIFY_WEBHOOK_URLS', ''))))),
    'events' => ['pending', 'report', 'spam_deny'],
    'timeout' => 5,
],
```

See [Webhooks](/webhooks).

## `badges`

```php theme={null}
'badges' => [
    'enabled' => true,
    'pins' => true,
    'author_key' => 'user_id',
    'moderator_ids' => [],
],
```

See [Badges and pins](/badges).

## `toxicity`

```php theme={null}
'toxicity' => [
    'key' => env('COMMENTIFY_PERSPECTIVE_KEY'),
    'hold_threshold' => 0.7,
    'deny_threshold' => 0.9,
    'attributes' => ['TOXICITY', 'SEVERE_TOXICITY', 'IDENTITY_ATTACK', 'INSULT', 'THREAT'],
],
```

Add `'toxicity'` to `spam.checkers` as well. See [AI toxicity](/toxicity).

## `gdpr`

```php theme={null}
'gdpr' => [
    'ip_retention_days' => (int) env('COMMENTIFY_IP_RETENTION_DAYS', 90),
],
```

See [GDPR](/gdpr).

## Environment variables

| Variable                       | Purpose                                 |
| ------------------------------ | --------------------------------------- |
| `AKISMET_KEY`                  | Akismet API key                         |
| `COMMENTIFY_PERSPECTIVE_KEY`   | Google Perspective / Comment Analyzer   |
| `COMMENTIFY_MODERATORS`        | Comma-separated emails for digests      |
| `COMMENTIFY_DIGEST_INTERVAL`   | `daily`, `hourly`, `off`                |
| `COMMENTIFY_MEDIA_ENABLED`     | Image uploads                           |
| `COMMENTIFY_MEDIA_DISK`        | Filesystem disk to clone (`s3` default) |
| `COMMENTIFY_MEDIA_BUCKET`      | Optional dedicated bucket               |
| `COMMENTIFY_REALTIME`          | Broadcast creates and likes             |
| `COMMENTIFY_WEBHOOKS`          | Enable moderator webhooks               |
| `COMMENTIFY_WEBHOOK_URLS`      | Comma-separated POST URLs               |
| `COMMENTIFY_IP_RETENTION_DAYS` | IP anonymize window (default 90)        |

<Tip>
  The free Filament **Commentify Settings** page can toggle many `core` flags without editing the file. Guest commenting (`allow_guests`) stays in config.
</Tip>
