Skill

absinthe-subscriptions

Use when implementing real-time GraphQL subscriptions with Absinthe. Covers Phoenix channels, PubSub, and subscription patterns.

From absinthe-graphql
Install
1
Run in your terminal
$
npx claudepluginhub thebushidocollective/han --plugin absinthe-graphql
Tool Access

This skill uses the workspace's default tool permissions.

Skill Content

Absinthe - Subscriptions

Guide to implementing real-time GraphQL subscriptions with Absinthe and Phoenix.

Key Concepts

Basic Setup

# In your Phoenix endpoint
defmodule MyAppWeb.Endpoint do
  use Phoenix.Endpoint, otp_app: :my_app
  use Absinthe.Phoenix.Endpoint

  socket "/socket", MyAppWeb.UserSocket,
    websocket: true,
    longpoll: false
end

# Socket configuration
defmodule MyAppWeb.UserSocket do
  use Phoenix.Socket
  use Absinthe.Phoenix.Socket, schema: MyApp.Schema

  def connect(params, socket, _connect_info) do
    current_user = get_user_from_token(params["token"])
    socket = Absinthe.Phoenix.Socket.put_options(socket,
      context: %{current_user: current_user}
    )
    {:ok, socket}
  end

  def id(socket), do: "user_socket:#{socket.assigns.user_id}"
end

Defining Subscriptions

defmodule MyApp.Schema.Subscriptions do
  use Absinthe.Schema.Notation

  object :post_subscriptions do
    field :post_created, :post do
      config fn _args, _resolution ->
        {:ok, topic: "posts"}
      end

      trigger :create_post, topic: fn _post ->
        "posts"
      end
    end

    field :post_updated, :post do
      arg :id, non_null(:id)

      config fn %{id: id}, _resolution ->
        {:ok, topic: "post:#{id}"}
      end

      trigger :update_post, topic: fn post ->
        "post:#{post.id}"
      end
    end
  end
end

Publishing from Mutations

defmodule MyApp.Resolvers.Post do
  def create_post(_parent, %{input: input}, _resolution) do
    case MyApp.Posts.create_post(input) do
      {:ok, post} ->
        # Publish to subscription
        Absinthe.Subscription.publish(
          MyAppWeb.Endpoint,
          post,
          post_created: "posts"
        )
        {:ok, post}
      {:error, changeset} ->
        {:error, changeset}
    end
  end
end

User-Specific Subscriptions

field :user_notification, :notification do
  config fn _args, %{context: %{current_user: user}} ->
    {:ok, topic: "user:#{user.id}:notifications"}
  end
end

# Publishing
Absinthe.Subscription.publish(
  MyAppWeb.Endpoint,
  notification,
  user_notification: "user:#{user_id}:notifications"
)

Best Practices

  1. Scope subscriptions - Use topics to limit data exposure
  2. Authenticate connections - Verify users in socket connect
  3. Use triggers - Automatically publish on mutations
  4. Handle disconnections - Clean up resources on disconnect
  5. Rate limit subscriptions - Prevent abuse

PubSub Configuration

# config/config.exs
config :my_app, MyAppWeb.Endpoint,
  pubsub_server: MyApp.PubSub

# application.ex
children = [
  {Phoenix.PubSub, name: MyApp.PubSub},
  MyAppWeb.Endpoint,
  {Absinthe.Subscription, MyAppWeb.Endpoint}
]

Authorization in Subscriptions

field :private_messages, :message do
  config fn _args, %{context: context} ->
    case context do
      %{current_user: %{id: user_id}} ->
        {:ok, topic: "user:#{user_id}:messages"}
      _ ->
        {:error, "Unauthorized"}
    end
  end
end

Anti-Patterns

  • Don't publish sensitive data to broad topics
  • Avoid subscriptions without authentication
  • Don't skip connection-level authorization
  • Avoid overly granular topics (performance impact)
Similar Skills
cache-components

Expert guidance for Next.js Cache Components and Partial Prerendering (PPR). **PROACTIVE ACTIVATION**: Use this skill automatically when working in Next.js projects that have `cacheComponents: true` in their next.config.ts/next.config.js. When this config is detected, proactively apply Cache Components patterns and best practices to all React Server Component implementations. **DETECTION**: At the start of a session in a Next.js project, check for `cacheComponents: true` in next.config. If enabled, this skill's patterns should guide all component authoring, data fetching, and caching decisions. **USE CASES**: Implementing 'use cache' directive, configuring cache lifetimes with cacheLife(), tagging cached data with cacheTag(), invalidating caches with updateTag()/revalidateTag(), optimizing static vs dynamic content boundaries, debugging cache issues, and reviewing Cache Component implementations.

138.5k
Stats
Parent Repo Stars106
Parent Repo Forks13
Last CommitFeb 11, 2026