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:
co-authored by
Claude Sonnet 4.6
parent
ea3e376507
commit
bb6323b141
+1
-1
@@ -2,7 +2,7 @@ APP_NAME=Laravel
|
|||||||
APP_ENV=local
|
APP_ENV=local
|
||||||
APP_KEY=
|
APP_KEY=
|
||||||
APP_DEBUG=true
|
APP_DEBUG=true
|
||||||
APP_URL=http://localhost
|
APP_URL=https://lorekeepers.games
|
||||||
|
|
||||||
APP_LOCALE=en
|
APP_LOCALE=en
|
||||||
APP_FALLBACK_LOCALE=en
|
APP_FALLBACK_LOCALE=en
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ namespace App\Console\Commands;
|
|||||||
use App\Models\Game;
|
use App\Models\Game;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\Facades\URL;
|
||||||
use Spatie\Sitemap\Sitemap;
|
use Spatie\Sitemap\Sitemap;
|
||||||
use Spatie\Sitemap\Tags\Url;
|
use Spatie\Sitemap\Tags\Url;
|
||||||
|
|
||||||
@@ -15,6 +16,7 @@ class GenerateSitemapCommand extends Command
|
|||||||
|
|
||||||
public function handle(): int
|
public function handle(): int
|
||||||
{
|
{
|
||||||
|
URL::forceScheme('https');
|
||||||
$sitemap = Sitemap::create()
|
$sitemap = Sitemap::create()
|
||||||
->add(Url::create('/')->setPriority(1.0)->setChangeFrequency(Url::CHANGE_FREQUENCY_DAILY))
|
->add(Url::create('/')->setPriority(1.0)->setChangeFrequency(Url::CHANGE_FREQUENCY_DAILY))
|
||||||
->add(Url::create('/games')->setPriority(0.9)->setChangeFrequency(Url::CHANGE_FREQUENCY_DAILY))
|
->add(Url::create('/games')->setPriority(0.9)->setChangeFrequency(Url::CHANGE_FREQUENCY_DAILY))
|
||||||
|
|||||||
@@ -1,12 +1,22 @@
|
|||||||
@extends('layouts.app')
|
@extends('layouts.app')
|
||||||
|
|
||||||
@section('title', 'Browse Games — LoreKeepers')
|
@section('title', 'Browse Video Games — Filter by Genre, Platform & Year | LoreKeepers')
|
||||||
@section('description', 'Browse and discover video games. Filter by genre, platform, and year. Find your next favorite game on 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('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)
|
@if($shouldNoindex ?? false)
|
||||||
@section('robots', 'noindex,follow')
|
@section('robots', 'noindex,follow')
|
||||||
@endif
|
@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')
|
@section('content')
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-10">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-10">
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
@extends('layouts.app')
|
@extends('layouts.app')
|
||||||
|
|
||||||
@section('title', 'New Releases — LoreKeepers')
|
@section('title', 'New Video Game Releases — Latest Games | LoreKeepers')
|
||||||
@section('description', 'Browse the latest video game releases. Stay up to date with new games across all platforms.')
|
@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('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')
|
@section('content')
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-10">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-10">
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
@extends('layouts.app')
|
@extends('layouts.app')
|
||||||
@php use Illuminate\Support\Str; @endphp
|
@php use Illuminate\Support\Str; @endphp
|
||||||
|
|
||||||
@section('title', $game->title . ' — LoreKeepers')
|
@section('title', $game->title . ($game->release_year ? ' (' . $game->release_year . ')' : '') . ' — Reviews, Rating & Info | LoreKeepers')
|
||||||
@section('description', $game->summary ? Str::limit($game->summary, 155) : 'Track ' . $game->title . ' on 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_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_image', $game->cover_url ?? asset('images/og-default.jpg'))
|
||||||
@section('og_type', 'website')
|
@section('og_type', 'website')
|
||||||
@section('canonical', route('games.show', $game))
|
@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">
|
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-3">
|
||||||
@foreach($game->screenshots as $i => $shot)
|
@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">
|
<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>
|
</button>
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
@@ -716,7 +725,9 @@
|
|||||||
"@@type": "VideoGame",
|
"@@type": "VideoGame",
|
||||||
"name": {{ json_encode($game->title) }},
|
"name": {{ json_encode($game->title) }},
|
||||||
"description": {{ json_encode($game->summary ?? '') }},
|
"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())
|
@if($game->genres->isNotEmpty())
|
||||||
,"genre": {{ json_encode($game->genres->pluck('name')->values()) }}
|
,"genre": {{ json_encode($game->genres->pluck('name')->values()) }}
|
||||||
@endif
|
@endif
|
||||||
@@ -747,6 +758,10 @@
|
|||||||
@endforeach
|
@endforeach
|
||||||
]
|
]
|
||||||
@endif
|
@endif
|
||||||
|
@php $developer = $game->companies->where('pivot.role', 'developer')->first(); @endphp
|
||||||
|
@if($developer)
|
||||||
|
,"author": {"@@type": "Organization", "name": {{ json_encode($developer->name) }}}
|
||||||
|
@endif
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
@extends('layouts.app')
|
@extends('layouts.app')
|
||||||
|
|
||||||
@section('title', 'Top Rated Games — LoreKeepers')
|
@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 GameLog community ratings.')
|
@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('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')
|
@section('content')
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-10">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-10">
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
@extends('layouts.app')
|
@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')
|
@section('content')
|
||||||
|
|
||||||
|
|||||||
@@ -16,10 +16,10 @@
|
|||||||
<meta property="og:image" content="@yield('og_image', asset('images/og-default.jpg'))">
|
<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:type" content="@yield('og_type', 'website')">
|
||||||
<meta property="og:url" content="@yield('og_url', url()->current())">
|
<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:card" content="summary_large_image">
|
||||||
<meta name="twitter:title" content="@yield('title', 'GameLog — Track Every Game You Play')">
|
<meta name="twitter:title" content="@yield('title', 'LoreKeepers — 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: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'))">
|
<meta name="twitter:image" content="@yield('og_image', asset('images/og-default.jpg'))">
|
||||||
|
|
||||||
<!-- Fonts -->
|
<!-- Fonts -->
|
||||||
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||||
@stack('styles')
|
@stack('styles')
|
||||||
|
@stack('head_links')
|
||||||
</head>
|
</head>
|
||||||
<body class="h-full bg-[#0f0f13] text-slate-200 antialiased font-sans">
|
<body class="h-full bg-[#0f0f13] text-slate-200 antialiased font-sans">
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
@extends('layouts.app')
|
@extends('layouts.app')
|
||||||
@php use Illuminate\Support\Str; @endphp
|
@php use Illuminate\Support\Str; @endphp
|
||||||
|
|
||||||
@section('title', 'Community Lists — GameLog')
|
@section('title', 'Community Lists — LoreKeepers')
|
||||||
@section('description', 'Browse public game lists created by the GameLog community.')
|
@section('description', 'Browse public game lists created by the LoreKeepers community.')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-10">
|
<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 class="flex items-center justify-between mb-8">
|
||||||
<div>
|
<div>
|
||||||
<h1 class="text-2xl font-bold text-white">Community Lists</h1>
|
<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>
|
</div>
|
||||||
@auth
|
@auth
|
||||||
<a href="{{ route('lists.index') }}"
|
<a href="{{ route('lists.index') }}"
|
||||||
|
|||||||
Reference in New Issue
Block a user