Skip to content
Agentmart
Submit a tool

apply-phoenix-controller-conventions

Use when writing new controller code in Phoenix applications.

Skill by igmarin

IndexedMIT★ 5
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/igmarin-apply-phoenix-controller-conventions

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Use when writing new controller code in Phoenix applications. Enforces consistent patterns for RESTful routing, plug pipeline ordering, action methods, strong parameters, content negotiation, fallback controllers, and error handling. Covers resource routing, controller plugs, conn.assigns, json/html rendering, and authentication plugs. Trigger words: phoenix controller conventions, controller patterns, phoenix router, plug pipeline, controller plugs, fallback controller, strong params, phoenix routes, action fallback.

Use cases: frontend, data, writing

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/apply-phoenix-controller-conventions

What's inside

Skill name
apply-phoenix-controller-conventions
Description
Use when writing new controller code in Phoenix applications. Enforces consistent patterns for RESTful routing, plug pipeline ordering, action methods, strong parameters, content negotiation, fallback controllers, and error handling. Covers resource routing, controller plugs, conn.assigns, json/html rendering, and authentication plugs. Trigger words: phoenix controller conventions, controller patterns, phoenix router, plug pipeline, controller plugs, fallback controller, strong params, phoenix routes, action fallback.
License
MIT
Metadata
version: 1.0.0 · user-invocable: true
Instructions
276 lines in SKILL.md · view on GitHub

Files (1)

  • SKILL.md

SKILL.md (first lines)

# Apply Phoenix Controller Conventions

Use this skill when writing new Phoenix controller modules or modifying existing controller code to ensure consistent, idiomatic patterns.

**Precondition:** Invoke `phoenix-liveview-essentials` before this skill if the feature uses LiveView; for traditional request/response, use this skill directly.


## Quick Reference

| Pattern | Convention |
|---------|------------|
| Routes | `resources` for RESTful; `scope` for grouping |
| Controllers | Thin — delegate business logic to contexts |
| Controller plugs | For auth, resource loading; halt or return `conn` |
| Strong params | Use `changeset` validation or `cast/4` in context |
| Content type | Pipeline `:browser` for HTML; `:api` for JSON |
| Error handling | Use `FallbackController` for structured errors |
| Auth plugs | Include pipeline plugs; skip with `:skip` option |


## RULES — Follow these with no exceptions

**1.** **Keep controllers thin** — never put business logic in controllers; delegate to context modules
**2.** **Use `plug` guards for authentication and resource loading** — chain with `when action not in [...]` opt-out pattern
**3.** **Always validate and authorize** every action that touches access-controlled resources
**4.** **Use `FallbackController` for JSON API error handling** — never inline catch-all `case` clauses in actions
**5.** **Match content pipeline to format** — API pipeline (no session, no CSRF) for JSON; browser pipeline for HTML
**6.** **Use `conn.assigns` for passing data between plugs and actions** — never use `Process` dictionaries
**7.** **Never interpolate user input into redirect paths** — use `~p"..."` paths for verified routes


## FCIS at this boundary

Controllers are edges: cast params, call context, render. No business math or multi-step domain orchestration in the action body.

❌ **Bad:** fat controller

```elixir
def create(conn, %{"post" => params}) do
  params = Map.put(params, "slug", slugify(params["title"]))
  {:ok, post} = Repo.insert(Post.changeset(%Post{}, params))
  redirect(conn, to: ~p"/posts/#{post}")
end
```

✅ **Good:** thin action

```elixir
def create(conn, %{"post" => params}) do
  case Blog.create_post(conn.assigns.current_scope, params) do
    {:ok, post} -> redirect(conn, to: ~p"/posts/#{post}")
    {:error, changeset} -> render(conn, :new, form: to_form(changeset))
  end
end
```

## Routing Conventions

✅ **RESTful resources with explicit shallow-style split** (Phoenix has no `shallow: true`):
```elixir
scope "/", MyAppWeb do
  pipe_through :browser

  # Collection under parent
  resources "/users", UserController do
    resources "/posts", PostController, only: [:index, :new, :create]
  end

  # Member routes at top level
  resources "/posts", PostController, only: [:show, :edit, :update, :delete]
end
```

**Checkpoint:** Run `mix phx.routes` to verify routes resolve correctly and there are no unintended deep-nesting paths.


## Plug Pipeline Ordering

✅ **`plug` guards with opt-out, auth at controller level:**
```elixir
defmodule MyAppWeb.UserController do
  use MyAppWeb, :controller

  plug :require_authenticated_user when action not in [:index, :show]
  plug :load_user when action in [:edit, :update]

  def index(conn, _params) do
    users = Accounts.list_users()
    render(conn, :index, users: users)
  end

  def edit(conn, _params) do
    render(conn, :edit, user: conn.assigns.user)
  end

  def update(conn, %{"user" => user_params}) do
    case Accounts.update_user(conn.assigns.user, user_params) do
      {:ok, user} -> redirect(conn, to: ~p"/users/#{user}")
      {:error, changeset} -> render(conn, :edit, user: conn.assigns.user, changeset: changeset)
    end
  end

  defp require_authenticated_user(conn, _opts) do
    if conn.assigns[:current_user] do
      conn
    else
      conn
      |> put_flash(:error, "You must be logged in")
      |> redirect(to: ~p"/login")
      |> halt()
    end
  end

  defp load_user(conn, _opts) do
    user = Accounts.get_user!(conn.params["id"])
    assign(conn, :user, user)
  end
end
```

From igmarin/elixir-phoenix-skills, MIT.

More from igmarin/elixir-phoenix-skills

Signals

Stars
5
Forks
0
Open issues
0
Last commit (this folder)
Sep 28, 2026 (1 month ago)

From GitHub (fetched Oct 24, 2026).

Details

Version
1.0.0
License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from igmarin

Cite this page

apply-phoenix-controller-conventions skill. Agent Mart. https://agentmart.dev/skills/igmarin-apply-phoenix-controller-conventions (last updated 2026-10-24)