From phoenix
Implements Phoenix Framework patterns for context design, controller actions, fallback handling, and plug pipelines when building Elixir web applications.
npx claudepluginhub thebushidocollective/han --plugin phoenixThis skill is limited to using the following tools:
Master Phoenix Framework patterns to build well-structured, maintainable web applications in Elixir.
Guides Phoenix web app development in Elixir: LiveView lifecycle and components, context design and generation, channels, routers, plugs, project structure, and troubleshooting.
Guides Phoenix context design: creating/splitting contexts, Scope (1.8+), Ecto.Multi, PubSub, routers, plugs, controllers. Use when editing contexts, routers, or designing boundaries.
Writes idiomatic Elixir code with OTP patterns, supervision trees, Phoenix LiveView. Handles concurrency, fault tolerance, distributed systems.
Share bugs, ideas, or general feedback.
Master Phoenix Framework patterns to build well-structured, maintainable web applications in Elixir.
Contexts are dedicated modules that expose and group related functionality:
defmodule MyApp.Accounts do
@moduledoc """
The Accounts context handles user management and authentication.
"""
alias MyApp.Repo
alias MyApp.Accounts.User
def list_users do
Repo.all(User)
end
def get_user!(id), do: Repo.get!(User, id)
def get_user_by_email(email) do
Repo.get_by(User, email: email)
end
def create_user(attrs \\ %{}) do
%User{}
|> User.changeset(attrs)
|> Repo.insert()
end
def update_user(%User{} = user, attrs) do
user
|> User.changeset(attrs)
|> Repo.update()
end
def delete_user(%User{} = user) do
Repo.delete(user)
end
def change_user(%User{} = user, attrs \\ %{}) do
User.changeset(user, attrs)
end
end
defmodule MyAppWeb.UserController do
use MyAppWeb, :controller
alias MyApp.Accounts
alias MyApp.Accounts.User
action_fallback MyAppWeb.FallbackController
def index(conn, _params) do
users = Accounts.list_users()
render(conn, :index, users: users)
end
def create(conn, %{"user" => user_params}) do
with {:ok, %User{} = user} <- Accounts.create_user(user_params) do
conn
|> put_status(:created)
|> put_resp_header("location", ~p"/api/users/#{user}")
|> render(:show, user: user)
end
end
def show(conn, %{"id" => id}) do
user = Accounts.get_user!(id)
render(conn, :show, user: user)
end
def update(conn, %{"id" => id, "user" => user_params}) do
user = Accounts.get_user!(id)
with {:ok, %User{} = user} <- Accounts.update_user(user, user_params) do
render(conn, :show, user: user)
end
end
def delete(conn, %{"id" => id}) do
user = Accounts.get_user!(id)
with {:ok, %User{}} <- Accounts.delete_user(user) do
send_resp(conn, :no_content, "")
end
end
end
defmodule MyAppWeb.FallbackController do
use MyAppWeb, :controller
def call(conn, {:error, :not_found}) do
conn
|> put_status(:not_found)
|> put_view(json: MyAppWeb.ErrorJSON)
|> render(:"404")
end
def call(conn, {:error, %Ecto.Changeset{} = changeset}) do
conn
|> put_status(:unprocessable_entity)
|> put_view(json: MyAppWeb.ChangesetJSON)
|> render(:error, changeset: changeset)
end
def call(conn, {:error, :unauthorized}) do
conn
|> put_status(:unauthorized)
|> put_view(json: MyAppWeb.ErrorJSON)
|> render(:"401")
end
end
defmodule MyAppWeb.Router do
use MyAppWeb, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, html: {MyAppWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
end
pipeline :api do
plug :accepts, ["json"]
plug MyAppWeb.Plugs.Authenticate
end
pipeline :admin do
plug MyAppWeb.Plugs.RequireAdmin
end
scope "/", MyAppWeb do
pipe_through :browser
get "/", PageController, :home
end
scope "/api", MyAppWeb do
pipe_through :api
resources "/users", UserController, except: [:new, :edit]
scope "/admin" do
pipe_through :admin
resources "/settings", Admin.SettingsController
end
end
end
defmodule MyAppWeb.Plugs.Authenticate do
import Plug.Conn
def init(opts), do: opts
def call(conn, _opts) do
with ["Bearer " <> token] <- get_req_header(conn, "authorization"),
{:ok, user} <- MyApp.Accounts.verify_token(token) do
assign(conn, :current_user, user)
else
_ ->
conn
|> put_status(:unauthorized)
|> Phoenix.Controller.put_view(json: MyAppWeb.ErrorJSON)
|> Phoenix.Controller.render(:"401")
|> halt()
end
end
end
Use phoenix-patterns when you need to: