Agent skill

Phoenix LiveView Patterns

by georgeguimaraes in georgeguimaraes/elixir-agent-tools

Guidance for building and debugging Phoenix web interfaces: where LiveView loads data, scopes, PubSub topics, external polling and component state.

Apache-2.0Auto-check passedBackend & APIs

Install Phoenix LiveView Patterns

skills CLI
$ npx skills add georgeguimaraes/elixir-agent-tools --skill phoenix -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install georgeguimaraes/elixir-agent-tools phoenix --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/georgeguimaraes/elixir-agent-tools.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/elixir-dev/skills/phoenix .claude/skills/phoenix && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
phoenix
GitHub stars
184
Token cost
~1.3k tokens
SKILL.md length
524 words
Files
1
Skills in repo
5
Repo updated
First seen
Licence
Apache-2.0

At a glance

Guidance for building and debugging Phoenix web interfaces: where LiveView loads data, scopes, PubSub topics, external polling and component state.

  • Deciding whether LiveView data belongs in mount or handle_params
  • SKILL.md covers Where to Load Data: mount vs…, Scopes: Security-First Pattern…, PubSub Topics Must Be Scoped and External Polling: GenServer,…, plus 4 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md
  • Scoping PubSub topics and queries so tenants cannot see each other's data

What it does

The default is to load data in mount/3. The skill explains that mount and handle_params both run twice on first load, once as an HTTP dead render and once on the WebSocket connect, which is the LiveView lifecycle rather than a bug. handle_params/3 is for data that changes on live navigation through push_patch or patch links. When the double load really matters, it points to connected?(socket), assign_async/3 and assign_new/3 and notes what each one does not deduplicate.

Other patterns cover scopes, the Phoenix 1.8+ approach that threads authorization context through queries to prevent broken access control, PubSub topics that must be scoped by something like the organization or tenants see each other's data, external polling done by a single GenServer that broadcasts instead of every connected user calling the API, and the split between display-only functional components and LiveComponents that own state. The description also lists forms, routes, controllers, Plug and channels, and sends changesets and queries to the ecto skill.

When your agent uses it

  • Deciding whether LiveView data belongs in mount or handle_params
  • Scoping PubSub topics and queries so tenants cannot see each other's data
  • Debugging a LiveView that appears to load data twice
  • Moving external API polling out of individual LiveViews

Example prompts

  • “My LiveView runs the posts query twice on page load. Is that a bug?”
  • “Scope this PubSub subscription to the current organization.”
  • “Refactor our dashboard so one process polls the weather API and broadcasts to every LiveView.”

Requirements

  • An Elixir project that uses Phoenix

What it can do on your machine

Read from SKILL.md and the folder at commit ac3a5a1. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are elixir).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Phoenix LiveView Patterns loads about 1.3k tokens when it runs. Until then it costs about 64 tokens; SKILL.md has 524 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~64
When it runs · the whole SKILL.md, loaded when a task matches
~1.3k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from georgeguimaraes/elixir-agent-tools at commit ac3a5a1, republished under its Apache-2.0 licence (© georgeguimaraes). 524 words, ~1,307 tokens.

