Resource-agnostic, polymorphic commenting module for PhoenixKit. Drop-in comments with unlimited nested threading, like/dislike reactions, moderation, and an admin dashboard.
- Polymorphic comments — attach comments to any resource via
(resource_type, resource_uuid)with zero schema coupling - Unlimited nested threading — self-referencing
parent_uuidwith automatic depth tracking - Like/dislike reactions — one per user per comment, with denormalized counters and transaction-safe updates
- Moderation — optional approval workflow; comments start as
"pending"when moderation is enabled - Admin dashboard — search, filter by status/resource type, paginate, and perform bulk actions
- Auto-discovery — implements
PhoenixKit.Modulebehaviour; PhoenixKit finds it at startup with zero config - LiveView component — embeddable
CommentsComponentfor any page
Add phoenix_kit_comments to your dependencies in mix.exs:
def deps do
[
{:phoenix_kit_comments, "~> 0.1.0"}
]
endThen fetch dependencies:
mix deps.getNote: For development or if not yet published to Hex, you can use:
{:phoenix_kit_comments, github: "mdon/phoenix_kit_comments"}
PhoenixKit auto-discovers the module at startup — no additional configuration needed.
- Add the dependency to
mix.exs - Run
mix deps.get - Enable the module in admin settings (
comments_enabled: true) - Embed the
CommentsComponentin your LiveViews
Use the CommentsComponent LiveComponent in any LiveView:
<.live_component
module={PhoenixKitComments.Web.CommentsComponent}
id="comments"
resource_type="post"
resource_uuid={@post.uuid}
current_user={@current_user}
/>Modules that consume comments can register handlers to receive lifecycle notifications:
# config/config.exs
config :phoenix_kit, :comment_resource_handlers, %{
"post" => PhoenixKitPosts,
"entity" => PhoenixKitEntities
}Handler modules can implement:
on_comment_created/3— called after a comment is createdon_comment_deleted/3— called after a comment is deletedresolve_comment_resources/1— returns%{uuid => %{title: ..., path: ...}}for admin display
| Key | Type | Default | Description |
|---|---|---|---|
comments_enabled |
boolean | false |
Enable/disable the module |
comments_moderation |
boolean | false |
Require approval for new comments |
comments_max_depth |
integer | 10 |
Maximum thread nesting level |
comments_max_length |
integer | 10000 |
Maximum comment length (characters) |
When comments_moderation is enabled:
- New comments start with status
"pending" - Admins can approve (set to
"published") or reject (set to"hidden") - Approved comments become visible to all users
- Rejected comments remain hidden but are not deleted
The module declares permissions via permission_metadata/0:
:admin_comments— Access to moderation dashboard:admin_settings_comments— Access to settings page
Use Scope.has_module_access?/2 to check permissions in your application.
For Tailwind CSS users: ensure phoenix_kit_comments is listed in your tailwind.config.js sources:
module.exports = {
content: [
// ...
"./deps/phoenix_kit_comments/**/*.{heex,ex}",
// ...
]
}lib/
phoenix_kit_comments.ex # Context + PhoenixKit.Module behaviour
phoenix_kit_comments/
schemas/
comment.ex # Polymorphic comment schema with threading
comment_like.ex # Like tracking (unique per user per comment)
comment_dislike.ex # Dislike tracking (unique per user per comment)
web/
comments_component.ex # Embeddable LiveComponent
index.ex # Admin moderation dashboard
settings.ex # Admin settings page
| Status | Description |
|---|---|
"published" |
Visible to all (default when moderation is off) |
"pending" |
Awaiting moderator approval |
"hidden" |
Hidden by a moderator |
"deleted" |
Soft-deleted |
phoenix_kit_comments— comment records (UUIDv7 primary keys)phoenix_kit_comments_likes— like records with unique(comment_uuid, user_uuid)constraintphoenix_kit_comments_dislikes— dislike records with unique(comment_uuid, user_uuid)constraint
mix deps.get # Install dependencies
mix test # Run tests
mix format # Format code
mix credo # Static analysis
mix dialyzer # Type checking
mix docs # Generate documentation- Verify
comments_enabledistruein settings - Check that the resource type matches exactly (case-sensitive)
- Ensure the current user is authenticated and passed to the component
- Add
phoenix_kit_commentsto your Tailwind content sources - Run
mix assets.deployto rebuild CSS
- Verify the user has the
:admin_commentspermission - Check that
Scope.has_module_access?/2returnstrue
MIT — see LICENSE for details.