Refine SEO, uploads, and deploy handling

This commit is contained in:
2026-05-02 10:48:08 +02:00
parent b6be6ed2ac
commit a9dfa6ea11
97 changed files with 373 additions and 327 deletions

View File

@@ -6,7 +6,7 @@
->addJsonLd([
'@context' => 'https://schema.org',
'@type' => 'CollectionPage',
'name' => $meta['title'] ?? 'Nova Cards - Skinbase Nova',
'name' => $meta['title'] ?? 'Cards - Skinbase',
'description' => $meta['description'] ?? '',
'url' => $meta['canonical'] ?? route('cards.index'),
'isPartOf' => [
@@ -35,7 +35,7 @@
@section('content')
<section class="px-6 pt-8 md:px-10">
<div class="rounded-[34px] border border-white/10 bg-[radial-gradient(circle_at_top_left,rgba(56,189,248,0.14),transparent_38%),linear-gradient(180deg,rgba(15,23,42,0.96),rgba(2,6,23,0.88))] p-6 shadow-[0_24px_70px_rgba(2,6,23,0.32)] md:p-8">
<p class="text-[11px] font-semibold uppercase tracking-[0.28em] text-sky-200/75">Nova Cards</p>
<p class="text-[11px] font-semibold uppercase tracking-[0.28em] text-sky-200/75">Cards</p>
<h1 class="mt-3 text-3xl font-semibold tracking-[-0.04em] text-white md:text-5xl">{{ $heading }}</h1>
<p class="mt-4 max-w-3xl text-sm leading-7 text-slate-300 md:text-base">{{ $subheading }}</p>
<div class="mt-6 flex flex-wrap gap-3">
@@ -118,7 +118,7 @@
<div>
<p class="text-[11px] font-semibold uppercase tracking-[0.22em] text-slate-500">Creator profile</p>
<h2 class="mt-1 text-2xl font-semibold text-white">{{ $creatorSummary['creator']['display_name'] }}</h2>
<p class="mt-2 text-sm leading-7 text-slate-300">{{ ($context ?? null) === 'creator-portfolio' ? 'A dedicated Nova Cards portfolio view with public works, signature themes, remix activity, and publishing history.' : 'A public snapshot of this creator\'s Nova Cards footprint, top styles, and strongest publishing signals.' }}</p>
<p class="mt-2 text-sm leading-7 text-slate-300">{{ ($context ?? null) === 'creator-portfolio' ? 'A dedicated Cards portfolio view with public works, signature themes, remix activity, and publishing history.' : 'A public snapshot of this creator\'s Cards footprint, top styles, and strongest publishing signals.' }}</p>
</div>
<span class="rounded-full border border-sky-300/20 bg-sky-400/10 px-3 py-1.5 text-[11px] font-semibold uppercase tracking-[0.18em] text-sky-100">{{ '@' . $creatorSummary['creator']['username'] }}</span>
</div>
@@ -266,7 +266,7 @@
@endforeach
</div>
@else
<div class="mt-4 rounded-[20px] border border-dashed border-white/12 bg-white/[0.03] px-4 py-6 text-sm text-slate-400">Challenge entries and featured placements will appear here as this creator participates in Nova Cards challenges.</div>
<div class="mt-4 rounded-[20px] border border-dashed border-white/12 bg-white/[0.03] px-4 py-6 text-sm text-slate-400">Challenge entries and featured placements will appear here as this creator participates in Cards challenges.</div>
@endif
</div>
</div>
@@ -631,7 +631,7 @@
<i class="fa-solid fa-id-card text-3xl"></i>
</div>
<h3 class="mt-5 text-2xl font-semibold text-white">No public cards yet</h3>
<p class="mx-auto mt-3 max-w-xl text-sm leading-7 text-slate-300">As creators publish their Nova Cards, they will appear here with crawlable quote text and preview imagery.</p>
<p class="mx-auto mt-3 max-w-xl text-sm leading-7 text-slate-300">As creators publish their Cards, they will appear here with crawlable quote text and preview imagery.</p>
</div>
@else
<div class="grid gap-4 sm:grid-cols-2 xl:grid-cols-3">

View File

@@ -6,8 +6,8 @@
->addJsonLd([
'@context' => 'https://schema.org',
'@type' => 'CollectionPage',
'name' => $meta['title'] ?? 'Nova Card Lineage - Skinbase Nova',
'description' => $meta['description'] ?? 'Trace the remix lineage for this Nova Card.',
'name' => $meta['title'] ?? 'Nova Lineage - Skinbase',
'description' => $meta['description'] ?? 'Trace the remix lineage for this Card.',
'url' => $meta['canonical'] ?? route('cards.lineage', ['slug' => $card['slug'], 'id' => $card['id']]),
'mainEntity' => collect($familyCards ?? [])->map(fn ($familyCard) => [
'@type' => 'CreativeWork',

View File

@@ -5,7 +5,7 @@
)
->og(
type: 'article',
title: $meta['title'] ?? ($card['title'] . ' - Nova Cards - Skinbase Nova'),
title: $meta['title'] ?? ($card['title'] . ' - Cards - Skinbase'),
description: $meta['description'] ?? $card['quote_text'],
url: $meta['canonical'] ?? $card['public_url'],
image: $card['og_preview_url'] ?? $card['preview_url'] ?? null,

View File

@@ -2,15 +2,9 @@
<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">
<head>
<title>{{ $page_title ?? 'Skinbase' }}</title>
@include('partials.seo.head', ['seo' => $seo ?? null])
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="{{ $page_meta_description ?? '' }}">
<meta name="keywords" content="{{ $page_meta_keywords ?? '' }}">
@isset($page_canonical)
<link rel="canonical" href="{{ $page_canonical }}" />
@endisset
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" />
<link rel="shortcut icon" href="/favicon.ico">

View File

@@ -4,8 +4,8 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
@php($page_robots = $page_robots ?? 'noindex,nofollow')
@include('partials.seo.head', ['seo' => $seo ?? null])
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">

View File

@@ -4,8 +4,8 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
@php($page_robots = $page_robots ?? 'noindex,nofollow')
@include('partials.seo.head', ['seo' => $seo ?? null])
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">

View File

@@ -36,16 +36,7 @@
@yield('sidebar')
</aside>
</div>
@else
<section class="min-w-0">
@yield('content')
</section>
@endif
</div>
</main>
@include('layouts.nova.footer')
@include('partials.seo.head', ['seo' => $seo ?? null])
@stack('toolbar')
@stack('scripts')

View File

@@ -3,7 +3,8 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>@yield('title', 'Skinbase')</title>
@php($page_robots = $page_robots ?? 'noindex,nofollow')
@include('partials.seo.head', ['seo' => $seo ?? null])
</head>
<body>
@yield('content')

View File

@@ -6,7 +6,21 @@
$deferFontAwesome = request()->routeIs('index');
$deferWebManifest = request()->routeIs('index');
$isInertiaPage = isset($page) && is_array($page);
$shouldRenderBladeSeo = ($useUnifiedSeo ?? false) && (($renderBladeSeo ?? false) || ! $isInertiaPage);
$isAuthSeoRoute = request()->routeIs([
'login',
'register',
'register.notice',
'password.request',
'password.reset',
'password.confirm',
'verification.notice',
'registration.verify',
'setup.email.create',
'setup.password.create',
'setup.username.create',
]);
$page_robots = $page_robots ?? ($isAuthSeoRoute ? 'noindex,nofollow' : null);
$shouldRenderBladeSeo = ($useUnifiedSeo ?? ! $isInertiaPage) && (($renderBladeSeo ?? true) || ! $isInertiaPage);
$novaCssEntries = [
'resources/css/app.css',
'resources/css/nova-grid.css',

View File

@@ -6,6 +6,10 @@
@php
$skinbaseSessionSkipped = request()->attributes->get('skinbase.session_skipped') === true;
$skinbaseCanUseSession = request()->hasSession() && ! $skinbaseSessionSkipped;
$page_title = $page_title ?? 'Story Editor';
$page_meta_description = $page_meta_description ?? 'Create and edit stories on Skinbase.';
$page_canonical = $page_canonical ?? url()->current();
$page_robots = $page_robots ?? 'noindex,nofollow';
@endphp
<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">
@@ -16,7 +20,7 @@
<meta name="csrf-token" content="{{ csrf_token() }}">
@endif
<title>{{ $page_title ?? 'Story Editor' }} Skinbase</title>
@include('partials.seo.head', ['seo' => $seo ?? null])
<link rel="icon" type="image/png" href="/favicon/favicon-96x96.png" sizes="96x96" />
<link rel="icon" type="image/svg+xml" href="/favicon/favicon.svg" />

View File

@@ -1,6 +1,6 @@
@extends('news.layout', [
'metaTitle' => $archiveDate->format('F Y') . ' — News Archive',
'metaDescription' => 'News archive for ' . $archiveDate->format('F Y') . ' on Skinbase Nova.',
'metaDescription' => 'News archive for ' . $archiveDate->format('F Y') . ' on Skinbase.',
'metaCanonical' => route('news.archive', ['year' => $archiveDate->year, 'month' => $archiveDate->month]),
])

View File

@@ -31,7 +31,7 @@
<div>
<div class="text-[11px] font-semibold uppercase tracking-[0.2em] text-white/40">News author</div>
<h2 class="mt-2 text-2xl font-semibold text-white">{{ $authorLabel }}</h2>
<p class="mt-2 text-sm leading-7 text-white/60">{{ $author->profile?->bio ? Str::limit($author->profile->bio, 180) : 'Writes updates, announcements, and editorial stories for Skinbase Nova.' }}</p>
<p class="mt-2 text-sm leading-7 text-white/60">{{ $author->profile?->bio ? Str::limit($author->profile->bio, 180) : 'Writes updates, announcements, and editorial stories for Skinbase.' }}</p>
</div>
</div>
</div>

View File

@@ -5,6 +5,7 @@
<meta name="csrf-token" content="{{ csrf_token() }}" />
@endif
@vite(['resources/js/studio.jsx'])
@inertiaHead
<style>
body.page-studio main { padding-top: 2.3rem; }
</style>

View File

@@ -15,6 +15,7 @@
</script>
@vite(['resources/js/entry-topbar.jsx','resources/js/upload.jsx'])
@inertiaHead
<style>
/* Upload page spacing: extra top padding and bottom space so sticky action bar won't overlap content */
body.page-upload main {

View File

@@ -11,7 +11,7 @@
<div class="pointer-events-none absolute inset-0 bg-gradient-to-t from-nova-900 via-nova-900/60 to-transparent"></div>
<div class="relative z-10 w-full px-6 pb-7 sm:px-10 lg:px-16">
<h1 class="text-2xl font-bold tracking-tight text-white sm:text-4xl">
Skinbase Nova
Skinbase
</h1>
<p class="mt-2 max-w-xl text-sm text-soft">
Discover. Create. Inspire.