apply-phoenix-controller-conventions
Use when writing new controller code in Phoenix applications.
Skill by igmarin
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.
About
Use cases: frontend, data, writing
Reviews
Write a reviewNo 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
- 0.585score
phoenix-authorization-patterns
igmarin
Handles all authorization and access control work in Phoenix and LiveView applications.
SkillAFreshness: A★ 5Claude Code +9 - 0.585score
benchee-profiling
igmarin
MANDATORY when profiling and benchmarking Elixir code, or before optimizing performance-critical code.
SkillAFreshness: A★ 5Claude Code +9 - 0.585score
broadway-data-pipelines
igmarin
MANDATORY when building data processing pipelines or consuming message queues.
SkillAFreshness: A★ 5Claude Code +9 - 0.585score
oban-essentials
igmarin
MANDATORY for ALL Oban work.
SkillAFreshness: A★ 5Claude Code +9 - 0.585score
cachex-caching
igmarin
MANDATORY for implementing caching in Elixir applications.
SkillAFreshness: A★ 5Claude Code +9 - 0.585score
otp-essentials
igmarin
MANDATORY for ALL OTP work.
SkillAFreshness: A★ 5Claude Code +9 - 0.585score
phoenix-authentication
igmarin
Use when adding or changing Phoenix authentication, phx.gen.auth integration, LiveView session identity, or migration between current_user and Phoenix 1.8…
SkillAFreshness: A★ 5Claude Code +9 - 0.585score
ash-framework
igmarin
MANDATORY when considering, adopting, or working with Ash Framework for Elixir applications.
SkillAFreshness: A★ 5Claude Code +9 - 0.585score
deployment-gotchas
igmarin
MANDATORY for deployment and release configuration.
SkillAFreshness: A★ 5Claude Code +9 - 0.585score
ecto-changeset-patterns
igmarin
MANDATORY for ALL changeset work beyond basic CRUD.
SkillAFreshness: A★ 5Claude Code +9 - 0.585score
ecto-nested-associations
igmarin
MANDATORY for ALL nested association and multi-table work.
SkillAFreshness: A★ 5Claude Code +9 - 0.585score
gettext-i18n
igmarin
Use when implementing internationalization (i18n) in Elixir/Phoenix applications.
SkillAFreshness: A★ 5Claude Code +9
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
- Repository
- github.com/igmarin/elixir-phoenix-skills
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from igmarin
- 0.619score
implement-hotwire
igmarin
Use when adding Turbo Frames, Turbo Streams, or Stimulus controllers.
SkillAFreshness: A★ 28Claude Code +9 - 0.619score
optimize-performance
igmarin
Use when investigating N+1s, slow queries, caching, or query plans in Rails.
SkillAFreshness: A★ 28Claude Code +9 - 0.619score
extract-engine
igmarin
Use when extracting a host-app feature into a Rails engine.
SkillAFreshness: A★ 28Claude Code +9 - 0.619score
implement-authorization
igmarin
Use when adding or reviewing Rails authorization with Pundit, CanCanCan, or policy objects.
SkillAFreshness: A★ 28Claude Code +9 - 0.619score
create-engine
igmarin
Use when scaffolding a new Rails engine.
SkillAFreshness: A★ 28Claude Code +9 - 0.619score
seed-database
igmarin
Use when choosing seeds, fixtures, or factories for Rails dev/test data.
SkillAFreshness: A★ 28Claude Code +9
Cite this page
apply-phoenix-controller-conventions skill. Agent Mart. https://agentmart.dev/skills/igmarin-apply-phoenix-controller-conventions (last updated 2026-10-24)