Skip to main content
The skin catalog feature provides a comprehensive, searchable database of all League of Legends champion skins with advanced filtering capabilities.

Overview

Heimerdinger.lol’s skin catalog allows users to:
  • Browse all available champion skins with pagination
  • Search skins by name with partial matching
  • Filter by rarity tier (Common, Epic, Legendary, Mythic, Ultimate, etc.)
  • View high-quality splash art and loading screen images
  • Explore chroma variants for each skin
  • See visual features (new animations, voice, textures, particles, recall, VFX, SFX)

Routes

The skin feature uses two main routes defined in routes/web.php:47-48:
Route::get('skins', static fn (Request $request) => (new ChampionSkinController)->index($request))->name('skins.index');
Route::get('skin/{championSkin}', static fn (ChampionSkin $championSkin) => (new ChampionSkinController)->show($championSkin))->name('skins.show');

Skin List Page

The ChampionSkinController::index() method (source/app/Http/Controllers/ChampionSkinController.php:18-36) displays paginated skins with filtering:
public function index(Request $request)
{
    $skins = QueryBuilder::for(ChampionSkin::class)
        ->allowedFilters(AllowedFilter::partial('name', 'skin_name'), 'rarity')
        ->paginate(16)
        ->appends(request()->query());

    $rarityColor = [
        'Common' => 'text-stone-300',
        'Epic' => 'text-blue-400',
        'Legendary' => 'text-red-500',
        'Rare' => 'text-pink-300',
        'Mythic' => 'text-purple-500',
        'Ultimate' => 'text-yellow-400',
        'Transcendent' => 'text-violet-400',
        'Exalted' => 'text-violet-300',
    ];

    return view('skins.index', ['skins' => $skins, 'rarityColor' => $rarityColor])
        ->fragmentIf($request->hasHeader('HX-Request'), 'skin-list');
}

Advanced Filtering

The skin catalog uses Spatie Query Builder for powerful filtering:

Name Search

Partial matching on skin names (e.g., ?filter[name]=star finds “Star Guardian Ahri”)

Rarity Filter

Exact match on rarity tier (e.g., ?filter[rarity]=Legendary)

Pagination

16 skins per page with query string preservation

HTMX Support

Fragment rendering for dynamic updates

Rarity Tiers

Skins are categorized into 8 rarity tiers, each with a distinctive color:
RarityColorTailwindCSS Class
CommonStonetext-stone-300
RarePinktext-pink-300
EpicBluetext-blue-400
LegendaryRedtext-red-500
MythicPurpletext-purple-500
UltimateYellowtext-yellow-400
TranscendentViolettext-violet-400
ExaltedLight Violettext-violet-300

Skin Detail Page

The ChampionSkinController::show() method (source/app/Http/Controllers/ChampionSkinController.php:58-67) displays individual skin details:
public function show(ChampionSkin $championSkin)
{
    $skin = Cache::remember(
        'championSkinShowCache'.$championSkin->slug,
        60 * 60 * 48,  // 48 hours
        static fn () => $championSkin->load('champion', 'chromas')
    );

    return view('skins.show', ['skin' => $skin]);
}

Eager Loading

Skin detail pages load the parent champion and all chroma variants to minimize database queries.

Cache Strategy

Skin detail pages are cached for 48 hours with a unique cache key per skin slug.

Skin Model

Skins are represented by the ChampionSkin model located at source/app/Models/ChampionSkin.php. The model includes:

Database Properties

id
integer
Primary key
skin_id
integer
Riot Games API skin ID
champion_id
integer
Parent champion ID (foreign key)
skin_name
string
Full skin name (e.g., “Star Guardian Ahri”)
rarity
string
Rarity tier (Common, Epic, Legendary, etc.)
price
integer
RP (Riot Points) price
sale_price
integer
default:"null"
Discounted price if on sale
is_legacy
boolean
Whether the skin is legacy (limited availability)
loot_eligible
boolean
Whether the skin can be obtained from loot boxes

Visual Features

The skin model tracks which new visual elements each skin includes:
  • new_animations - Custom animations
  • new_voice - New voice lines
  • new_textures - Updated textures
  • new_particles - Particle effects
  • new_recall - Custom recall animation
  • new_vfx - Visual effects
  • new_sfx - Sound effects

Relationships

// Belongs to a champion
public function champion(): BelongsTo
{
    return $this->belongsTo(Champion::class, 'champion_id', 'champion_id');
}

// Has many chromas
public function chromas(): HasMany
{
    return $this->hasMany(SkinChroma::class, 'skin_id', 'skin_id');
}

Skin Images

The ChampionSkin model provides image accessors for different display contexts:
$skin->skin_splash_centered
// High-resolution centered splash art

Chromas

Chromas are color variants of skins represented by the SkinChroma model. Each chroma has:
  • Unique chroma ID and name
  • Individual splash art and loading screen
  • Price in RP or Blue Essence
  • Association with parent skin
Chromas are displayed on the skin detail page and loaded via the chromas() relationship.

HTMX Integration

The skin catalog supports HTMX for dynamic page updates:
return view('skins.index', ['skins' => $skins, 'rarityColor' => $rarityColor])
    ->fragmentIf($request->hasHeader('HX-Request'), 'skin-list');
When an HTMX request is detected, only the skin-list fragment is returned for efficient partial page updates.

Champions

View champion details and abilities

Sales

Check current champion and skin sales

Skin Model

View the full ChampionSkin model API reference

Controller API

See the ChampionSkinController documentation

Build docs developers (and LLMs) love