Files
labelmaker/CLAUDE.md
2025-10-14 18:15:41 -04:00

5.8 KiB
Raw Permalink Blame History

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 (magick command) 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

  1. Homepage (/): LabelmakerWeb.Home LiveView provides an interactive form where users can preview text with different styling options
  2. Image Generation (/:label): LabelmakerWeb.LabelController.show/2 handles 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 -pointsize for natural text sizing
    • Width x Height mode: Uses caption: with -size WxH for fixed dimensions
  • generate_link/1: Creates URLs based on current parameters and sizing mode
  • process_label/1: Handles \n to 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 parameters
    • update_preview: Changes preview background (gradient/solid)
    • update_sizing: Toggles between font size mode and width×height mode
    • update_alignment: Changes text alignment (left/center/right)
  • Redirects to /:label route 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:

  1. Basic settings: background, fill color, font
  2. Outline settings: stroke color and width (if not "none")
  3. Size settings: Either pointsize + label: OR width×height + caption:
  4. 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:

  1. Merge with defaults from Constants.defaults()
  2. Process label (convert \n escapes)
  3. Validate each parameter against permitted lists
  4. Filter out invalid values
  5. Calculate derived values (preview_height, rows, link)
  6. 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 magick command 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; \n is processed as literal newline
  • Main branch: This repo uses trunk as the main branch (not main or master)