Refine SEO, uploads, and deploy handling
This commit is contained in:
@@ -30,15 +30,14 @@ final class UploadVisionSuggestController extends Controller
|
||||
|
||||
public function __invoke(int $id, Request $request): JsonResponse
|
||||
{
|
||||
if (! $this->vision->isEnabled()) {
|
||||
return response()->json(['tags' => [], 'vision_enabled' => false]);
|
||||
}
|
||||
|
||||
$artwork = Artwork::query()->findOrFail($id);
|
||||
$this->authorizeOrNotFound($request->user(), $artwork);
|
||||
$limit = (int) $request->query('limit', 10);
|
||||
|
||||
return response()->json($this->vision->suggestTags($artwork, $this->normalizer, $limit));
|
||||
return response()->json([
|
||||
'tags' => [],
|
||||
'vision_enabled' => false,
|
||||
'reason' => 'disabled',
|
||||
]);
|
||||
}
|
||||
|
||||
private function authorizeOrNotFound(mixed $user, Artwork $artwork): void
|
||||
|
||||
@@ -108,7 +108,7 @@ class CollectionInsightsController extends Controller
|
||||
'bulkActions' => route('settings.collections.bulk-actions'),
|
||||
],
|
||||
'seo' => [
|
||||
'title' => 'Collections Dashboard — Skinbase Nova',
|
||||
'title' => 'Collections Dashboard — Skinbase',
|
||||
'description' => 'Overview of collection lifecycle, quality, activity, and upcoming collection campaigns.',
|
||||
'canonical' => route('settings.collections.dashboard'),
|
||||
'robots' => 'noindex,follow',
|
||||
@@ -127,7 +127,7 @@ class CollectionInsightsController extends Controller
|
||||
'historyUrl' => route('settings.collections.history', ['collection' => $collection->id]),
|
||||
'dashboardUrl' => route('settings.collections.dashboard'),
|
||||
'seo' => [
|
||||
'title' => sprintf('%s Analytics — Skinbase Nova', $collection->title),
|
||||
'title' => sprintf('%s Analytics — Skinbase', $collection->title),
|
||||
'description' => sprintf('Analytics and performance history for the %s collection.', $collection->title),
|
||||
'canonical' => route('settings.collections.analytics', ['collection' => $collection->id]),
|
||||
'robots' => 'noindex,follow',
|
||||
@@ -150,7 +150,7 @@ class CollectionInsightsController extends Controller
|
||||
'analyticsUrl' => route('settings.collections.analytics', ['collection' => $collection->id]),
|
||||
'restorePattern' => route('settings.collections.history.restore', ['collection' => $collection->id, 'history' => '__HISTORY__']),
|
||||
'seo' => [
|
||||
'title' => sprintf('%s History — Skinbase Nova', $collection->title),
|
||||
'title' => sprintf('%s History — Skinbase', $collection->title),
|
||||
'description' => sprintf('Audit history and lifecycle changes for the %s collection.', $collection->title),
|
||||
'canonical' => route('settings.collections.history', ['collection' => $collection->id]),
|
||||
'robots' => 'noindex,follow',
|
||||
|
||||
@@ -92,7 +92,7 @@ class CollectionProgrammingController extends Controller
|
||||
'surfaces' => route('settings.collections.surfaces.index'),
|
||||
],
|
||||
'seo' => [
|
||||
'title' => 'Collection Programming — Skinbase Nova',
|
||||
'title' => 'Collection Programming — Skinbase',
|
||||
'description' => 'Staff programming tools for assignments, previews, eligibility diagnostics, and recommendation refreshes.',
|
||||
'canonical' => route('staff.collections.programming'),
|
||||
'robots' => 'noindex,follow',
|
||||
|
||||
@@ -66,7 +66,7 @@ class CollectionSurfaceController extends Controller
|
||||
'batchEditorial' => route('settings.collections.surfaces.batch-editorial'),
|
||||
],
|
||||
'seo' => [
|
||||
'title' => 'Collection Surfaces - Skinbase Nova',
|
||||
'title' => 'Collection Surfaces - Skinbase',
|
||||
'description' => 'Staff tools for homepage, discovery, and campaign collection surfaces.',
|
||||
'canonical' => route('settings.collections.surfaces.index'),
|
||||
'robots' => 'noindex,follow',
|
||||
|
||||
@@ -43,7 +43,7 @@ class FeaturedArtworkAdminController extends Controller
|
||||
'forceHeroEnabled' => $this->hasForceHeroColumn(),
|
||||
],
|
||||
'seo' => [
|
||||
'title' => 'Featured Artworks — Skinbase Nova',
|
||||
'title' => 'Featured Artworks — Skinbase',
|
||||
'description' => 'Editorial controls for homepage featured artworks and the current hero winner.',
|
||||
'canonical' => route($routePrefix . 'main'),
|
||||
'robots' => 'noindex,follow',
|
||||
|
||||
@@ -40,7 +40,7 @@ final class StudioWorldController extends Controller
|
||||
|
||||
return Inertia::render('Studio/StudioWorldsIndex', [
|
||||
'title' => 'Worlds',
|
||||
'description' => 'Create and manage seasonal, event, and campaign destinations across Skinbase Nova.',
|
||||
'description' => 'Create and manage seasonal, event, and campaign destinations across Skinbase.',
|
||||
'listing' => $this->worlds->studioListing($request->only(['q', 'status', 'type', 'per_page'])),
|
||||
'analytics' => $this->analytics->portfolioReport(),
|
||||
'statusOptions' => [
|
||||
@@ -435,7 +435,7 @@ final class StudioWorldController extends Controller
|
||||
|
||||
$payload = $this->worlds->publicShowPayload($world, $request->user(), true);
|
||||
$seo = app(SeoFactory::class)->collectionPage(
|
||||
$world->seo_title ?: ($world->title . ' — Skinbase Nova Preview'),
|
||||
$world->seo_title ?: ($world->title . ' — Skinbase Preview'),
|
||||
$world->seo_description ?: ($world->summary ?: $world->description ?: 'Preview world page'),
|
||||
route('studio.worlds.preview', ['world' => $world]),
|
||||
$world->ogImageUrl(),
|
||||
|
||||
@@ -116,9 +116,9 @@ class ProfileCollectionController extends Controller
|
||||
|
||||
$seo = app(SeoFactory::class)->collectionPage(
|
||||
$collection->is_featured
|
||||
? sprintf('Featured: %s by %s — Skinbase Nova', $collection->title, $collection->displayOwnerName())
|
||||
: sprintf('%s by %s — Skinbase Nova', $collection->title, $collection->displayOwnerName()),
|
||||
$collection->summary ?: $collection->description ?: sprintf('Explore the %s collection by %s on Skinbase Nova.', $collection->title, $collection->displayOwnerName()),
|
||||
? sprintf('Featured: %s by %s — Skinbase', $collection->title, $collection->displayOwnerName())
|
||||
: sprintf('%s by %s — Skinbase', $collection->title, $collection->displayOwnerName()),
|
||||
$collection->summary ?: $collection->description ?: sprintf('Explore the %s collection by %s on Skinbase.', $collection->title, $collection->displayOwnerName()),
|
||||
$collectionPayload['public_url'],
|
||||
$collectionPayload['cover_image'],
|
||||
$collection->visibility === Collection::VISIBILITY_PUBLIC,
|
||||
@@ -202,8 +202,8 @@ class ProfileCollectionController extends Controller
|
||||
$seriesDescription = $seriesMeta['description'];
|
||||
|
||||
$seo = app(SeoFactory::class)->collectionListing(
|
||||
sprintf('Series: %s — Skinbase Nova', $seriesKey),
|
||||
sprintf('Explore the %s collection series on Skinbase Nova.', $seriesKey),
|
||||
sprintf('Series: %s — Skinbase', $seriesKey),
|
||||
sprintf('Explore the %s collection series on Skinbase.', $seriesKey),
|
||||
route('collections.series.show', ['seriesKey' => $seriesKey])
|
||||
)->toArray();
|
||||
|
||||
|
||||
@@ -155,8 +155,8 @@ class SavedCollectionController extends Controller
|
||||
'libraryUrl' => route('me.saved.collections'),
|
||||
'browseUrl' => route('collections.featured'),
|
||||
'seo' => [
|
||||
'title' => $activeList ? sprintf('%s — Saved Collections — Skinbase Nova', $activeList->title) : 'Saved Collections — Skinbase Nova',
|
||||
'description' => $activeList ? sprintf('Saved collections in the %s list on Skinbase Nova.', $activeList->title) : 'Your saved collections on Skinbase Nova.',
|
||||
'title' => $activeList ? sprintf('%s — Saved Collections — Skinbase', $activeList->title) : 'Saved Collections — Skinbase',
|
||||
'description' => $activeList ? sprintf('Saved collections in the %s list on Skinbase.', $activeList->title) : 'Your saved collections on Skinbase.',
|
||||
'canonical' => $activeList ? route('me.saved.collections.lists.show', ['listSlug' => $activeList->slug]) : route('me.saved.collections'),
|
||||
'robots' => 'noindex,follow',
|
||||
],
|
||||
|
||||
@@ -18,7 +18,7 @@ final class AccountHelpPageController extends Controller
|
||||
$seo = app(SeoFactory::class)
|
||||
->collectionPage(
|
||||
'Account Settings Help — Skinbase',
|
||||
'Learn how account settings, profile settings, email changes, password care, and creator preferences work on Skinbase Nova.',
|
||||
'Learn how account settings, profile settings, email changes, password care, and creator preferences work on Skinbase.',
|
||||
$canonical,
|
||||
)
|
||||
->toArray();
|
||||
|
||||
@@ -18,7 +18,7 @@ final class AuthHelpPageController extends Controller
|
||||
$seo = app(SeoFactory::class)
|
||||
->collectionPage(
|
||||
'Signup and Login Help — Skinbase',
|
||||
'Learn how signup, login, password recovery, verification, and account access work on Skinbase Nova, with clear guidance for common access problems and practical next steps.',
|
||||
'Learn how signup, login, password recovery, verification, and account access work on Skinbase, with clear guidance for common access problems and practical next steps.',
|
||||
$canonical,
|
||||
)
|
||||
->toArray();
|
||||
@@ -27,7 +27,7 @@ final class AuthHelpPageController extends Controller
|
||||
|
||||
return Inertia::render('Help/AuthHelpPage', [
|
||||
'title' => 'Signup & Login Help',
|
||||
'description' => 'Get clear help for account creation, sign-in, password recovery, verification basics, and common access problems on Skinbase Nova.',
|
||||
'description' => 'Get clear help for account creation, sign-in, password recovery, verification basics, and common access problems on Skinbase.',
|
||||
'seo' => $seo,
|
||||
'links' => [
|
||||
'help_home' => route('help'),
|
||||
|
||||
@@ -184,7 +184,7 @@ class BrowseGalleryController extends \App\Http\Controllers\Controller
|
||||
(object) ['name' => 'Explore', 'url' => '/browse'],
|
||||
(object) ['name' => $contentType->name, 'url' => '/' . $contentSlug],
|
||||
]),
|
||||
'page_title' => $contentType->name . ' – Skinbase Nova',
|
||||
'page_title' => $contentType->name . ' – Skinbase',
|
||||
'page_meta_description' => $contentType->description ?? ('Discover the best ' . $contentType->name . ' artworks on Skinbase'),
|
||||
'page_meta_keywords' => strtolower($contentType->slug) . ', skinbase, artworks, wallpapers, skins, photography',
|
||||
'page_canonical' => $seo['canonical'],
|
||||
@@ -264,7 +264,7 @@ class BrowseGalleryController extends \App\Http\Controllers\Controller
|
||||
'hero_title' => $category->name,
|
||||
'hero_description' => $category->description ?? ($contentType->name . ' artworks on Skinbase.'),
|
||||
'breadcrumbs' => $breadcrumbs,
|
||||
'page_title' => $category->name . ' – Skinbase Nova',
|
||||
'page_title' => $category->name . ' – Skinbase',
|
||||
'page_meta_description' => $category->description ?? ('Discover the best ' . $category->name . ' ' . $contentType->name . ' artworks on Skinbase'),
|
||||
'page_meta_keywords' => strtolower($contentType->slug) . ', skinbase, artworks, wallpapers, skins, photography',
|
||||
'page_canonical' => $seo['canonical'],
|
||||
|
||||
@@ -18,7 +18,7 @@ final class CardsHelpPageController extends Controller
|
||||
$seo = app(SeoFactory::class)
|
||||
->collectionPage(
|
||||
'Cards Help — Skinbase',
|
||||
'Learn what Cards are on Skinbase Nova, how they differ from artworks, posts, and collections, and how to create, publish, and use them effectively in personal and Group workflows.',
|
||||
'Learn what Cards are on Skinbase, how they differ from artworks, posts, and collections, and how to create, publish, and use them effectively in personal and Group workflows.',
|
||||
$canonical,
|
||||
)
|
||||
->toArray();
|
||||
@@ -27,7 +27,7 @@ final class CardsHelpPageController extends Controller
|
||||
|
||||
return Inertia::render('Help/CardsHelpPage', [
|
||||
'title' => 'Cards Help',
|
||||
'description' => 'Understand Cards as a distinct creative format on Skinbase Nova, with guidance for creation, publishing, ownership, design quality, and real-world use cases.',
|
||||
'description' => 'Understand Cards as a distinct creative format on Skinbase, with guidance for creation, publishing, ownership, design quality, and real-world use cases.',
|
||||
'seo' => $seo,
|
||||
'links' => [
|
||||
'help_home' => route('help'),
|
||||
|
||||
@@ -52,9 +52,9 @@ class CollectionDiscoveryController extends Controller
|
||||
$results = $this->search->publicSearch($filters, (int) config('collections.v5.search.public_per_page', 18));
|
||||
|
||||
$seo = app(SeoFactory::class)->collectionListing(
|
||||
'Search Collections — Skinbase Nova',
|
||||
'Search Collections — Skinbase',
|
||||
filled($filters['q'] ?? null)
|
||||
? sprintf('Search results for "%s" across public Skinbase Nova collections.', $filters['q'])
|
||||
? sprintf('Search results for "%s" across public Skinbase collections.', $filters['q'])
|
||||
: 'Browse public collections using filters for category, style, theme, color, quality tier, freshness, and programming metadata.',
|
||||
$request->fullUrl(),
|
||||
null,
|
||||
@@ -65,7 +65,7 @@ class CollectionDiscoveryController extends Controller
|
||||
'eyebrow' => 'Search',
|
||||
'title' => 'Search collections',
|
||||
'description' => filled($filters['q'] ?? null)
|
||||
? sprintf('Search results for "%s" across public Skinbase Nova collections.', $filters['q'])
|
||||
? sprintf('Search results for "%s" across public Skinbase collections.', $filters['q'])
|
||||
: 'Browse public collections using filters for category, style, theme, color, quality tier, freshness, and programming metadata.',
|
||||
'seo' => $seo,
|
||||
'collections' => $this->collections->mapCollectionCardPayloads($results->items(), false, $request->user()),
|
||||
@@ -100,7 +100,7 @@ class CollectionDiscoveryController extends Controller
|
||||
viewer: $request->user(),
|
||||
eyebrow: 'Discovery',
|
||||
title: 'Featured collections',
|
||||
description: 'A rotating set of standout galleries from across Skinbase Nova. Some are meticulously hand-sequenced. Others are smart collections that stay fresh as the creator publishes new work.',
|
||||
description: 'A rotating set of standout galleries from across Skinbase. Some are meticulously hand-sequenced. Others are smart collections that stay fresh as the creator publishes new work.',
|
||||
collections: $featuredCollections->isNotEmpty() ? $featuredCollections : $this->discovery->publicFeaturedCollections((int) config('collections.discovery.featured_limit', 18)),
|
||||
communityCollections: $this->discovery->publicCollectionsByType(Collection::TYPE_COMMUNITY, 6),
|
||||
editorialCollections: $this->discovery->publicCollectionsByType(Collection::TYPE_EDITORIAL, 6),
|
||||
@@ -204,7 +204,7 @@ class CollectionDiscoveryController extends Controller
|
||||
abort_if(! $program || collect($landing['collections'])->isEmpty(), 404);
|
||||
|
||||
$seo = app(SeoFactory::class)->collectionListing(
|
||||
sprintf('%s — Skinbase Nova', $program['label']),
|
||||
sprintf('%s — Skinbase', $program['label']),
|
||||
$program['description'],
|
||||
route('collections.program.show', ['programKey' => $program['key']]),
|
||||
)->toArray();
|
||||
@@ -239,7 +239,7 @@ class CollectionDiscoveryController extends Controller
|
||||
$campaign = null,
|
||||
) {
|
||||
$seo = app(SeoFactory::class)->collectionListing(
|
||||
sprintf('%s — Skinbase Nova', $title),
|
||||
sprintf('%s — Skinbase', $title),
|
||||
$description,
|
||||
url()->current(),
|
||||
)->toArray();
|
||||
|
||||
@@ -18,7 +18,7 @@ final class GroupFaqPageController extends Controller
|
||||
$seo = app(SeoFactory::class)
|
||||
->collectionPage(
|
||||
'Groups FAQ — Skinbase',
|
||||
'Fast answers to the most common Groups questions on Skinbase Nova, including roles, permissions, publishing, contributor credit, invites, workflows, and troubleshooting.',
|
||||
'Fast answers to the most common Groups questions on Skinbase, including roles, permissions, publishing, contributor credit, invites, workflows, and troubleshooting.',
|
||||
$canonical,
|
||||
)
|
||||
->toArray();
|
||||
@@ -27,7 +27,7 @@ final class GroupFaqPageController extends Controller
|
||||
|
||||
return Inertia::render('Group/GroupFaqPage', [
|
||||
'title' => 'Groups FAQ',
|
||||
'description' => 'Quick answers about Groups, roles, permissions, publishing, contributor credit, invites, workflows, and troubleshooting on Skinbase Nova.',
|
||||
'description' => 'Quick answers about Groups, roles, permissions, publishing, contributor credit, invites, workflows, and troubleshooting on Skinbase.',
|
||||
'seo' => $seo,
|
||||
'links' => [
|
||||
'groups_directory' => route('groups.index'),
|
||||
|
||||
@@ -18,7 +18,7 @@ final class GroupHelpPageController extends Controller
|
||||
$seo = app(SeoFactory::class)
|
||||
->collectionPage(
|
||||
'Groups Guide, Help, and Best Practices — Skinbase',
|
||||
'Learn how Groups work on Skinbase Nova, how shared publishing preserves contributor credit, and how to manage roles, releases, reviews, projects, and team workflows with confidence.',
|
||||
'Learn how Groups work on Skinbase, how shared publishing preserves contributor credit, and how to manage roles, releases, reviews, projects, and team workflows with confidence.',
|
||||
$canonical,
|
||||
)
|
||||
->toArray();
|
||||
@@ -27,7 +27,7 @@ final class GroupHelpPageController extends Controller
|
||||
|
||||
return Inertia::render('Group/GroupHelpPage', [
|
||||
'title' => 'Groups Help & Guide',
|
||||
'description' => 'Everything creators need to understand Groups, publish collaboratively, preserve contributor credit, and build a healthy shared identity on Skinbase Nova.',
|
||||
'description' => 'Everything creators need to understand Groups, publish collaboratively, preserve contributor credit, and build a healthy shared identity on Skinbase.',
|
||||
'seo' => $seo,
|
||||
'links' => [
|
||||
'groups_directory' => route('groups.index'),
|
||||
|
||||
@@ -18,7 +18,7 @@ final class GroupQuickstartPageController extends Controller
|
||||
$seo = app(SeoFactory::class)
|
||||
->collectionPage(
|
||||
'Groups Quickstart — Skinbase',
|
||||
'A fast, creator-friendly Groups quickstart for Skinbase Nova. Learn when to use a Group, create one, invite members, and publish your first Group artwork with correct contributor credit.',
|
||||
'A fast, creator-friendly Groups quickstart for Skinbase. Learn when to use a Group, create one, invite members, and publish your first Group artwork with correct contributor credit.',
|
||||
$canonical,
|
||||
)
|
||||
->toArray();
|
||||
|
||||
@@ -18,7 +18,7 @@ final class HelpCenterPageController extends Controller
|
||||
$seo = app(SeoFactory::class)
|
||||
->collectionPage(
|
||||
'Help Center — Skinbase',
|
||||
'Find help, guides, quickstarts, FAQs, and troubleshooting for Skinbase Nova, including Groups, Studio, Upload, Cards, Profile, and account access.',
|
||||
'Find help, guides, quickstarts, FAQs, and troubleshooting for Skinbase, including Groups, Studio, Upload, Cards, Profile, and account access.',
|
||||
$canonical,
|
||||
)
|
||||
->toArray();
|
||||
@@ -27,7 +27,7 @@ final class HelpCenterPageController extends Controller
|
||||
|
||||
return Inertia::render('Help/HelpCenterPage', [
|
||||
'title' => 'Help Center',
|
||||
'description' => 'Find guides, quickstarts, FAQs, and troubleshooting for Skinbase Nova in one structured help hub.',
|
||||
'description' => 'Find guides, quickstarts, FAQs, and troubleshooting for Skinbase in one structured help hub.',
|
||||
'seo' => $seo,
|
||||
'links' => [
|
||||
'studio_help' => route('help.studio'),
|
||||
|
||||
@@ -60,12 +60,12 @@ class NovaCardsController extends Controller
|
||||
|
||||
return view('cards.index', [
|
||||
'meta' => [
|
||||
'title' => 'Nova Cards - Skinbase Nova',
|
||||
'description' => 'Browse featured, trending, and latest Nova Cards. Discover beautiful quote cards, mood cards, and visual text art by the Skinbase Nova community.',
|
||||
'title' => 'Cards - Skinbase',
|
||||
'description' => 'Browse featured, trending, and latest Cards. Discover beautiful quote cards, mood cards, and visual text art by the Skinbase community.',
|
||||
'canonical' => route('cards.index'),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
'heading' => 'Nova Cards',
|
||||
'heading' => 'Cards',
|
||||
'subheading' => (string) config('nova_cards.brand.subtitle'),
|
||||
'cards' => $this->presenter->cards($latest->items()),
|
||||
'pagination' => $latest,
|
||||
@@ -90,13 +90,13 @@ class NovaCardsController extends Controller
|
||||
|
||||
return view('cards.index', [
|
||||
'meta' => [
|
||||
'title' => $category->name . ' Cards - Skinbase Nova',
|
||||
'description' => $category->description ?: ('Browse ' . strtolower($category->name) . ' Nova Cards on Skinbase Nova.'),
|
||||
'title' => $category->name . ' Cards - Skinbase',
|
||||
'description' => $category->description ?: ('Browse ' . strtolower($category->name) . ' Cards on Skinbase.'),
|
||||
'canonical' => route('cards.category', ['categorySlug' => $category->slug]),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
'heading' => $category->name,
|
||||
'subheading' => $category->description ?: 'Explore this Nova Cards category.',
|
||||
'subheading' => $category->description ?: 'Explore this Cards category.',
|
||||
'cards' => $this->presenter->cards($cards->items()),
|
||||
'pagination' => $cards,
|
||||
'featuredCards' => [],
|
||||
@@ -119,8 +119,8 @@ class NovaCardsController extends Controller
|
||||
|
||||
return view('cards.index', [
|
||||
'meta' => [
|
||||
'title' => 'Popular Cards - Skinbase Nova',
|
||||
'description' => 'Browse the most liked, saved, and viewed Nova Cards on Skinbase Nova.',
|
||||
'title' => 'Popular Cards - Skinbase',
|
||||
'description' => 'Browse the most liked, saved, and viewed Cards on Skinbase.',
|
||||
'canonical' => route('cards.popular'),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
@@ -153,13 +153,13 @@ class NovaCardsController extends Controller
|
||||
|
||||
return view('cards.index', [
|
||||
'meta' => [
|
||||
'title' => 'Rising Cards - Skinbase Nova',
|
||||
'description' => 'Discover Nova Cards that are gaining traction right now — fresh creators and fast-rising saves and remixes.',
|
||||
'title' => 'Rising Cards - Skinbase',
|
||||
'description' => 'Discover Cards that are gaining traction right now — fresh creators and fast-rising saves and remixes.',
|
||||
'canonical' => route('cards.rising'),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
'heading' => 'Rising',
|
||||
'subheading' => 'Fresh Nova Cards gaining momentum right now.',
|
||||
'subheading' => 'Fresh Cards gaining momentum right now.',
|
||||
'cards' => $this->presenter->cards($paginated->items(), false, $request->user()),
|
||||
'pagination' => $paginated,
|
||||
'featuredCards' => [],
|
||||
@@ -182,13 +182,13 @@ class NovaCardsController extends Controller
|
||||
|
||||
return view('cards.index', [
|
||||
'meta' => [
|
||||
'title' => 'Remixed Cards - Skinbase Nova',
|
||||
'description' => 'Discover Nova Cards remixed from community originals with attribution and lineage.',
|
||||
'title' => 'Remixed Cards - Skinbase',
|
||||
'description' => 'Discover Cards remixed from community originals with attribution and lineage.',
|
||||
'canonical' => route('cards.remixed'),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
'heading' => 'Remixed cards',
|
||||
'subheading' => 'Community reinterpretations linked back to their original Nova Cards.',
|
||||
'subheading' => 'Community reinterpretations linked back to their original Cards.',
|
||||
'cards' => $this->presenter->cards($cards->items(), false, $request->user()),
|
||||
'pagination' => $cards,
|
||||
'featuredCards' => [],
|
||||
@@ -214,8 +214,8 @@ class NovaCardsController extends Controller
|
||||
|
||||
return view('cards.index', [
|
||||
'meta' => [
|
||||
'title' => 'Best Remixes - Skinbase Nova',
|
||||
'description' => 'Browse standout Nova Card remixes ranked by remix traction, saves, and likes.',
|
||||
'title' => 'Best Remixes - Skinbase',
|
||||
'description' => 'Browse standout Card remixes ranked by remix traction, saves, and likes.',
|
||||
'canonical' => route('cards.remix-highlights'),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
@@ -295,13 +295,13 @@ class NovaCardsController extends Controller
|
||||
|
||||
return view('cards.index', [
|
||||
'meta' => [
|
||||
'title' => 'Editorial Picks - Nova Cards - Skinbase Nova',
|
||||
'description' => 'Browse editorial Nova Cards picks, featured collections, and highlighted challenges.',
|
||||
'title' => 'Editorial Picks - Cards - Skinbase',
|
||||
'description' => 'Browse editorial Cards picks, featured collections, and highlighted challenges.',
|
||||
'canonical' => route('cards.editorial'),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
'heading' => 'Editorial picks',
|
||||
'subheading' => 'Curated Nova Cards, featured collections, and standout challenge surfaces chosen for quality and cohesion.',
|
||||
'subheading' => 'Curated Cards, featured collections, and standout challenge surfaces chosen for quality and cohesion.',
|
||||
'cards' => $this->presenter->cards($cards->items(), false, $request->user()),
|
||||
'pagination' => $cards,
|
||||
'featuredCards' => [],
|
||||
@@ -329,13 +329,13 @@ class NovaCardsController extends Controller
|
||||
|
||||
return view('cards.index', [
|
||||
'meta' => [
|
||||
'title' => 'Seasonal Cards - Nova Cards - Skinbase Nova',
|
||||
'description' => 'Browse seasonal and event-aware Nova Cards grouped by recurring moods, holidays, and time-of-year themes.',
|
||||
'title' => 'Seasonal Cards - Cards - Skinbase',
|
||||
'description' => 'Browse seasonal and event-aware Cards grouped by recurring moods, holidays, and time-of-year themes.',
|
||||
'canonical' => route('cards.seasonal'),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
'heading' => 'Seasonal cards',
|
||||
'subheading' => 'Discover Nova Cards grouped by recurring seasonal and campaign-style themes.',
|
||||
'subheading' => 'Discover Cards grouped by recurring seasonal and campaign-style themes.',
|
||||
'cards' => $this->presenter->cards($cards->items(), false, $request->user()),
|
||||
'pagination' => $cards,
|
||||
'featuredCards' => [],
|
||||
@@ -363,13 +363,13 @@ class NovaCardsController extends Controller
|
||||
|
||||
return view('cards.challenges', [
|
||||
'meta' => [
|
||||
'title' => 'Card Challenges - Skinbase Nova',
|
||||
'description' => 'Browse active and completed Nova Cards challenges, prompts, and winners.',
|
||||
'title' => 'Card Challenges - Skinbase',
|
||||
'description' => 'Browse active and completed Cards challenges, prompts, and winners.',
|
||||
'canonical' => route('cards.challenges'),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
'heading' => 'Card challenges',
|
||||
'subheading' => 'Official prompts and community challenge runs for Nova Cards creators.',
|
||||
'subheading' => 'Official prompts and community challenge runs for Cards creators.',
|
||||
'challenges' => $challenges,
|
||||
]);
|
||||
}
|
||||
@@ -388,8 +388,8 @@ class NovaCardsController extends Controller
|
||||
|
||||
return view('cards.challenges', [
|
||||
'meta' => [
|
||||
'title' => $challenge->title . ' - Skinbase Nova',
|
||||
'description' => $challenge->description ?: 'Browse entries for this Nova Cards challenge.',
|
||||
'title' => $challenge->title . ' - Skinbase',
|
||||
'description' => $challenge->description ?: 'Browse entries for this Cards challenge.',
|
||||
'canonical' => route('cards.challenges.show', ['slug' => $challenge->slug]),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
@@ -410,8 +410,8 @@ class NovaCardsController extends Controller
|
||||
{
|
||||
return view('cards.resources', [
|
||||
'meta' => [
|
||||
'title' => 'Template Packs - Skinbase Nova',
|
||||
'description' => 'Browse official Nova Cards template packs and starting points.',
|
||||
'title' => 'Template Packs - Skinbase',
|
||||
'description' => 'Browse official Cards template packs and starting points.',
|
||||
'canonical' => route('cards.templates'),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
@@ -427,13 +427,13 @@ class NovaCardsController extends Controller
|
||||
{
|
||||
return view('cards.resources', [
|
||||
'meta' => [
|
||||
'title' => 'Asset Packs - Skinbase Nova',
|
||||
'description' => 'Browse official Nova Cards asset packs for decorative and editorial layouts.',
|
||||
'title' => 'Asset Packs - Skinbase',
|
||||
'description' => 'Browse official Cards asset packs for decorative and editorial layouts.',
|
||||
'canonical' => route('cards.assets'),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
'heading' => 'Asset packs',
|
||||
'subheading' => 'Official decorative and editorial pack sets for the Nova Cards v2 editor.',
|
||||
'subheading' => 'Official decorative and editorial pack sets for the Cards v2 editor.',
|
||||
'packs' => collect($this->presenter->options()['asset_packs'] ?? []),
|
||||
'templates' => collect(),
|
||||
'resourceType' => 'asset',
|
||||
@@ -447,8 +447,8 @@ class NovaCardsController extends Controller
|
||||
|
||||
return view('cards.index', [
|
||||
'meta' => [
|
||||
'title' => '#' . $tag->name . ' Cards - Skinbase Nova',
|
||||
'description' => 'Browse Nova Cards tagged with #' . $tag->name . ' on Skinbase Nova.',
|
||||
'title' => '#' . $tag->name . ' Cards - Skinbase',
|
||||
'description' => 'Browse Cards tagged with #' . $tag->name . ' on Skinbase.',
|
||||
'canonical' => route('cards.tag', ['tagSlug' => $tag->slug]),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
@@ -480,13 +480,13 @@ class NovaCardsController extends Controller
|
||||
|
||||
return view('cards.index', [
|
||||
'meta' => [
|
||||
'title' => $mood['label'] . ' Mood Cards - Skinbase Nova',
|
||||
'description' => 'Browse Nova Cards grouped into the ' . strtolower((string) $mood['label']) . ' mood family on Skinbase Nova.',
|
||||
'title' => $mood['label'] . ' Mood Cards - Skinbase',
|
||||
'description' => 'Browse Cards grouped into the ' . strtolower((string) $mood['label']) . ' mood family on Skinbase.',
|
||||
'canonical' => route('cards.mood', ['moodSlug' => $mood['key']]),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
'heading' => $mood['label'],
|
||||
'subheading' => 'Discover Nova Cards grouped by a curated mood family using durable tag mappings.',
|
||||
'subheading' => 'Discover Cards grouped by a curated mood family using durable tag mappings.',
|
||||
'cards' => $this->presenter->cards($cards->items(), false, $request->user()),
|
||||
'pagination' => $cards,
|
||||
'featuredCards' => [],
|
||||
@@ -514,13 +514,13 @@ class NovaCardsController extends Controller
|
||||
|
||||
return view('cards.index', [
|
||||
'meta' => [
|
||||
'title' => $style['label'] . ' Style Cards - Skinbase Nova',
|
||||
'description' => 'Browse Nova Cards using the ' . strtolower((string) $style['label']) . ' style family on Skinbase Nova.',
|
||||
'title' => $style['label'] . ' Style Cards - Skinbase',
|
||||
'description' => 'Browse Cards using the ' . strtolower((string) $style['label']) . ' style family on Skinbase.',
|
||||
'canonical' => route('cards.style', ['styleSlug' => $style['key']]),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
'heading' => $style['label'],
|
||||
'subheading' => 'Discover Nova Cards grouped by a shared visual style family.',
|
||||
'subheading' => 'Discover Cards grouped by a shared visual style family.',
|
||||
'cards' => $this->presenter->cards($cards->items(), false, $request->user()),
|
||||
'pagination' => $cards,
|
||||
'featuredCards' => [],
|
||||
@@ -548,13 +548,13 @@ class NovaCardsController extends Controller
|
||||
|
||||
return view('cards.index', [
|
||||
'meta' => [
|
||||
'title' => $palette['label'] . ' Palette Cards - Skinbase Nova',
|
||||
'description' => 'Browse Nova Cards using the ' . strtolower((string) $palette['label']) . ' palette family on Skinbase Nova.',
|
||||
'title' => $palette['label'] . ' Palette Cards - Skinbase',
|
||||
'description' => 'Browse Cards using the ' . strtolower((string) $palette['label']) . ' palette family on Skinbase.',
|
||||
'canonical' => route('cards.palette', ['paletteSlug' => $palette['key']]),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
'heading' => $palette['label'],
|
||||
'subheading' => 'Discover Nova Cards grouped by shared palette families and color direction.',
|
||||
'subheading' => 'Discover Cards grouped by shared palette families and color direction.',
|
||||
'cards' => $this->presenter->cards($cards->items(), false, $request->user()),
|
||||
'pagination' => $cards,
|
||||
'featuredCards' => [],
|
||||
@@ -580,8 +580,8 @@ class NovaCardsController extends Controller
|
||||
|
||||
return view('cards.index', array_merge($this->creatorPagePayload($request, $user), [
|
||||
'meta' => [
|
||||
'title' => '@' . $user->username . ' Cards - Skinbase Nova',
|
||||
'description' => 'Browse Nova Cards created by @' . $user->username . ' on Skinbase Nova.',
|
||||
'title' => '@' . $user->username . ' Cards - Skinbase',
|
||||
'description' => 'Browse Cards created by @' . $user->username . ' on Skinbase.',
|
||||
'canonical' => route('cards.creator', ['username' => strtolower((string) $user->username)]),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
@@ -602,13 +602,13 @@ class NovaCardsController extends Controller
|
||||
|
||||
return view('cards.index', array_merge($this->creatorPagePayload($request, $user), [
|
||||
'meta' => [
|
||||
'title' => '@' . $user->username . ' Portfolio - Skinbase Nova',
|
||||
'description' => 'Browse the dedicated Nova Cards portfolio page for @' . $user->username . ' on Skinbase Nova.',
|
||||
'title' => '@' . $user->username . ' Portfolio - Skinbase',
|
||||
'description' => 'Browse the dedicated Cards portfolio page for @' . $user->username . ' on Skinbase.',
|
||||
'canonical' => route('cards.creator.portfolio', ['username' => strtolower((string) $user->username)]),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
'heading' => '@' . $user->username . ' Portfolio',
|
||||
'subheading' => 'A dedicated Nova Cards portfolio view for ' . ($user->name ?: '@' . $user->username) . '.',
|
||||
'subheading' => 'A dedicated Cards portfolio view for ' . ($user->name ?: '@' . $user->username) . '.',
|
||||
'context' => 'creator-portfolio',
|
||||
]));
|
||||
}
|
||||
@@ -695,8 +695,8 @@ class NovaCardsController extends Controller
|
||||
|
||||
return view('cards.collection', [
|
||||
'meta' => [
|
||||
'title' => $collection->name . ' - Nova Cards Collection - Skinbase Nova',
|
||||
'description' => $collection->description ?: 'Browse this curated Nova Cards collection.',
|
||||
'title' => $collection->name . ' - Cards Collection - Skinbase',
|
||||
'description' => $collection->description ?: 'Browse this curated Cards collection.',
|
||||
'canonical' => route('cards.collections.show', ['slug' => $collection->slug, 'id' => $collection->id]),
|
||||
'robots' => 'index,follow',
|
||||
],
|
||||
@@ -721,7 +721,7 @@ class NovaCardsController extends Controller
|
||||
|
||||
return view('cards.lineage', [
|
||||
'meta' => [
|
||||
'title' => $card->title . ' Lineage - Nova Cards - Skinbase Nova',
|
||||
'title' => $card->title . ' Lineage - Cards - Skinbase',
|
||||
'description' => 'Browse the remix lineage and related variants for this Nova Card.',
|
||||
'canonical' => route('cards.lineage', ['slug' => $card->slug, 'id' => $card->id]),
|
||||
'robots' => 'index,follow',
|
||||
@@ -767,7 +767,7 @@ class NovaCardsController extends Controller
|
||||
return view('cards.show', [
|
||||
'card' => $this->presenter->card($card, true, $request->user()),
|
||||
'meta' => [
|
||||
'title' => $card->title . ' - Nova Cards - Skinbase Nova',
|
||||
'title' => $card->title . ' - Cards - Skinbase',
|
||||
'description' => $card->description ?: $card->quote_text,
|
||||
'canonical' => route('cards.show', ['slug' => $card->slug, 'id' => $card->id]),
|
||||
'robots' => $card->visibility === NovaCard::VISIBILITY_PUBLIC ? 'index,follow' : 'noindex,follow',
|
||||
|
||||
@@ -18,7 +18,7 @@ final class ProfileHelpPageController extends Controller
|
||||
$seo = app(SeoFactory::class)
|
||||
->collectionPage(
|
||||
'Profile Help — Skinbase',
|
||||
'Learn how profiles work on Skinbase Nova, how they differ from Groups, and how to build a stronger personal identity with better setup, presentation, and creator-facing profile habits.',
|
||||
'Learn how profiles work on Skinbase, how they differ from Groups, and how to build a stronger personal identity with better setup, presentation, and creator-facing profile habits.',
|
||||
$canonical,
|
||||
)
|
||||
->toArray();
|
||||
|
||||
@@ -18,7 +18,7 @@ final class StudioHelpPageController extends Controller
|
||||
$seo = app(SeoFactory::class)
|
||||
->collectionPage(
|
||||
'Studio Help — Skinbase',
|
||||
'Learn how Studio works on Skinbase Nova, including drafts, publishing, personal versus Group context, artworks, cards, collections, and collaboration workflows.',
|
||||
'Learn how Studio works on Skinbase, including drafts, publishing, personal versus Group context, artworks, cards, collections, and collaboration workflows.',
|
||||
$canonical,
|
||||
)
|
||||
->toArray();
|
||||
@@ -27,7 +27,7 @@ final class StudioHelpPageController extends Controller
|
||||
|
||||
return Inertia::render('Help/StudioHelpPage', [
|
||||
'title' => 'Studio Help',
|
||||
'description' => 'Understand Studio as the creative control center of Skinbase Nova, with guidance for drafts, publishing, artworks, cards, collections, and Group workflows.',
|
||||
'description' => 'Understand Studio as the creative control center of Skinbase, with guidance for drafts, publishing, artworks, cards, collections, and Group workflows.',
|
||||
'seo' => $seo,
|
||||
'links' => [
|
||||
'help_home' => route('help'),
|
||||
|
||||
@@ -18,7 +18,7 @@ final class TroubleshootingHelpPageController extends Controller
|
||||
$seo = app(SeoFactory::class)
|
||||
->collectionPage(
|
||||
'Troubleshooting Help — Skinbase',
|
||||
'Use fast, support-oriented troubleshooting guidance for login issues, permissions confusion, publishing blockers, profile setup problems, and bug-report escalation on Skinbase Nova.',
|
||||
'Use fast, support-oriented troubleshooting guidance for login issues, permissions confusion, publishing blockers, profile setup problems, and bug-report escalation on Skinbase.',
|
||||
$canonical,
|
||||
)
|
||||
->toArray();
|
||||
|
||||
@@ -18,7 +18,7 @@ final class UploadHelpPageController extends Controller
|
||||
$seo = app(SeoFactory::class)
|
||||
->collectionPage(
|
||||
'Upload Help — Skinbase',
|
||||
'Learn how uploading works on Skinbase Nova, including draft creation, metadata review, previews, personal versus Group context, contributor credit, publishing, and troubleshooting.',
|
||||
'Learn how uploading works on Skinbase, including draft creation, metadata review, previews, personal versus Group context, contributor credit, publishing, and troubleshooting.',
|
||||
$canonical,
|
||||
)
|
||||
->toArray();
|
||||
@@ -27,7 +27,7 @@ final class UploadHelpPageController extends Controller
|
||||
|
||||
return Inertia::render('Help/UploadHelpPage', [
|
||||
'title' => 'Upload Help',
|
||||
'description' => 'Understand the full upload workflow on Skinbase Nova, from file submission and draft creation to metadata review, contributor credit, and final publish.',
|
||||
'description' => 'Understand the full upload workflow on Skinbase, from file submission and draft creation to metadata review, contributor credit, and final publish.',
|
||||
'seo' => $seo,
|
||||
'links' => [
|
||||
'help_home' => route('help'),
|
||||
|
||||
@@ -22,7 +22,7 @@ final class WorldController extends Controller
|
||||
{
|
||||
$payload = $this->worlds->publicIndexPayload($request->user());
|
||||
$seo = app(SeoFactory::class)->collectionListing(
|
||||
'Worlds — Skinbase Nova',
|
||||
'Worlds — Skinbase',
|
||||
$payload['description'],
|
||||
route('worlds.index'),
|
||||
)->toArray();
|
||||
@@ -45,8 +45,8 @@ final class WorldController extends Controller
|
||||
|
||||
$payload = $this->worlds->publicShowPayload($resolvedWorld, $request->user());
|
||||
$seo = app(SeoFactory::class)->collectionPage(
|
||||
$resolvedWorld->seo_title ?: ($resolvedWorld->title . ' — Skinbase Nova'),
|
||||
$resolvedWorld->seo_description ?: ($resolvedWorld->summary ?: $resolvedWorld->description ?: 'Seasonal and editorial discovery world on Skinbase Nova.'),
|
||||
$resolvedWorld->seo_title ?: ($resolvedWorld->title . ' — Skinbase'),
|
||||
$resolvedWorld->seo_description ?: ($resolvedWorld->summary ?: $resolvedWorld->description ?: 'Seasonal and editorial discovery world on Skinbase.'),
|
||||
$this->worlds->canonicalPublicUrl($resolvedWorld),
|
||||
$resolvedWorld->ogImageUrl(),
|
||||
)->toArray();
|
||||
@@ -69,8 +69,8 @@ final class WorldController extends Controller
|
||||
|
||||
$payload = $this->worlds->publicShowPayload($resolvedWorld, $request->user());
|
||||
$seo = app(SeoFactory::class)->collectionPage(
|
||||
$resolvedWorld->seo_title ?: ($resolvedWorld->title . ' — Skinbase Nova'),
|
||||
$resolvedWorld->seo_description ?: ($resolvedWorld->summary ?: $resolvedWorld->description ?: 'Seasonal and editorial discovery world on Skinbase Nova.'),
|
||||
$resolvedWorld->seo_title ?: ($resolvedWorld->title . ' — Skinbase'),
|
||||
$resolvedWorld->seo_description ?: ($resolvedWorld->summary ?: $resolvedWorld->description ?: 'Seasonal and editorial discovery world on Skinbase.'),
|
||||
$this->worlds->canonicalPublicUrl($resolvedWorld),
|
||||
$resolvedWorld->ogImageUrl(),
|
||||
)->toArray();
|
||||
|
||||
@@ -18,7 +18,7 @@ final class WorldsHelpPageController extends Controller
|
||||
$seo = app(SeoFactory::class)
|
||||
->collectionPage(
|
||||
'Worlds Help — Skinbase',
|
||||
'Learn how Worlds work on Skinbase Nova, including editorial purpose, attached content, section control, preview, publishing, recurrence, and homepage promotion.',
|
||||
'Learn how Worlds work on Skinbase, including editorial purpose, attached content, section control, preview, publishing, recurrence, and homepage promotion.',
|
||||
$canonical,
|
||||
)
|
||||
->toArray();
|
||||
@@ -27,7 +27,7 @@ final class WorldsHelpPageController extends Controller
|
||||
|
||||
return Inertia::render('Help/WorldsHelpPage', [
|
||||
'title' => 'Worlds Help',
|
||||
'description' => 'A complete guide to creating, attaching content to, previewing, and publishing Worlds on Skinbase Nova.',
|
||||
'description' => 'A complete guide to creating, attaching content to, previewing, and publishing Worlds on Skinbase.',
|
||||
'seo' => $seo,
|
||||
'links' => [
|
||||
'help_home' => route('help'),
|
||||
|
||||
@@ -48,7 +48,7 @@ final class GenerateArtworkEmbeddingJob implements ShouldQueue
|
||||
public function handle(
|
||||
ArtworkEmbeddingClient $client,
|
||||
ArtworkVisionImageUrl $imageUrlBuilder,
|
||||
VectorService|ArtworkVectorIndexService $vectors,
|
||||
ArtworkVectorIndexService $vectors,
|
||||
): void
|
||||
{
|
||||
if (! (bool) config('recommendations.embedding.enabled', true)) {
|
||||
@@ -128,7 +128,7 @@ final class GenerateArtworkEmbeddingJob implements ShouldQueue
|
||||
}
|
||||
|
||||
private function upsertVectorIndex(
|
||||
VectorService|ArtworkVectorIndexService $vectors,
|
||||
ArtworkVectorIndexService $vectors,
|
||||
Artwork $artwork
|
||||
): void
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@ final class AiBiographyPromptBuilder
|
||||
private const MIN_WORDS = 30;
|
||||
|
||||
private const SYSTEM_PROMPT = <<<'PROMPT'
|
||||
You are a concise writing assistant for Skinbase Nova, a digital art platform.
|
||||
You are a concise writing assistant for Skinbase, a digital art platform.
|
||||
|
||||
Write short creator biographies using only the facts provided. Use a polished, factual, and slightly editorial tone.
|
||||
|
||||
@@ -44,7 +44,7 @@ Rules:
|
||||
PROMPT;
|
||||
|
||||
private const SYSTEM_PROMPT_STRICT = <<<'PROMPT'
|
||||
You are a cautious writing assistant for Skinbase Nova, a digital art platform.
|
||||
You are a cautious writing assistant for Skinbase, a digital art platform.
|
||||
|
||||
Write a short, safe creator biography using only the facts provided. Be conservative.
|
||||
|
||||
@@ -59,7 +59,7 @@ Rules:
|
||||
PROMPT;
|
||||
|
||||
private const SYSTEM_PROMPT_SPARSE = <<<'PROMPT'
|
||||
You are a cautious writing assistant for Skinbase Nova, a digital art platform.
|
||||
You are a cautious writing assistant for Skinbase, a digital art platform.
|
||||
|
||||
Write a short, modest creator introduction using only the facts provided.
|
||||
|
||||
@@ -75,7 +75,7 @@ Rules:
|
||||
PROMPT;
|
||||
|
||||
private const SYSTEM_PROMPT_SPARSE_STRICT = <<<'PROMPT'
|
||||
You are a cautious writing assistant for Skinbase Nova, a digital art platform.
|
||||
You are a cautious writing assistant for Skinbase, a digital art platform.
|
||||
|
||||
Write a short, modest creator introduction using only the facts provided. Be conservative and precise.
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ class CollectionAiCurationService
|
||||
);
|
||||
|
||||
$seo = sprintf(
|
||||
'%s on Skinbase Nova: %d curated artworks%s.',
|
||||
'%s on Skinbase: %d curated artworks%s.',
|
||||
$this->draftString($collection, $draft, 'title') ?: $collection->title,
|
||||
$context['artworks_count'],
|
||||
$context['theme_sentence'] !== '' ? ' exploring ' . $context['theme_sentence'] : ''
|
||||
|
||||
@@ -238,7 +238,7 @@ final class ArtworkSquareThumbnailBackfillService
|
||||
'timeout' => 30,
|
||||
'ignore_errors' => true,
|
||||
'header' => implode("\r\n", [
|
||||
'User-Agent: Skinbase Nova square-thumb backfill',
|
||||
'User-Agent: Skinbase square-thumb backfill',
|
||||
'Accept: image/*,*/*;q=0.8',
|
||||
'Accept-Encoding: identity',
|
||||
'Connection: close',
|
||||
|
||||
@@ -9,7 +9,7 @@ use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
/**
|
||||
* ArtworkRankingService — Skinbase Nova Ranking Engine V2
|
||||
* ArtworkRankingService — Skinbase Ranking Engine V2
|
||||
*
|
||||
* Intelligent scoring system combining:
|
||||
* 1. Base engagement (views, downloads, favourites, comments, shares)
|
||||
|
||||
@@ -11,7 +11,7 @@ use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* RankingService — Skinbase Nova rank_v2
|
||||
* RankingService — Skinbase rank_v2
|
||||
*
|
||||
* Responsibilities:
|
||||
* 1. Score computation — turn raw artwork signals into three float scores.
|
||||
|
||||
@@ -33,7 +33,7 @@ final class GoogleNewsSitemapBuilder extends AbstractSitemapBuilder
|
||||
route('news.show', ['slug' => $article->slug]),
|
||||
trim((string) $article->title),
|
||||
$article->published_at,
|
||||
(string) \config('sitemaps.news.google_publication_name', 'Skinbase Nova'),
|
||||
(string) \config('sitemaps.news.google_publication_name', 'Skinbase'),
|
||||
(string) \config('sitemaps.news.google_language', 'en'),
|
||||
);
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user