Files
MarkandClaude Sonnet 4.6 bb6323b141 Fix SEO audit issues: brand rename cleanup, sitemap HTTPS, structured data, titles, descriptions, canonicals
- Replace all "GameLog" brand references with "LoreKeepers" (og:site_name, twitter meta, top-rated, community lists)
- Force HTTPS in sitemap generation; update .env.example APP_URL to https://lorekeepers.games
- Enhance VideoGame JSON-LD on game pages: add image, datePublished, author fields
- Improve title tags across all main pages (keyword-rich, include year on game pages)
- Add/update meta descriptions and og:description on all public pages
- Add canonical tag and og_title/og_description to homepage
- Add rel=prev/next pagination links on /games via head_links stack
- Add @stack('head_links') to layout head for child view injection
- Smarter description truncation on game pages (last sentence boundary)
- Improve screenshot alt text with genre context

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 14:49:27 +03:00

130 lines
6.8 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@extends('layouts.app')
@section('title', 'Browse Video Games — Filter by Genre, Platform & Year | LoreKeepers')
@section('description', 'Browse our full library of video games. Filter by genre, platform, release year, and sort by rating or popularity. Find your next favorite game.')
@section('canonical', route('games.index'))
@section('og_description', 'Browse our full library of video games. Filter by genre, platform, release year, and sort by rating or popularity. Find your next favorite game.')
@if($shouldNoindex ?? false)
@section('robots', 'noindex,follow')
@endif
@push('head_links')
@if($games->currentPage() > 1)
<link rel="prev" href="{{ $games->previousPageUrl() }}">
@endif
@if($games->hasMorePages())
<link rel="next" href="{{ $games->nextPageUrl() }}">
@endif
@endpush
@section('content')
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-10">
<div class="flex flex-col lg:flex-row gap-8">
{{-- Sidebar Filters --}}
<aside class="lg:w-56 flex-shrink-0">
<form method="GET" action="{{ route('games.index') }}" id="filter-form">
<div class="bg-[#16161d] rounded-xl border border-white/5 p-5 space-y-6">
<div>
<h3 class="text-xs font-semibold text-slate-500 uppercase tracking-wider mb-3">Sort By</h3>
<select name="sort" onchange="document.getElementById('filter-form').submit()"
class="w-full bg-[#0f0f13] border border-white/10 rounded-lg px-3 py-2 text-sm text-slate-200 focus:outline-none focus:border-purple-500">
<option value="rating" {{ request('sort', 'rating') === 'rating' ? 'selected' : '' }}>Top Rated</option>
<option value="release" {{ request('sort') === 'release' ? 'selected' : '' }}>Newest</option>
<option value="popular" {{ request('sort') === 'popular' ? 'selected' : '' }}>Most Popular</option>
<option value="title" {{ request('sort') === 'title' ? 'selected' : '' }}>A–Z</option>
</select>
</div>
@if($genres->isNotEmpty())
<div>
<h3 class="text-xs font-semibold text-slate-500 uppercase tracking-wider mb-3">Genre</h3>
<div class="space-y-1.5 max-h-52 overflow-y-auto pr-1">
<label class="flex items-center gap-2 cursor-pointer group">
<input type="radio" name="genre" value="" {{ !request('genre') ? 'checked' : '' }}
onchange="this.form.submit()"
class="accent-purple-500">
<span class="text-sm text-slate-400 group-hover:text-slate-200 transition-colors">All Genres</span>
</label>
@foreach($genres as $genre)
<label class="flex items-center gap-2 cursor-pointer group">
<input type="radio" name="genre" value="{{ $genre->id }}" {{ request('genre') == $genre->id ? 'checked' : '' }}
onchange="this.form.submit()"
class="accent-purple-500">
<span class="text-sm text-slate-400 group-hover:text-slate-200 transition-colors">{{ $genre->name }}</span>
</label>
@endforeach
</div>
</div>
@endif
@if($platforms->isNotEmpty())
<div>
<h3 class="text-xs font-semibold text-slate-500 uppercase tracking-wider mb-3">Platform</h3>
<div class="space-y-1.5 max-h-52 overflow-y-auto pr-1">
<label class="flex items-center gap-2 cursor-pointer group">
<input type="radio" name="platform" value="" {{ !request('platform') ? 'checked' : '' }}
onchange="this.form.submit()"
class="accent-purple-500">
<span class="text-sm text-slate-400 group-hover:text-slate-200 transition-colors">All Platforms</span>
</label>
@foreach($platforms as $platform)
<label class="flex items-center gap-2 cursor-pointer group">
<input type="radio" name="platform" value="{{ $platform->id }}" {{ request('platform') == $platform->id ? 'checked' : '' }}
onchange="this.form.submit()"
class="accent-purple-500">
<span class="text-sm text-slate-400 group-hover:text-slate-200 transition-colors">{{ $platform->name }}</span>
</label>
@endforeach
</div>
</div>
@endif
@if(request()->anyFilled(['genre', 'platform', 'year']))
<a href="{{ route('games.index') }}"
class="block text-center text-xs text-purple-400 hover:text-purple-300 transition-colors pt-2 border-t border-white/5">
Clear Filters
</a>
@endif
</div>
{{-- Keep sort in URL when filtering --}}
@if(request('sort'))
<input type="hidden" name="sort" value="{{ request('sort') }}">
@endif
</form>
</aside>
{{-- Games Grid --}}
<div class="flex-1 min-w-0">
<div class="flex items-center justify-between mb-6">
<h1 class="text-xl font-bold text-white">
Browse Games
<span class="text-slate-500 font-normal text-base ml-2">({{ number_format($games->total()) }})</span>
</h1>
</div>
@if($games->isEmpty())
<div class="text-center py-24 text-slate-500">
<p class="text-lg">No games found.</p>
<a href="{{ route('games.index') }}" class="mt-3 inline-block text-sm text-purple-400 hover:text-purple-300">Clear filters</a>
</div>
@else
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 xl:grid-cols-5 gap-4">
@foreach($games as $game)
<x-game-card :game="$game" />
@endforeach
</div>
<div class="mt-8">
{{ $games->links() }}
</div>
@endif
</div>
</div>
</div>
@endsection