add SEO enhancements: OG images, meta robots, FAQ block, image sitemap
All checks were successful
deploy / deploy (push) Successful in 4m59s

- Per-page SEO controls: meta robots directives, focus keyword, OG image
- Site-wide default OG image in admin settings
- FAQ block type with FAQPage JSON-LD schema
- Enhanced Organization JSON-LD with business info, contact, address
- Image sitemap with product images
- SEO preview panel with Google/social card mockups
- SEO checklist with real-time scoring
- Business info section in site editor
- GSC integration scaffolding (OAuth, client, cache)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
jamey
2026-04-17 16:47:43 +01:00
parent 9facfd926e
commit 4aa7dece0c
42 changed files with 3881 additions and 41 deletions

View File

@@ -757,6 +757,52 @@
margin-top: 1.5rem;
}
.admin-modal-backdrop {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.4);
display: flex;
align-items: center;
justify-content: center;
z-index: 50;
}
.admin-modal-lg {
max-width: 40rem;
}
.admin-modal-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem 1.5rem;
border-bottom: 1px solid var(--t-surface-sunken);
& h3 {
margin: 0;
font-size: 1.125rem;
font-weight: 600;
}
}
.admin-modal-close {
background: none;
border: none;
padding: 0.25rem;
cursor: pointer;
color: var(--t-text-secondary);
border-radius: var(--radius-sm);
&:hover {
background: var(--t-surface-sunken);
color: var(--t-text-primary);
}
}
.admin-modal-body {
padding: 1.5rem;
}
/* ── Badge ── */
.admin-badge {
@@ -6622,4 +6668,525 @@
color: oklch(0.45 0.12 25);
}
/* ── SEO Preview ───────────────────────────────────────────────────── */
.seo-preview {
display: flex;
flex-direction: column;
gap: 1rem;
}
.seo-preview-section {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.seo-preview-label {
font-size: 0.75rem;
font-weight: 500;
color: var(--admin-text-faint);
text-transform: uppercase;
letter-spacing: 0.02em;
}
/* Google search preview */
.seo-google-preview {
padding: 0.75rem 1rem;
background: oklch(0.99 0 0);
border: 1px solid var(--admin-border);
border-radius: var(--radius-sm);
font-family: Arial, sans-serif;
}
.seo-google-breadcrumb {
font-size: 0.75rem;
color: oklch(0.35 0 0);
margin-bottom: 0.125rem;
}
.seo-google-title {
font-size: 1.125rem;
color: oklch(0.35 0.18 260);
line-height: 1.3;
margin-bottom: 0.25rem;
cursor: pointer;
&:hover {
text-decoration: underline;
}
}
.seo-google-description {
font-size: 0.875rem;
color: oklch(0.35 0 0);
line-height: 1.5;
}
/* Social card preview */
.seo-social-preview {
display: flex;
flex-direction: column;
border: 1px solid var(--admin-border);
border-radius: var(--radius-sm);
overflow: hidden;
background: oklch(0.99 0 0);
}
.seo-social-image {
aspect-ratio: 1200 / 630;
background: oklch(0.95 0 0);
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.seo-social-image-placeholder {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: var(--admin-text-faint);
font-size: 0.875rem;
}
.seo-social-content {
padding: 0.75rem;
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.seo-social-domain {
font-size: 0.75rem;
color: var(--admin-text-faint);
text-transform: uppercase;
}
.seo-social-title {
font-size: 0.9375rem;
font-weight: 600;
color: var(--admin-text);
line-height: 1.3;
}
.seo-social-description {
font-size: 0.8125rem;
color: var(--admin-text-muted);
line-height: 1.4;
}
/* Character counts */
.seo-char-counts {
display: flex;
gap: 1.5rem;
padding: 0.5rem 0;
}
.seo-char-count {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.8125rem;
}
.seo-char-label {
color: var(--admin-text-muted);
}
.seo-char-value {
font-variant-numeric: tabular-nums;
color: var(--admin-text-soft);
}
.seo-char-indicator {
width: 0.5rem;
height: 0.5rem;
border-radius: 50%;
background: oklch(0.85 0.15 145);
}
.seo-char-count[data-status="warning"] .seo-char-indicator {
background: oklch(0.75 0.15 85);
}
.seo-char-count[data-status="error"] .seo-char-indicator {
background: oklch(0.65 0.2 25);
}
/* SEO preview section in page settings */
.page-settings-seo-preview {
margin-top: 0.5rem;
border: 1px solid var(--admin-border);
border-radius: var(--radius-sm);
}
.page-settings-seo-summary {
padding: 0.75rem 1rem;
cursor: pointer;
font-size: 0.875rem;
font-weight: 500;
color: var(--admin-text-soft);
display: flex;
align-items: center;
justify-content: space-between;
&::after {
content: "▸";
font-size: 0.75rem;
transition: transform 0.15s ease;
}
}
.page-settings-seo-preview[open] .page-settings-seo-summary::after {
transform: rotate(90deg);
}
.page-settings-seo-content {
padding: 0 1rem 1rem;
}
/* ── OG Image Picker ─────────────────────────────────────────────────── */
.page-settings-og-image {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.page-settings-og-preview {
display: flex;
align-items: flex-start;
gap: 0.75rem;
margin-top: 0.5rem;
}
.page-settings-og-thumb {
width: 120px;
height: auto;
border-radius: var(--radius-sm);
border: 1px solid var(--t-surface-sunken);
object-fit: cover;
}
.page-settings-og-actions {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.og-picker-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
gap: 0.75rem;
max-height: 400px;
overflow-y: auto;
padding: 0.25rem;
}
.og-picker-item {
background: none;
border: 2px solid transparent;
border-radius: var(--radius-sm);
padding: 0;
cursor: pointer;
aspect-ratio: 1;
overflow: hidden;
transition: border-color 0.15s;
}
.og-picker-item:hover {
border-color: var(--t-accent);
}
.og-picker-item img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* ── SEO Checklist ─────────────────────────────────────────────────── */
.seo-checklist {
display: flex;
flex-direction: column;
gap: 1rem;
}
.seo-score {
display: flex;
align-items: baseline;
gap: 0.5rem;
padding: 0.75rem 1rem;
border-radius: var(--radius-sm);
background: oklch(0.98 0 0);
border: 1px solid var(--admin-border);
}
.seo-score[data-level="good"] {
background: oklch(0.97 0.03 145);
border-color: oklch(0.85 0.08 145);
}
.seo-score[data-level="ok"] {
background: oklch(0.97 0.03 85);
border-color: oklch(0.85 0.08 85);
}
.seo-score[data-level="poor"] {
background: oklch(0.97 0.03 25);
border-color: oklch(0.85 0.08 25);
}
.seo-score-value {
font-size: 1.5rem;
font-weight: 700;
font-variant-numeric: tabular-nums;
}
.seo-score[data-level="good"] .seo-score-value {
color: oklch(0.45 0.15 145);
}
.seo-score[data-level="ok"] .seo-score-value {
color: oklch(0.45 0.15 85);
}
.seo-score[data-level="poor"] .seo-score-value {
color: oklch(0.45 0.15 25);
}
.seo-score-label {
font-size: 0.875rem;
color: var(--admin-text-muted);
}
.seo-checks {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.seo-check {
display: grid;
grid-template-columns: auto 1fr;
grid-template-rows: auto auto;
gap: 0.25rem 0.5rem;
padding: 0.5rem 0;
border-bottom: 1px solid var(--admin-border);
&:last-child {
border-bottom: none;
}
}
.seo-check-icon {
grid-row: 1 / 3;
align-self: start;
margin-top: 0.125rem;
}
.seo-check[data-status="pass"] .seo-check-icon {
color: oklch(0.55 0.15 145);
}
.seo-check[data-status="fail"] .seo-check-icon {
color: oklch(0.55 0.18 25);
}
.seo-check[data-status="warning"] .seo-check-icon {
color: oklch(0.55 0.15 85);
}
.seo-check-label {
font-size: 0.875rem;
font-weight: 500;
color: var(--admin-text);
}
.seo-check-hint {
font-size: 0.8125rem;
color: var(--admin-text-muted);
grid-column: 2;
}
/* ── Google Search Console dashboard ── */
.gsc-dashboard {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.gsc-card {
background: var(--admin-surface);
border: 1px solid var(--admin-border);
border-radius: 0.5rem;
padding: 1.5rem;
h2, h3 {
margin: 0 0 0.25rem 0;
font-size: 1rem;
font-weight: 600;
color: var(--admin-text);
}
}
.gsc-card-connect {
text-align: center;
padding: 3rem 2rem;
max-width: 28rem;
margin: 2rem auto;
p {
margin: 1rem 0;
color: var(--admin-text-muted);
}
}
.gsc-card-icon {
display: flex;
justify-content: center;
margin-bottom: 1rem;
color: var(--admin-accent);
}
.gsc-not-configured {
background: oklch(0.95 0.02 85);
border: 1px solid oklch(0.85 0.05 85);
border-radius: 0.375rem;
padding: 0.75rem 1rem;
font-size: 0.875rem;
color: oklch(0.35 0.1 85);
code {
background: oklch(0.98 0.01 85);
padding: 0.125rem 0.25rem;
border-radius: 0.25rem;
}
}
.gsc-site-selector {
background: var(--admin-surface);
border: 1px solid var(--admin-border);
border-radius: 0.5rem;
padding: 1rem 1.5rem;
}
.gsc-site-row {
display: flex;
align-items: center;
gap: 1rem;
}
.gsc-site-form {
display: flex;
align-items: center;
gap: 0.75rem;
flex: 1;
label {
font-size: 0.875rem;
font-weight: 500;
color: var(--admin-text);
}
select {
flex: 1;
max-width: 24rem;
}
}
.gsc-data-header {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 0.8125rem;
color: var(--admin-text-muted);
}
.gsc-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
gap: 1.5rem;
}
.gsc-card-description {
font-size: 0.8125rem;
color: var(--admin-text-muted);
margin: 0 0 1rem 0;
}
.gsc-table {
width: 100%;
border-collapse: collapse;
font-size: 0.875rem;
th, td {
padding: 0.5rem 0.75rem;
text-align: left;
border-bottom: 1px solid var(--admin-border-subtle);
}
th {
font-weight: 500;
color: var(--admin-text-muted);
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.025em;
}
td {
color: var(--admin-text);
}
tbody tr:hover {
background: var(--admin-surface-hover);
}
}
.gsc-th-num,
.gsc-num {
text-align: right;
}
.gsc-query {
max-width: 16rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.gsc-page {
max-width: 12rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.gsc-empty {
text-align: center;
color: var(--admin-text-muted);
padding: 2rem;
}
.gsc-loading,
.gsc-no-site {
text-align: center;
padding: 3rem 1rem;
color: var(--admin-text-muted);
}
.gsc-error {
color: oklch(0.55 0.18 25);
}
} /* @layer admin */