Download SKILL.mdSave it as .claude/skills/phoenix/SKILL.md (or your agent's skills folder).
name
phoenix
description
Build and debug Phoenix web interfaces and HTTP endpoints. Use for LiveView lifecycle and data loading, components, forms, routes, controllers, Plug, channels, and PubSub. Use ecto for changesets, queries, and persistence behind those interfaces.

Phoenix

Structure Phoenix interfaces, load LiveView data, and scope real-time updates.

Where to Load Data: mount vs handle_params

Default: load data in mount/3.

elixir
def mount(_params, _session, socket) do
  posts = Blog.list_posts(socket.assigns.current_scope)
  {:ok, assign(socket, posts: posts)}
end

Yes, mount runs twice on initial load (HTTP dead render + WebSocket connect). So does handle_params/3. That's the LiveView lifecycle, not a bug to route around. Moving queries from mount to handle_params does not dedupe them.

Use handle_params/3 for data that changes on live navigation (push_patch / <.link patch={...}>). mount does not re-run on patches, handle_params does.

elixir
def handle_params(%{"filter" => filter}, _uri, socket) do
  posts = Blog.list_posts(socket.assigns.current_scope, filter)
  {:noreply, assign(socket, posts: posts, filter: filter)}
end

When the initial double-load actually matters, the real tools are:

  • connected?(socket) to gate work to the connected render (loses SEO / no-JS rendering)
  • assign_async/3 to load after mount returns, in a separate process
  • assign_new/3 to reuse values already set on conn.assigns by upstream Plugs (e.g. :current_user), or shared from a parent LiveView. It does not dedupe arbitrary work across the dead/connected boundary: the function still runs on connected mount.
elixir
def mount(_params, _session, socket) do
  posts = if connected?(socket), do: Blog.list_posts(socket.assigns.current_scope), else: []
  {:ok, assign(socket, posts: posts)}
end

Scopes: Security-First Pattern (Phoenix 1.8+)

Scopes address OWASP #1 vulnerability: Broken Access Control. Authorization context is threaded automatically—no more forgetting to scope queries.

elixir
def list_posts(%Scope{user: user}) do
  Post |> where(user_id: ^user.id) |> Repo.all()
end

PubSub Topics Must Be Scoped

elixir
def subscribe(%Scope{organization: org}) do
  Phoenix.PubSub.subscribe(@pubsub, "posts:org:#{org.id}")
end

Unscoped topics = data leaks between tenants.

External Polling: GenServer, Not LiveView

Bad: Every connected user makes API calls (multiplied by users). Good: Single GenServer polls, broadcasts to all via PubSub.

Components Receive Data, LiveViews Own Data

  • Functional components: Display-only, no internal state
  • LiveComponents: Own state, handle own events
  • LiveViews: Full page, owns URL, top-level state

Async Data Loading

Use assign_async/3 for data that can load after mount:

elixir
def mount(_params, _session, socket) do
  {:ok, assign_async(socket, :user, fn -> {:ok, %{user: fetch_user()}} end)}
end

Gotchas from Core Team

LiveView terminate/2 Requires trap_exit

terminate/2 only fires if you're trapping exits—which you shouldn't do in LiveView.

Fix: Use a separate GenServer that monitors the LiveView process via Process.monitor/1, then handle :DOWN messages to run cleanup.

start_async Duplicate Names: Later Wins

Calling start_async with the same name while a task is in-flight: the later one wins, the previous task's result is ignored.

Fix: Call cancel_async/3 first if you want to abort the previous task.

Show full SKILL.md (206 more words)Show less
Channel Intercept Socket State is Stale

The socket in handle_out intercept is a snapshot from subscription time, not current state.

Why: Socket is copied into fastlane lookup at subscription time for performance.

Fix: Use separate topics per role, or fetch current state explicitly.

CSS Class Precedence is Stylesheet Order

When merging classes on components, precedence is determined by stylesheet order, not HTML order. If btn-primary appears later in the compiled CSS than bg-red-500, it wins regardless of HTML order.

Fix: Use variant props instead of class merging.

Upload Content-Type Can't Be Trusted

The :content_type in %Plug.Upload{} is user-provided. Always validate actual file contents (magic bytes) and rewrite filename/extension.

Read Body Before Plug.Parsers for Webhooks

To verify webhook signatures, you need the raw body. But Plug.Parsers consumes it.

elixir
{:ok, body, conn} = Plug.Conn.read_body(conn)
verify_signature!(conn, body)
%{conn | body_params: JSON.decode!(body)}

Don't use preserve_req_body: true—it keeps the entire body in memory for ALL requests.

Red Flags - STOP and Reconsider

  • Loading patch-mutable data in mount/3 instead of handle_params/3
  • Unscoped PubSub topics in multi-tenant app
  • LiveView polling external APIs directly
  • Using terminate/2 for cleanup (won't fire without trap_exit)
  • Calling start_async with same name without cancel_async first
  • Relying on socket.assigns in Channel intercepts (stale!)
  • CSS class merging for component customization (use variants)
  • Trusting %Plug.Upload{}.content_type for security

Any of these? Re-read the Gotchas section.

© georgeguimaraes, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in plugins/elixir-dev/skills/phoenix of georgeguimaraes/elixir-agent-tools.

Open the folder on GitHubat commit ac3a5a1

Compare with similar skills

Phoenix LiveView Patterns next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Phoenix LiveView Patterns compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Phoenix LiveView Patterns this skillgeorgeguimaraes/elixir-agent-tools184—~1.3kAutomated safety check: PassApache-2.0
Django Access Reviewgetsentry/skills1k3 repos~2.6kAutomated safety check: NotesApache-2.0
Frontmcp Auth UIagentfront/frontmcp146—~3.7kAutomated safety check: PassApache-2.0
Configuring Horizoncoollabsio/coolify63k4 repos~898Automated safety check: PassMIT
Abp Authorizationabpframework/abp14k—~1.3kAutomated safety check: PassLGPL-3.0
Tyrohasinhayder/tyro685—~1.4kAutomated safety check: PassMIT

Similar skills

  • Django Access Review

    getsentry/skills

    Official

    Django access control and IDOR security review. An agent skill from getsentry/skills.

    1k GitHub starsUsed in 3 repos~2.6k tokens
    Backend & APIsAuto-check: notes
  • Frontmcp Auth UI

    agentfront/frontmcp

    A skill your agent uses when customizing, branding, or replacing the built-in FrontMCP OAuth pages (the login, consent, federated-select, incremental-authorization, and error pages) with your own…

    146 GitHub stars~3.7k tokensUpdated today
    Backend & APIsAuto-check passed
  • Configuring Horizon

    coollabsio/coolify

    A skill your agent uses whenever the user mentions Horizon by name in a Laravel context.

    63k GitHub starsUsed in 4 repos~898 tokens
    Backend & APIsAuto-check passed
  • Abp Authorization

    abpframework/abp

    ABP permission system - PermissionDefinitionProvider, [Authorize] attribute, CheckPolicyAsync, IsGrantedAsync, ICurrentUser, IPermissionManager, multi-tenancy side.

    14k GitHub stars~1.3k tokensUpdated today
    Backend & APIsAuto-check passed
  • Tyro

    hasinhayder/tyro

    Framework-maintainer skill for the Tyro Laravel authorization package

    685 GitHub stars~1.4k tokensUpdated 1 mo ago
    Backend & APIsAuto-check passed
  • Pulse Development

    MineTrax/minetrax

    Handles Laravel Pulse setup, configuration, and custom card development.

    116 GitHub starsUsed in 1 repo~1.7k tokens
    Backend & APIsAuto-check passed

More from georgeguimaraes/elixir-agent-tools

  • Ecto Persistence Patterns

    georgeguimaraes/elixir-agent-tools

    Designs and debugs Elixir persistence with Ecto: schemas, changesets, queries, preloads, migrations and multi-tenancy, kept within application contexts.

    184 GitHub stars~1.2k tokensUpdated 20 days ago
    Auto-check passed
  • Idiomatic Elixir

    georgeguimaraes/elixir-agent-tools

    Writes and refactors idiomatic Elixir modules and functions, with rules for pattern matching, error handling, protocols and when a process is really needed.

    184 GitHub stars~2.1k tokensUpdated 20 days ago
    Auto-check passed
  • Oban Background Jobs

    georgeguimaraes/elixir-agent-tools

    Guidance for building and debugging durable background jobs in Elixir with Oban and Oban Pro, covering serialization, retries, uniqueness, chaining, chunking and workflows.

    184 GitHub stars~2.2k tokensUpdated 20 days ago
    Auto-check passed
  • Elixir OTP Concurrency

    georgeguimaraes/elixir-agent-tools

    Guides choices among GenServer, Supervisor, Task, Registry, ETS and Broadway when designing or debugging Elixir concurrency, state and fault recovery.

    184 GitHub stars~1.2k tokensUpdated 20 days ago
    Auto-check passed

Works with

Questions about Phoenix LiveView Patterns

What does Phoenix LiveView Patterns do?

Guidance for building and debugging Phoenix web interfaces: where LiveView loads data, scopes, PubSub topics, external polling and component state. The default is to load data in mount/3. The skill explains that mount and handle_params both run twice on first load, once as an HTTP dead render and once on the WebSocket connect, which is the LiveView lifecycle rather than a bug.

When should I use Phoenix LiveView Patterns?

Phoenix LiveView Patterns fits situations like: deciding whether LiveView data belongs in mount or handle_params; scoping PubSub topics and queries so tenants cannot see each other's data; debugging a LiveView that appears to load data twice; moving external API polling out of individual LiveViews.

How do I install Phoenix LiveView Patterns in Claude Code?

Run `npx skills add georgeguimaraes/elixir-agent-tools --skill phoenix -a claude-code`. Or copy the skill folder (plugins/elixir-dev/skills/phoenix in georgeguimaraes/elixir-agent-tools) into .claude/skills/phoenix in your project. Claude Code loads it when a task matches its description.

How do I install Phoenix LiveView Patterns in Codex?

Run `npx skills add georgeguimaraes/elixir-agent-tools --skill phoenix -a codex`. Or copy the skill folder (plugins/elixir-dev/skills/phoenix in georgeguimaraes/elixir-agent-tools) into .agents/skills/phoenix in your project. Codex loads it when a task matches its description.

Can I use Phoenix LiveView Patterns in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add georgeguimaraes/elixir-agent-tools --skill phoenix -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/phoenix, .gemini/skills/phoenix, .github/skills/phoenix and .opencode/skills/phoenix in your project.

What does Phoenix LiveView Patterns need to run?

SKILL.md names no scripts, command-line tools or credentials: Phoenix LiveView Patterns is instructions for the agent only. Our summary lists: An Elixir project that uses Phoenix.

Does Phoenix LiveView Patterns access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Phoenix LiveView Patterns safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Phoenix LiveView Patterns use?

Phoenix LiveView Patterns is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Phoenix LiveView Patterns use?

About 1.3k tokens (SKILL.md is roughly 5.2k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Phoenix LiveView Patterns?

Skills that share tags, products or a category with Phoenix LiveView Patterns: Django Access Review (getsentry/skills, 1k stars), Frontmcp Auth UI (agentfront/frontmcp, 146 stars), Configuring Horizon (coollabsio/coolify, 63k stars) and Abp Authorization (abpframework/abp, 14k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Phoenix LiveView Patterns?

georgeguimaraes (a GitHub user) maintains it in georgeguimaraes/elixir-agent-tools, which has 184 GitHub stars. The repository holds 5 skills in this directory. The repository was last updated on September 20, 2026.

Source: georgeguimaraes/elixir-agent-tools on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.