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>
This commit is contained in:
Mark
2026-06-02 14:49:27 +03:00
co-authored by Claude Sonnet 4.6
parent ea3e376507
commit bb6323b141
9 changed files with 53 additions and 19 deletions
+12 -2
View File
@@ -1,12 +1,22 @@
@extends('layouts.app')
@section('title', 'Browse Games — LoreKeepers')
@section('description', 'Browse and discover video games. Filter by genre, platform, and year. Find your next favorite game on LoreKeepers.')
@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">
+3 -2
View File
@@ -1,8 +1,9 @@
@extends('layouts.app')
@section('title', 'New Releases — LoreKeepers')
@section('description', 'Browse the latest video game releases. Stay up to date with new games across all platforms.')
@section('title', 'New Video Game Releases — Latest Games | LoreKeepers')
@section('description', 'Explore the latest video game releases sorted by release date. Track new games, add them to your library, and see what the LoreKeepers community thinks.')
@section('canonical', route('games.new-releases'))
@section('og_description', 'Explore the latest video game releases sorted by release date. Track new games, add them to your library, and see what the LoreKeepers community thinks.')
@section('content')
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-10">
+20 -5
View File
@@ -1,10 +1,19 @@
@extends('layouts.app')
@php use Illuminate\Support\Str; @endphp
@section('title', $game->title . ' — LoreKeepers')
@section('description', $game->summary ? Str::limit($game->summary, 155) : 'Track ' . $game->title . ' on LoreKeepers.')
@section('title', $game->title . ($game->release_year ? ' (' . $game->release_year . ')' : '') . ' — Reviews, Rating & Info | LoreKeepers')
@php
$metaDesc = $game->summary ?? '';
if (strlen($metaDesc) > 155) {
$truncated = substr($metaDesc, 0, 155);
$lastDot = strrpos($truncated, '.');
$metaDesc = $lastDot > 100 ? substr($truncated, 0, $lastDot + 1) : Str::limit($metaDesc, 155);
}
if (!$metaDesc) $metaDesc = 'Track, rate and review ' . $game->title . ' on LoreKeepers. See community ratings, reviews, and similar games.';
@endphp
@section('description', $metaDesc)
@section('og_title', $game->title . ' — LoreKeepers')
@section('og_description', $game->summary ? Str::limit($game->summary, 155) : 'Track ' . $game->title . ' on LoreKeepers.')
@section('og_description', $game->summary ? Str::limit($game->summary, 200) : 'Track, rate and review ' . $game->title . ' on LoreKeepers.')
@section('og_image', $game->cover_url ?? asset('images/og-default.jpg'))
@section('og_type', 'website')
@section('canonical', route('games.show', $game))
@@ -406,7 +415,7 @@
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-3">
@foreach($game->screenshots as $i => $shot)
<button @click="openAt({{ $i }})" class="block w-full rounded-lg overflow-hidden bg-[#16161d] hover:ring-1 hover:ring-purple-500 transition-all">
<img src="{{ $shot->thumb_url ?? $shot->url }}" alt="{{ $game->title }} screenshot {{ $loop->iteration }}" class="w-full aspect-video object-cover">
<img src="{{ $shot->thumb_url ?? $shot->url }}" alt="{{ $game->title }} — screenshot {{ $loop->iteration }}, {{ $game->genres->first()?->name ?? 'gameplay' }} scene" class="w-full aspect-video object-cover">
</button>
@endforeach
</div>
@@ -716,7 +725,9 @@
"@@type": "VideoGame",
"name": {{ json_encode($game->title) }},
"description": {{ json_encode($game->summary ?? '') }},
"url": {{ json_encode(route('games.show', $game)) }}
"url": {{ json_encode(route('games.show', $game)) }},
"image": {{ json_encode($game->cover_url ?? '') }},
"datePublished": {{ json_encode($game->release_date?->toDateString() ?? '') }}
@if($game->genres->isNotEmpty())
,"genre": {{ json_encode($game->genres->pluck('name')->values()) }}
@endif
@@ -747,6 +758,10 @@
@endforeach
]
@endif
@php $developer = $game->companies->where('pivot.role', 'developer')->first(); @endphp
@if($developer)
,"author": {"@@type": "Organization", "name": {{ json_encode($developer->name) }}}
@endif
}
</script>
<script>
+3 -2
View File
@@ -1,8 +1,9 @@
@extends('layouts.app')
@section('title', 'Top Rated Games — LoreKeepers')
@section('description', 'Discover the highest rated video games of all time, ranked by GameLog community ratings.')
@section('title', 'Top Rated Video Games of All Time — Community Rankings | LoreKeepers')
@section('description', 'Discover the highest-rated video games of all time, ranked by LoreKeepers community ratings. Filter by genre and platform to find the best games to play.')
@section('canonical', route('games.top-rated'))
@section('og_description', 'Discover the highest-rated video games of all time, ranked by LoreKeepers community ratings. Filter by genre and platform to find the best games to play.')
@section('content')
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-10">
+5 -1
View File
@@ -1,6 +1,10 @@
@extends('layouts.app')
@section('title', 'LoreKeepers — Track Every Game You Play')
@section('title', 'LoreKeepers — Track, Rate & Discover Video Games You Love')
@section('canonical', route('home'))
@section('description', 'LoreKeepers lets you track, rate, and review every game you play. Build your game library, discover top-rated games, and connect with other players.')
@section('og_title', 'LoreKeepers — Track, Rate & Discover Video Games You Love')
@section('og_description', 'Track, rate and review every game you play. Build your game library, discover top-rated games, and connect with other players on LoreKeepers.')
@section('content')
+4 -3
View File
@@ -16,10 +16,10 @@
<meta property="og:image" content="@yield('og_image', asset('images/og-default.jpg'))">
<meta property="og:type" content="@yield('og_type', 'website')">
<meta property="og:url" content="@yield('og_url', url()->current())">
<meta property="og:site_name" content="GameLog">
<meta property="og:site_name" content="LoreKeepers">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="@yield('title', 'GameLog — Track Every Game You Play')">
<meta name="twitter:description" content="@yield('description', 'GameLog lets you track every game you play, rate your favorites, and discover what to play next.')">
<meta name="twitter:title" content="@yield('title', 'LoreKeepers — Track Every Game You Play')">
<meta name="twitter:description" content="@yield('description', 'LoreKeepers lets you track every game you play, rate your favorites, and discover what to play next.')">
<meta name="twitter:image" content="@yield('og_image', asset('images/og-default.jpg'))">
<!-- Fonts -->
@@ -28,6 +28,7 @@
@vite(['resources/css/app.css', 'resources/js/app.js'])
@stack('styles')
@stack('head_links')
</head>
<body class="h-full bg-[#0f0f13] text-slate-200 antialiased font-sans">
+3 -3
View File
@@ -1,8 +1,8 @@
@extends('layouts.app')
@php use Illuminate\Support\Str; @endphp
@section('title', 'Community Lists — GameLog')
@section('description', 'Browse public game lists created by the GameLog community.')
@section('title', 'Community Lists — LoreKeepers')
@section('description', 'Browse public game lists created by the LoreKeepers community.')
@section('content')
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-10">
@@ -10,7 +10,7 @@
<div class="flex items-center justify-between mb-8">
<div>
<h1 class="text-2xl font-bold text-white">Community Lists</h1>
<p class="text-sm text-slate-500 mt-1">Public game lists from GameLog members</p>
<p class="text-sm text-slate-500 mt-1">Public game lists from LoreKeepers members</p>
</div>
@auth
<a href="{{ route('lists.index') }}"