5.8 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Labelmaker is a Phoenix LiveView web application that generates text-based images via URL. Users can visit labelmaker.xyz/Your Text to instantly get an image with their text, with various customization options (font, color, outline, size). The app is designed for creating decals in Tabletop Simulator.
Technology Stack
- Elixir + Phoenix Framework (Phoenix 1.7+ with LiveView)
- ImageMagick (
magickcommand) for image generation - Tailwind CSS for styling
- esbuild for JavaScript bundling
Common Commands
Development
# Install dependencies and set up assets
mix setup
# Start Phoenix server (runs on http://localhost:4000)
mix phx.server
# Start server with interactive Elixir shell
iex -S mix phx.server
Testing
# Run all tests
mix test
# Run a specific test file
mix test test/labelmaker_web/controllers/label_controller_test.exs
# Run a specific test
mix test test/labelmaker_web/controllers/label_controller_test.exs:42
Assets
# Install asset build tools (Tailwind, esbuild)
mix assets.setup
# Build assets for development
mix assets.build
# Build assets for production (minified + digest)
mix assets.deploy
Docker
docker build -t labelmaker .
docker run -p 4000:4000 labelmaker
Architecture
Request Flow
- Homepage (
/):LabelmakerWeb.HomeLiveView provides an interactive form where users can preview text with different styling options - Image Generation (
/:label):LabelmakerWeb.LabelController.show/2handles dynamic image generation
Core Components
LabelmakerWeb.LabelController (lib/labelmaker_web/controllers/label_controller.ex)
- Main entry point for image generation requests
- Takes URL path (label text) and query parameters (color, font, outline, size, width, height, align)
- Generates SHA256 hash from parameters to create unique filename for caching
- Checks if cached image exists; if not, builds ImageMagick command and generates image
- Stores generated images in
priv/static/labels/ - Returns image as PNG response
LabelmakerWeb.Tools (lib/labelmaker_web/tools.ex)
- Contains parameter processing and validation logic
process_parameters/1: Validates and normalizes user input against permitted values- Handles two sizing modes:
- Font mode (default): Uses
label:with-pointsizefor natural text sizing - Width x Height mode: Uses
caption:with-size WxHfor fixed dimensions
- Font mode (default): Uses
generate_link/1: Creates URLs based on current parameters and sizing modeprocess_label/1: Handles\nto actual newline conversion for multi-line labels- Input validation: filters colors, fonts, sizes, outlines against permitted lists
LabelmakerWeb.Constants (lib/labelmaker_web/constants.ex)
- Single source of truth for all permitted values and defaults
- Defines available colors, fonts, sizes, alignments
- Font map supports shortcuts (e.g., "h" → "Helvetica", "cs" → "Comic-Sans-MS")
- Max dimensions: 1024x1024 pixels
- Max label length: 1024 characters
- Available fonts: Comic Sans, Courier, Georgia, Helvetica, Impact, Verdana
LabelmakerWeb.Home (lib/labelmaker_web/live/home.ex)
- LiveView for homepage with interactive preview
- Handles real-time updates via
handle_event/3:update_label: Updates label text and styling parametersupdate_preview: Changes preview background (gradient/solid)update_sizing: Toggles between font size mode and width×height modeupdate_alignment: Changes text alignment (left/center/right)
- Redirects to
/:labelroute when user submits the form
LabelmakerWeb.RadioComponent (lib/labelmaker_web/live/components/radio_component.ex)
- Reusable Phoenix Component for radio button groups
- Used in the homepage form for alignment selection
ImageMagick Command Construction
The controller builds ImageMagick commands programmatically:
- Basic settings: background, fill color, font
- Outline settings: stroke color and width (if not "none")
- Size settings: Either pointsize +
label:OR width×height +caption: - Final settings: Adds metadata comment and output filepath
Example generated command:
magick -background none -fill black -font Helvetica -stroke white -strokewidth 1 -pointsize 72 label:Hello World output.png
Sizing Modes
The app supports two distinct sizing modes (controlled by sizing parameter):
- Font mode (
sizing=font): ImageMagick calculates image size based on font size; natural text rendering - Width × Height mode (
sizing=wxh): Fixed canvas dimensions with text wrapped/aligned within bounds
Parameter Processing
All parameters flow through Tools.process_parameters/1:
- Merge with defaults from
Constants.defaults() - Process label (convert
\nescapes) - Validate each parameter against permitted lists
- Filter out invalid values
- Calculate derived values (preview_height, rows, link)
- Return merged map with all parameters
Caching Strategy
Images are cached using SHA256 hash of the processed options map:
- Hash includes: label, color, font, outline, size, width, height, align
- Cached files stored in
priv/static/labels/ - Before generating, checks if file exists
- No expiration mechanism (cache persists until manually cleared)
Important Notes
- ImageMagick dependency: The
magickcommand must be available in PATH - Alignment/Gravity mapping: User-facing "left/center/right" maps to ImageMagick "west/center/east" gravity values (see
Tools.process_gravity/1) - URL escaping: Special characters in labels must be URL-encoded;
\nis processed as literal newline - Main branch: This repo uses
trunkas the main branch (notmainormaster)