phoenix-views-templates
Render views and templates in Phoenix using HEEx templates, function components, slots, and assigns
What this skill does
# Phoenix Views and Templates
Phoenix uses HEEx (HTML+EEx) templates for rendering dynamic HTML content. HEEx provides compile-time validation, security through automatic escaping, and a component-based architecture. Views in Phoenix are modules that organize template rendering logic and house reusable function components.
## View Module Structure
Phoenix view modules use the `embed_templates` macro to load HEEx templates from a directory:
```elixir
defmodule HelloWeb.HelloHTML do
use HelloWeb, :html
embed_templates "hello_html/*"
end
```
This automatically creates functions for each `.html.heex` file in the `hello_html/` directory.
## HEEx Templates
### Basic Template Structure
HEEx templates combine HTML with embedded Elixir expressions:
```heex
<section>
<h2>Hello World, from Phoenix!</h2>
</section>
```
### Interpolating Dynamic Content
Use `<%= ... %>` to interpolate Elixir expressions into HTML:
```heex
<section>
<h2>Hello World, from <%= @messenger %>!</h2>
</section>
```
The `@` symbol accesses assigns passed from the controller.
### Multi-line Expressions
For expressions without output, omit the `=`:
```heex
<% # This is a comment %>
<% user_name = String.upcase(@user.name) %>
<p>Welcome, <%= user_name %>!</p>
```
## Working with Assigns
Assigns are key-value pairs passed from controllers to templates:
```elixir
# Controller
def show(conn, %{"messenger" => messenger}) do
render(conn, :show, messenger: messenger, receiver: "Dweezil")
end
```
```heex
<!-- Template -->
<section>
<h2>Hello <%= @receiver %>, from <%= @messenger %>!</h2>
</section>
```
All assigns are accessed with the `@` prefix in templates.
## Conditional Rendering
### Using if/else
HEEx supports conditional rendering with `if/else` blocks:
```heex
<%= if some_condition? do %>
<p>Some condition is true for user: <%= @username %></p>
<% else %>
<p>Some condition is false for user: <%= @username %></p>
<% end %>
```
### Using unless
For negative conditions:
```heex
<%= unless @user.premium do %>
<div class="upgrade-banner">
Upgrade to premium for more features!
</div>
<% end %>
```
### Pattern Matching with case
For multiple conditions:
```heex
<%= case @status do %>
<% :pending -> %>
<span class="badge badge-warning">Pending</span>
<% :approved -> %>
<span class="badge badge-success">Approved</span>
<% :rejected -> %>
<span class="badge badge-danger">Rejected</span>
<% end %>
```
## Looping and Iteration
### For Comprehensions
Generate dynamic lists using `for`:
```heex
<table>
<tr>
<th>Number</th>
<th>Power</th>
</tr>
<%= for number <- 1..10 do %>
<tr>
<td><%= number %></td>
<td><%= number * number %></td>
</tr>
<% end %>
</table>
```
### Iterating Over Collections
Loop through lists or maps:
```heex
<ul>
<%= for post <- @posts do %>
<li>
<h3><%= post.title %></h3>
<p><%= post.excerpt %></p>
</li>
<% end %>
</ul>
```
### Shorthand :for Attribute
HEEx provides cleaner syntax for simple iterations:
```heex
<ul>
<li :for={item <- @items}><%= item.name %></li>
</ul>
```
### Accessing Index
Get the iteration index with `Enum.with_index/2`:
```heex
<%= for {item, index} <- Enum.with_index(@items) do %>
<div class="item-<%= index %>">
<%= item.name %>
</div>
<% end %>
```
## Function Components
Function components are reusable UI elements defined as Elixir functions that return HEEx templates.
### Defining Function Components
Use the `attr` macro to declare attributes and the `~H` sigil for the template:
```elixir
defmodule HelloWeb.HelloHTML do
use HelloWeb, :html
embed_templates "hello_html/*"
attr :messenger, :string, required: true
def greet(assigns) do
~H"""
<h2>Hello World, from <%= @messenger %>!</h2>
"""
end
end
```
### Using Function Components
Invoke components with the `<.component_name />` syntax:
```heex
<section>
<.greet messenger={@messenger} />
</section>
```
### Optional Attributes with Defaults
Define optional attributes with default values:
```elixir
attr :messenger, :string, default: nil
attr :class, :string, default: "greeting"
def greet(assigns) do
~H"""
<h2 class={@class}>
Hello World<%= if @messenger, do: ", from #{@messenger}" %>!
</h2>
"""
end
```
### Multiple Attribute Types
Components can accept various attribute types:
```elixir
attr :title, :string, required: true
attr :count, :integer, default: 0
attr :active, :boolean, default: false
attr :user, :map, required: true
attr :items, :list, default: []
def card(assigns) do
~H"""
<div class={"card" <> if @active, do: " active", else: ""}>
<h3><%= @title %></h3>
<p>Count: <%= @count %></p>
<p>User: <%= @user.name %></p>
<ul>
<li :for={item <- @items}><%= item %></li>
</ul>
</div>
"""
end
```
### Components with Computed Values
Use `assign/2` to compute values within components:
```elixir
attr :x, :integer, required: true
attr :y, :integer, required: true
attr :title, :string, required: true
def sum_component(assigns) do
assigns = assign(assigns, sum: assigns.x + assigns.y)
~H"""
<h1><%= @title %></h1>
<p>Sum: <%= @sum %></p>
"""
end
```
## Slots
Slots allow components to accept blocks of content, enabling powerful composition patterns.
### Defining and Using Slots
Define a slot and render it:
```elixir
slot :inner_block, required: true
def card(assigns) do
~H"""
<div class="card">
<%= render_slot(@inner_block) %>
</div>
"""
end
```
Use the component with content:
```heex
<.card>
<h2>Card Title</h2>
<p>Card content goes here</p>
</.card>
```
### Named Slots
Components can have multiple named slots:
```elixir
slot :header, required: true
slot :body, required: true
slot :footer
def panel(assigns) do
~H"""
<div class="panel">
<div class="panel-header">
<%= render_slot(@header) %>
</div>
<div class="panel-body">
<%= render_slot(@body) %>
</div>
<%= if @footer != [] do %>
<div class="panel-footer">
<%= render_slot(@footer) %>
</div>
<% end %>
</div>
"""
end
```
Usage:
```heex
<.panel>
<:header>
<h2>Panel Title</h2>
</:header>
<:body>
<p>Panel content</p>
</:body>
<:footer>
<button>Close</button>
</:footer>
</.panel>
```
### Slots with Attributes
Slots can accept attributes for more dynamic rendering:
```elixir
slot :item, required: true do
attr :title, :string, required: true
attr :highlighted, :boolean, default: false
end
def list(assigns) do
~H"""
<ul>
<%= for item <- @item do %>
<li class={if item.highlighted, do: "highlight"}>
<%= item.title %>: <%= render_slot(item) %>
</li>
<% end %>
</ul>
"""
end
```
## Rendering Child Templates
### Rendering Other Templates
Include child templates within a parent:
```heex
<%= render("child_template.html", assigns) %>
```
### Rendering Components from Other Modules
Call components from different modules:
```heex
<MyApp.Components.button text="Click me" />
```
Or with aliasing:
```elixir
alias MyApp.Components
# In template:
<Components.button text="Click me" />
```
## Layout Templates
### Using Layouts
Layouts wrap rendered templates. Configure the layout in the controller:
```elixir
def controller do
quote do
use Phoenix.Controller,
formats: [:html, :json],
layouts: [html: HelloWeb.Layouts]
...
end
end
```
### Root Layout
The root layout includes the `@inner_content` placeholder:
```heex
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>My App</title>
</head>
<body>
<%= @inner_content %>
</body>
</html>
```
### App Layout Component
Nest layouts using components:
```heex
<Layouts.app flash={@flash}>
<section>
<h2>Hello World, from <%= @messenger %>!</h2>
</section>
</Layouts.app>
```
### Disabling Layouts
Render without a layout:
```elixir
def home(conn, _params) Related in Image & Video
watch
IncludedWatch a video (URL or local path). Downloads with yt-dlp, extracts auto-scaled frames with ffmpeg, pulls the transcript from captions (or Whisper API fallback), and hands the result to Claude so it can answer questions about what's in the video.
physical-ai-defect-image-generation
IncludedUse when the user wants to orchestrate defect image generation, run associated setup, or handle outputs on OSMO. The Day 0 path handles cold-start with USD-to-ROI, image-edit augmentation, and AnomalyGen to create initial PCBA datasets. The Day 1 path performs inference and labeling on real images. This skill helps with first-time asset setup, creation of finetuning checkpoints, and configuring deployment. Trigger keywords: defect image generation, dig workflow, dig pipeline, defect image detection workflow, aoi pipeline, aoi anomalygen, usd2roi anomalygen, day 0 pcba, day 1 pcba, day 1 real-photo alignment, day 1 manual roi, metal surface anomaly, glass defect, anomalygen finetune, setup_pcb, setup_metal, setup_glass, setup_pretrained, dig setup, dig datasets, dig pretrained checkpoint, dig image-edit endpoint.
accelint-react-best-practices
IncludedReact performance optimization and best practices. ALWAYS use this skill when working with any React code - writing components, hooks, JSX; refactoring; optimizing re-renders, memoization, state management; reviewing for performance; fixing hydration mismatches; debugging infinite re-renders, stale closures, input focus loss, animations restarting; preventing remounting; implementing transitions, lazy initialization, effect dependencies. Even simple React tasks benefit from these patterns. Covers React 19+ (useEffectEvent, Activity, ref props). Triggers - useEffect, useState, useMemo, useCallback, memo, inline components, nested components, components inside components, re-render, performance, hydration, SSR, Next.js, useDeferredValue, combined hooks.
elevenlabs-agents
IncludedBuild conversational AI voice agents with ElevenLabs Platform using React, JavaScript, React Native, or Swift SDKs. Configure agents, tools (client/server/MCP), RAG knowledge bases, multi-voice, and Scribe real-time STT. Use when: building voice chat interfaces, implementing AI phone agents with Twilio, configuring agent workflows or tools, adding RAG knowledge bases, testing with CLI "agents as code", or troubleshooting deprecated @11labs packages, Android audio cutoff, CSP violations, dynamic variables, or WebRTC config. Keywords: ElevenLabs Agents, ElevenLabs voice agents, AI voice agents, conversational AI, @elevenlabs/react, @elevenlabs/client, @elevenlabs/react-native, @elevenlabs/elevenlabs-js, @elevenlabs/agents-cli, elevenlabs SDK, voice AI, TTS, text-to-speech, ASR, speech recognition, turn-taking model, WebRTC voice, WebSocket voice, ElevenLabs conversation, agent system prompt, agent tools, agent knowledge base, RAG voice agents, multi-voice agents, pronunciation dictionary, voice speed control, elevenlabs scribe, @11labs deprecated, Android audio cutoff, CSP violation elevenlabs, dynamic variables elevenlabs, case-sensitive tool names, webhook authentication
humanizer
IncludedHumanize AI-generated text by detecting and removing patterns typical of LLM output. Rewrites text to sound natural, specific, and human. Uses 28 pattern detectors, 560+ AI vocabulary terms across 3 tiers, and statistical analysis (burstiness, type-token ratio, readability) for comprehensive detection. Use when asked to humanize text, de-AI writing, make content sound more natural/human, review writing for AI patterns, score text for AI detection, or improve AI-generated drafts. Covers content, language, style, communication, and filler categories.
generating-mermaid-diagrams
IncludedSalesforce architecture diagrams using Mermaid with ASCII fallback. Use this skill when generating text-based diagrams for Salesforce architecture, OAuth flows, ERDs, integration sequences, or Agentforce structure. TRIGGER when: user says "diagram", "visualize", "ERD", or asks for sequence diagrams, flowcharts, class diagrams, or architecture visualizations in Mermaid. DO NOT TRIGGER when: user wants PNG/SVG image output (use generating-visual-diagrams), or asks about non-Salesforce systems.