assigns-audit

Inspect LiveView socket assigns for memory bloat — missing temporary_assigns, unused assigns, unbounded lists needing streams, memory estimates. Use when LiveView memory grows or you need to add tempo

SKILL.md

GitHub

LiveView Assigns Audit

Analyze LiveView socket assigns for memory efficiency, clarity, and best practices.

Iron Laws - Never Violate These

  1. Use streams for lists > 100 items - Never store large lists directly in assigns
  2. Use temporary_assigns for transient data - Flash messages, temp errors, notifications
  3. Preload only needed fields - Don't store full Ecto schemas when only needing subset
  4. Initialize all assigns in mount - Never access assigns that might not exist
  5. NEVER modify assigns or code during audit — this is a read-only diagnostic; report findings only

Quick Audit Commands

Extract All Assigns

Use Grep to find all assign( and assign_new( calls in the target LiveView file.

Find Large Data Patterns

Use Grep to find large data patterns: lists stored in assigns (assign.*\[\], assign.*Repo\.all) and full schema storage (assign.*Repo\.get) in the target file.

Audit Checklist

1. Memory Issues

Pattern Problem Solution
assign(:items, Repo.all(...)) Unbounded list Use stream/3
assign(:user, Repo.get!(...)) Full schema Select only needed fields
assign(:file_data, binary) Large binary Store reference, not data
Nested preloads Excessive data Preload only what's rendered

2. Missing temporary_assigns

Should use temporary_assigns:

  • Flash messages
  • Form errors after submission
  • One-time notifications
  • Upload progress
def mount(_params, _session, socket) do
  {:ok, socket, temporary_assigns: [flash_message: nil]}
end

3. Unused Assigns

Search for assigns defined but never used in templates:

Use Grep to extract all assign names (assign\(:(\w+)) from the LiveView file, then use Grep to find all @\w+ references in the corresponding .heex template. Compare to find unused assigns.

4. Missing Initialization

# BAD: @items might not exist
def render(assigns) do
  ~H"<%= for item <- @items do %>"
end

# GOOD: Initialize in mount
def mount(_params, _session, socket) do
  {:ok, assign(socket, items: [])}
end

Memory Estimation

For each assign, estimate memory footprint:

Data Type Approx Size Concern Level
Integer 8 bytes Low
String (100 chars) ~200 bytes Low
List of 100 maps ~10-50 KB Medium
List of 1000 items ~100-500 KB High
Binary (image) Varies Critical
Full Ecto schema ~1-5 KB each Medium

Usage

Run /lv:assigns path/to/live_view.ex to generate an assigns inventory with memory estimates and optimization recommendations.