Implement creator studio and upload updates
This commit is contained in:
@@ -5,31 +5,37 @@
|
||||
|
||||
@php
|
||||
$hero_title = $post->title;
|
||||
$seo = \App\Support\Seo\SeoDataBuilder::fromArray(
|
||||
app(\App\Support\Seo\SeoFactory::class)->fromViewData(get_defined_vars())
|
||||
)
|
||||
->og(
|
||||
type: 'article',
|
||||
title: $post->meta_title ?: $post->title,
|
||||
description: $post->meta_description ?: $post->excerpt ?: '',
|
||||
url: $post->url,
|
||||
image: $post->featured_image,
|
||||
)
|
||||
->addJsonLd([
|
||||
'@context' => 'https://schema.org',
|
||||
'@type' => 'Article',
|
||||
'headline' => $post->title,
|
||||
'datePublished' => $post->published_at?->toIso8601String(),
|
||||
'dateModified' => $post->updated_at?->toIso8601String(),
|
||||
'author' => [
|
||||
'@type' => 'Organization',
|
||||
'name' => 'Skinbase',
|
||||
],
|
||||
'publisher' => [
|
||||
'@type' => 'Organization',
|
||||
'name' => 'Skinbase',
|
||||
],
|
||||
'description' => $post->meta_description ?: $post->excerpt ?: '',
|
||||
'mainEntityOfPage' => $post->url,
|
||||
'image' => $post->featured_image,
|
||||
])
|
||||
->build();
|
||||
@endphp
|
||||
|
||||
@push('head')
|
||||
{{-- Article structured data --}}
|
||||
<script type="application/ld+json">
|
||||
{!! json_encode([
|
||||
'@context' => 'https://schema.org',
|
||||
'@type' => 'Article',
|
||||
'headline' => $post->title,
|
||||
'datePublished' => $post->published_at?->toIso8601String(),
|
||||
'dateModified' => $post->updated_at?->toIso8601String(),
|
||||
'author' => [
|
||||
'@type' => 'Organization',
|
||||
'name' => 'Skinbase',
|
||||
],
|
||||
'publisher' => [
|
||||
'@type' => 'Organization',
|
||||
'name' => 'Skinbase',
|
||||
],
|
||||
'description' => $post->meta_description ?: $post->excerpt ?: '',
|
||||
'mainEntityOfPage' => $post->url,
|
||||
], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) !!}
|
||||
</script>
|
||||
@endpush
|
||||
|
||||
@section('page-content')
|
||||
|
||||
<article class="max-w-3xl">
|
||||
|
||||
@@ -1,16 +1,6 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@push('head')
|
||||
<link rel="canonical" href="{{ $page_canonical ?? url('/categories') }}">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:site_name" content="Skinbase">
|
||||
<meta property="og:title" content="{{ $page_title ?? 'Categories' }}">
|
||||
<meta property="og:description" content="{{ $page_meta_description ?? '' }}">
|
||||
<meta property="og:url" content="{{ $page_canonical ?? url('/categories') }}">
|
||||
@if(!empty($structured_data ?? null))
|
||||
<script type="application/ld+json">{!! json_encode($structured_data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_TAG) !!}</script>
|
||||
@endif
|
||||
@endpush
|
||||
@php($useUnifiedSeo = true)
|
||||
|
||||
@section('main-class', '')
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
@php
|
||||
use Illuminate\Support\Str;
|
||||
use App\Banner;
|
||||
$useUnifiedSeo = true;
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@php
|
||||
@php
|
||||
$page_title = $page_title ?? 'Community Activity';
|
||||
$page_meta_description = 'Track comments, replies, reactions, and mentions from across the Skinbase community in one live feed.';
|
||||
$page_canonical = route('community.activity', array_filter([
|
||||
'filter' => ($initialFilter ?? null) && ($initialFilter ?? 'all') !== 'all' ? $initialFilter : null,
|
||||
'user_id' => $initialUserId ?? null,
|
||||
], fn (mixed $value): bool => $value !== null && $value !== ''));
|
||||
$useUnifiedSeo = true;
|
||||
$headerBreadcrumbs = collect([
|
||||
(object) ['name' => $page_title ?? 'Community Activity', 'url' => route('community.activity')],
|
||||
(object) ['name' => $page_title, 'url' => $page_canonical],
|
||||
]);
|
||||
$breadcrumbs = $headerBreadcrumbs;
|
||||
$seo = \App\Support\Seo\SeoDataBuilder::fromArray(
|
||||
app(\App\Support\Seo\SeoFactory::class)->fromViewData(get_defined_vars())
|
||||
)->build();
|
||||
|
||||
$initialFilterLabel = match (($initialFilter ?? 'all')) {
|
||||
'comments' => 'Comments',
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@php
|
||||
$page_title = $page_title ?? 'Monthly Top Commentators';
|
||||
$page_meta_description = 'Members who posted the most comments in the last 30 days.';
|
||||
$page_canonical = route('comments.monthly', request()->query());
|
||||
$useUnifiedSeo = true;
|
||||
$headerBreadcrumbs = collect([
|
||||
(object) ['name' => $page_title ?? 'Monthly Top Commentators', 'url' => route('comments.monthly')],
|
||||
(object) ['name' => $page_title, 'url' => $page_canonical],
|
||||
]);
|
||||
$breadcrumbs = $headerBreadcrumbs;
|
||||
$seo = \App\Support\Seo\SeoDataBuilder::fromArray(
|
||||
app(\App\Support\Seo\SeoFactory::class)->fromViewData(get_defined_vars())
|
||||
)->build();
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@php
|
||||
$page_title = $page_title ?? 'Daily Uploads';
|
||||
$page_meta_description = 'Browse public artworks grouped by upload date across the last two weeks on Skinbase.';
|
||||
$page_canonical = route('uploads.daily', request()->query());
|
||||
$useUnifiedSeo = true;
|
||||
$headerBreadcrumbs = collect([
|
||||
(object) ['name' => $page_title ?? 'Daily Uploads', 'url' => route('uploads.daily')],
|
||||
(object) ['name' => $page_title, 'url' => $page_canonical],
|
||||
]);
|
||||
$breadcrumbs = $headerBreadcrumbs;
|
||||
$seo = \App\Support\Seo\SeoDataBuilder::fromArray(
|
||||
app(\App\Support\Seo\SeoFactory::class)->fromViewData(get_defined_vars())
|
||||
)->build();
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@php
|
||||
$page_title = $page_title ?? 'Most Downloaded Today';
|
||||
$page_meta_description = 'Browse the artworks downloaded the most today on Skinbase.';
|
||||
$page_canonical = route('downloads.today', request()->query());
|
||||
$gallery_type = 'today-downloads';
|
||||
$useUnifiedSeo = true;
|
||||
$headerBreadcrumbs = collect([
|
||||
(object) ['name' => $page_title ?? 'Most Downloaded Today', 'url' => route('downloads.today')],
|
||||
(object) ['name' => $page_title, 'url' => $page_canonical],
|
||||
]);
|
||||
$breadcrumbs = $headerBreadcrumbs;
|
||||
$galleryArtworks = collect($artworks->items())->map(fn ($art) => [
|
||||
'id' => $art->id,
|
||||
'name' => $art->name ?? null,
|
||||
@@ -26,6 +32,9 @@
|
||||
] : null,
|
||||
])->values();
|
||||
$galleryNextPageUrl = $artworks->nextPageUrl();
|
||||
$seo = \App\Support\Seo\SeoDataBuilder::fromArray(
|
||||
app(\App\Support\Seo\SeoFactory::class)->fromViewData(get_defined_vars())
|
||||
)->build();
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@php
|
||||
$page_title = $page_title ?? 'Featured Artworks';
|
||||
$page_meta_description = 'Browse staff-picked and community-highlighted artwork in the shared gallery feed.';
|
||||
$page_canonical = request()->fullUrl();
|
||||
$gallery_type = 'featured';
|
||||
$useUnifiedSeo = true;
|
||||
$featuredBreadcrumbs = collect([
|
||||
(object) ['name' => 'Featured', 'url' => request()->path()],
|
||||
(object) ['name' => $page_title ?? 'Featured Artworks', 'url' => request()->fullUrl()],
|
||||
(object) ['name' => $page_title, 'url' => $page_canonical],
|
||||
]);
|
||||
$breadcrumbs = $featuredBreadcrumbs;
|
||||
|
||||
$galleryArtworks = collect($artworks->items())->map(fn ($art) => [
|
||||
'id' => $art->id,
|
||||
@@ -24,6 +30,9 @@
|
||||
])->values();
|
||||
|
||||
$galleryNextPageUrl = $artworks->nextPageUrl();
|
||||
$seo = \App\Support\Seo\SeoDataBuilder::fromArray(
|
||||
app(\App\Support\Seo\SeoFactory::class)->fromViewData(get_defined_vars())
|
||||
)->build();
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
|
||||
@@ -1,48 +1,8 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('meta-description', $meta['description'])
|
||||
@section('meta-keywords', $meta['keywords'])
|
||||
@php($useUnifiedSeo = true)
|
||||
|
||||
@push('head')
|
||||
<title>{{ $meta['title'] }}</title>
|
||||
<link rel="canonical" href="{{ $meta['canonical'] }}">
|
||||
|
||||
{{-- Open Graph --}}
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:site_name" content="Skinbase">
|
||||
<meta property="og:title" content="{{ $meta['title'] }}">
|
||||
<meta property="og:description" content="{{ $meta['description'] }}">
|
||||
<meta property="og:url" content="{{ $meta['canonical'] }}">
|
||||
@if(!empty($meta['og_image']))
|
||||
<meta property="og:image" content="{{ $meta['og_image'] }}">
|
||||
<meta property="og:image:type" content="image/webp">
|
||||
@endif
|
||||
|
||||
{{-- Twitter --}}
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:title" content="{{ $meta['title'] }}">
|
||||
<meta name="twitter:description" content="{{ $meta['description'] }}">
|
||||
@if(!empty($meta['og_image']))
|
||||
<meta name="twitter:image" content="{{ $meta['og_image'] }}">
|
||||
@endif
|
||||
|
||||
{{-- JSON-LD WebSite schema --}}
|
||||
@php
|
||||
$websiteSchema = [
|
||||
'@context' => 'https://schema.org',
|
||||
'@type' => 'WebSite',
|
||||
'name' => 'Skinbase',
|
||||
'url' => url('/'),
|
||||
'description' => $meta['description'],
|
||||
'potentialAction' => [
|
||||
'@type' => 'SearchAction',
|
||||
'target' => url('/search') . '?q={search_term_string}',
|
||||
'query-input' => 'required name=search_term_string',
|
||||
],
|
||||
];
|
||||
@endphp
|
||||
<script type="application/ld+json">{!! json_encode($websiteSchema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_TAG) !!}</script>
|
||||
|
||||
{{-- Preload hero image for faster LCP --}}
|
||||
@if(!empty($props['hero']['thumb_lg']))
|
||||
<link rel="preload" as="image" href="{{ $props['hero']['thumb_lg'] }}">
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@php
|
||||
$page_title = $page_title ?? 'Member Photos';
|
||||
$page_meta_description = 'Artwork submitted by the Skinbase community, presented in the shared Nova gallery feed.';
|
||||
$page_canonical = route('members.photos', request()->query());
|
||||
$gallery_type = 'member-photos';
|
||||
$useUnifiedSeo = true;
|
||||
$memberPhotoBreadcrumbs = collect([
|
||||
(object) ['name' => 'Members', 'url' => route('creators.top')],
|
||||
(object) ['name' => $page_title ?? 'Member Photos', 'url' => route('members.photos')],
|
||||
(object) ['name' => $page_title, 'url' => $page_canonical],
|
||||
]);
|
||||
$breadcrumbs = $memberPhotoBreadcrumbs;
|
||||
$memberPhotoItems = collect(method_exists($artworks ?? null, 'items') ? $artworks->items() : ($artworks ?? []));
|
||||
$memberPhotoGallery = $memberPhotoItems->map(fn ($art) => [
|
||||
'id' => $art->id ?? null,
|
||||
@@ -28,6 +34,9 @@
|
||||
: null,
|
||||
]);
|
||||
$memberPhotosNextPageUrl = method_exists($artworks ?? null, 'nextPageUrl') ? $artworks->nextPageUrl() : null;
|
||||
$seo = \App\Support\Seo\SeoDataBuilder::fromArray(
|
||||
app(\App\Support\Seo\SeoFactory::class)->fromViewData(get_defined_vars())
|
||||
)->build();
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
@php
|
||||
$useUnifiedSeo = true;
|
||||
$seo = \App\Support\Seo\SeoDataBuilder::fromArray(
|
||||
app(\App\Support\Seo\SeoFactory::class)->fromViewData(get_defined_vars())
|
||||
)
|
||||
->addJsonLd([
|
||||
'@context' => 'https://schema.org',
|
||||
'@type' => 'CollectionPage',
|
||||
'name' => $page_title,
|
||||
'description' => $page_meta_description,
|
||||
'url' => $page_canonical,
|
||||
])
|
||||
->build();
|
||||
@endphp
|
||||
@extends('layouts.nova')
|
||||
|
||||
@section('content')
|
||||
|
||||
@@ -2,36 +2,27 @@
|
||||
|
||||
@php
|
||||
$storySummary = $story->excerpt ?: \Illuminate\Support\Str::limit(trim(strip_tags($safeContent)), 160);
|
||||
@endphp
|
||||
|
||||
@push('head')
|
||||
@php
|
||||
$storyUrl = $story->canonical_url ?: route('stories.show', ['slug' => $story->slug]);
|
||||
$creatorName = $story->creator?->display_name ?: $story->creator?->username ?: 'Unknown creator';
|
||||
$metaDescription = $story->meta_description ?: $storySummary;
|
||||
$metaTitle = $story->meta_title ?: $story->title;
|
||||
$ogImage = $story->og_image ?: $story->cover_url;
|
||||
$creatorFollowProps = $story->creator ? [
|
||||
'username' => $story->creator->username,
|
||||
'following' => (bool) ($storySocialProps['state']['is_following_creator'] ?? false),
|
||||
'followers_count' => (int) ($storySocialProps['creator']['followers_count'] ?? 0),
|
||||
] : null;
|
||||
@endphp
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:title" content="{{ $metaTitle }}" />
|
||||
<meta property="og:description" content="{{ $metaDescription }}" />
|
||||
<meta property="og:url" content="{{ $storyUrl }}" />
|
||||
@if($ogImage)
|
||||
<meta property="og:image" content="{{ $ogImage }}" />
|
||||
@endif
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content="{{ $metaTitle }}" />
|
||||
<meta name="twitter:description" content="{{ $metaDescription }}" />
|
||||
@if($ogImage)
|
||||
<meta name="twitter:image" content="{{ $ogImage }}" />
|
||||
@endif
|
||||
<script type="application/ld+json">
|
||||
{!! json_encode([
|
||||
$storyUrl = $story->canonical_url ?: route('stories.show', ['slug' => $story->slug]);
|
||||
$creatorName = $story->creator?->display_name ?: $story->creator?->username ?: 'Unknown creator';
|
||||
$metaDescription = $story->meta_description ?: $storySummary;
|
||||
$metaTitle = $story->meta_title ?: $story->title;
|
||||
$ogImage = $story->og_image ?: $story->cover_url;
|
||||
$creatorFollowProps = $story->creator ? [
|
||||
'username' => $story->creator->username,
|
||||
'following' => (bool) ($storySocialProps['state']['is_following_creator'] ?? false),
|
||||
'followers_count' => (int) ($storySocialProps['creator']['followers_count'] ?? 0),
|
||||
] : null;
|
||||
$seo = \App\Support\Seo\SeoDataBuilder::fromArray(
|
||||
app(\App\Support\Seo\SeoFactory::class)->fromViewData(get_defined_vars())
|
||||
)
|
||||
->og(
|
||||
type: 'article',
|
||||
title: $metaTitle,
|
||||
description: $metaDescription,
|
||||
url: $storyUrl,
|
||||
image: $ogImage,
|
||||
)
|
||||
->addJsonLd(array_filter([
|
||||
'@context' => 'https://schema.org',
|
||||
'@type' => 'Article',
|
||||
'headline' => $story->title,
|
||||
@@ -44,9 +35,9 @@
|
||||
'datePublished' => optional($story->published_at)->toIso8601String(),
|
||||
'dateModified' => optional($story->updated_at)->toIso8601String(),
|
||||
'mainEntityOfPage' => $storyUrl,
|
||||
], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) !!}
|
||||
</script>
|
||||
@endpush
|
||||
], fn (mixed $value): bool => $value !== null && $value !== ''))
|
||||
->build();
|
||||
@endphp
|
||||
|
||||
@section('page-hero')
|
||||
<div class="hidden" aria-hidden="true"></div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@php
|
||||
$useUnifiedSeo = true;
|
||||
$hero_title = 'Tags';
|
||||
$hero_description = 'Browse all artwork tags on Skinbase.';
|
||||
$breadcrumbs = $breadcrumbs ?? collect([
|
||||
@@ -9,18 +10,6 @@
|
||||
]);
|
||||
@endphp
|
||||
|
||||
@push('head')
|
||||
@isset($page_canonical)
|
||||
<link rel="canonical" href="{{ $page_canonical }}" />
|
||||
@endisset
|
||||
<meta name="robots" content="{{ $page_robots ?? 'index,follow' }}">
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="{{ $page_canonical ?? url()->current() }}" />
|
||||
<meta property="og:title" content="{{ $page_title ?? 'Skinbase' }}" />
|
||||
<meta property="og:description" content="{{ $page_meta_description ?? $hero_description }}" />
|
||||
<meta property="og:site_name" content="Skinbase" />
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
@php
|
||||
$query = trim((string) ($query ?? ''));
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
@extends('layouts.nova')
|
||||
|
||||
@php
|
||||
$page_title = $page_title ?? 'Latest Artworks';
|
||||
$page_meta_description = 'Fresh public uploads across skins, photography, wallpapers, and the rest of the Skinbase catalog.';
|
||||
$page_canonical = route('uploads.latest', request()->query());
|
||||
$gallery_type = 'latest-uploads';
|
||||
$useUnifiedSeo = true;
|
||||
$latestBreadcrumbs = collect([
|
||||
(object) ['name' => 'Uploads', 'url' => route('uploads.latest')],
|
||||
(object) ['name' => $page_title ?? 'Latest Artworks', 'url' => route('uploads.latest')],
|
||||
(object) ['name' => $page_title, 'url' => $page_canonical],
|
||||
]);
|
||||
$breadcrumbs = $latestBreadcrumbs;
|
||||
$cursorStateLabel = request()->filled('cursor') ? 'Browsing archive' : 'Latest slice';
|
||||
$cursorStateCopy = request()->filled('cursor')
|
||||
? 'You are viewing an older slice of the cursor-based feed.'
|
||||
@@ -29,6 +35,9 @@
|
||||
'url' => isset($art->id) ? '/art/' . $art->id . '/' . ($art->slug ?: \Illuminate\Support\Str::slug($art->name ?? 'artwork')) : '#',
|
||||
])->values();
|
||||
$galleryNextPageUrl = method_exists($artworks, 'nextPageUrl') ? $artworks->nextPageUrl() : null;
|
||||
$seo = \App\Support\Seo\SeoDataBuilder::fromArray(
|
||||
app(\App\Support\Seo\SeoFactory::class)->fromViewData(get_defined_vars())
|
||||
)->build();
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
|
||||
Reference in New Issue
Block a user