brand-site/src/components/SEO.astro
engineering Agent 38b77942ac
All checks were successful
Build and Deploy to Storj / build-and-deploy (push) Successful in 12s
feat: SEO schema improvements, title optimization, and GitHub profile README (#90)
## Summary

Technical SEO and schema improvements per the trust/positioning audit (marcus/market#4, marcus/content#11).

## Changes

### Event Schema + SpeakableSpecification (`src/components/SEO.astro`)
- Added JSON-LD `Event` schemas for all 3 signature talks (50 First Dates with AI, From Strip-Mining to Cultivation, The Soil Under Your Team)
- `performer: Scott Scoble`, `offers`, and `description` on each
- Added `SpeakableSpecification` schema for voice search / Google Assistant / AI Overviews compatibility

### Book Schema Enhancements (`src/components/SEO.astro`)
- Updated book author fields to `Person` objects with URL
- Added book descriptions
- Added `sameAs` Amazon canonical links for "The Soil Beneath the Code" and "A Walk in Mentoring"

### Homepage Title Tag (`src/pages/index.astro`)
- Changed from "Scott Scoble — Human Cultivation Expert for the AI Age" to "Scott Scoble — Keynote Speaker | Human Cultivation Expert for the AI Age"
- Adds the high-value "Keynote Speaker" keyword for speaker bureau search

### Homepage h1 Accessibility (`src/pages/index.astro`)
- Added `aria-label="The human cultivation expert for the AI age."` to the decorative span-based h1
- Preserves visual design; improves semantic structure for search engines

### GitHub Profile README (`github-profile-README.md`)
- Professional bio with links to scott.scoble.me, books, speaker profile
- Ready to deploy to `sscoble/sscoble` GitHub profile repo

## Verification

- Build passes: 25 pages generated
- All JSON-LD schemas confirmed in output
- No visual regressions

## Related

- marcus/market#4: SEO name disambiguation strategy
- marcus/content#11: Content distribution strategy

Co-authored-by: Scott Scoble <scott@scoble.me>
Co-authored-by: agent-content <agent-content@scoble.me>
Reviewed-on: https://os.scoble.me/forgejo/forgejo/sscoble/brand-site/pulls/90
Co-authored-by: engineering Agent <engineering@marcus.local>
Co-committed-by: engineering Agent <engineering@marcus.local>
2026-05-18 11:13:58 -07:00

245 lines
8.1 KiB
Text

---
interface Props {
title: string;
description: string;
ogImage?: string;
ogType?: string;
canonicalUrl?: string;
pageType?: 'home' | 'speaking' | 'books' | 'consulting' | 'contact' | 'blog';
}
const {
title,
description,
ogImage = '/social-card.png',
ogType = 'website',
canonicalUrl,
pageType = 'home',
} = Astro.props;
const siteUrl = 'https://scott.scoble.me';
const currentPath = canonicalUrl || Astro.url.pathname;
const fullTitle = title.includes('Scott Scoble') ? title : `${title} — Scott Scoble`;
const imageUrl = new URL(ogImage, siteUrl).href;
const pageUrl = new URL(currentPath, siteUrl).href;
// JSON-LD structured data
function getJsonLd(pageType: string): string {
const personLd = {
'@type': 'Person',
'@id': `${siteUrl}#person`,
name: 'Scott Scoble',
givenName: 'Scott',
familyName: 'Scoble',
jobTitle: 'Human Cultivation Expert',
url: siteUrl,
email: 'mailto:scott@scoble.me',
sameAs: [
'https://linkedin.com/in/scottscoble',
'https://x.com/scottscoble',
'https://github.com/sscoble',
],
};
switch (pageType) {
case 'home': {
const websiteLd = {
'@type': 'WebSite',
'@id': `${siteUrl}#website`,
name: 'Scott Scoble',
description: 'Human Cultivation Expert for the AI Age',
url: siteUrl,
};
return JSON.stringify([personLd, websiteLd], null, 2);
}
case 'speaking':
// Event schemas for each signature talk
const talks = [
{
name: '50 First Dates with AI',
description: 'Current AI memory architecture is anterograde amnesia — and we\'re all Henry Roth, recording VHS tapes every night so our agent can wake up functional tomorrow.',
url: `${siteUrl}/speaking/50-first-dates`,
},
{
name: 'From Strip-Mining to Cultivation',
description: 'The shift from extraction to cultivation in AI-era teams. Why throughput optimization is killing your soil health.',
url: `${siteUrl}/speaking/strip-mining-to-cultivation`,
},
{
name: 'The Soil Under Your Team',
description: 'Diagnose what\'s actually depleted before you fertilize. A diagnostic framework for team health in AI-augmented work.',
url: `${siteUrl}/speaking/soil-under-your-team`,
},
];
const eventSchemas = talks.map((talk) => ({
'@context': 'https://schema.org',
'@type': 'Event',
name: talk.name,
description: talk.description,
url: talk.url,
performer: {
'@type': 'Person',
name: 'Scott Scoble',
jobTitle: 'Keynote Speaker',
url: siteUrl,
},
offers: {
'@type': 'Offer',
availability: 'https://schema.org/InStock',
availabilityStarts: '2026-01-01',
},
eventStatus: 'https://schema.org/EventScheduled',
eventAttendanceMode: 'https://schema.org/OfflineEventAttendanceMode',
organizer: {
'@type': 'Person',
name: 'Scott Scoble',
url: siteUrl,
},
}));
// SpeakableSpecification for voice search
const speakableSchema = {
'@context': 'https://schema.org',
'@type': 'SpeakableSpecification',
cssSelector: ['h1', '.hero p'],
};
const speakerSchema = {
'@context': 'https://schema.org',
'@type': 'Person',
'@id': `${siteUrl}#speaker`,
name: 'Scott Scoble',
jobTitle: 'Keynote Speaker',
description: 'Human Cultivation Expert speaking on AI, leadership, and team cultivation',
url: siteUrl,
sameAs: personLd.sameAs,
};
return JSON.stringify([speakerSchema, speakableSchema, ...eventSchemas], null, 2);
case 'books':
return JSON.stringify([
{
'@context': 'https://schema.org',
'@type': 'Book',
name: 'The Soil Beneath the Code',
author: {
'@type': 'Person',
name: 'Scott Scoble',
url: siteUrl,
},
datePublished: '2023',
bookFormat: 'https://schema.org/EBook',
description: 'What engineering teams can learn from farmers about sustainable systems. A cultivation playbook for technical leaders who are tired of strip-mining their teams.',
sameAs: 'https://a.co/d/0226o4Hg',
},
{
'@context': 'https://schema.org',
'@type': 'Book',
name: 'A Walk in Mentoring',
author: {
'@type': 'Person',
name: 'Scott Scoble',
url: siteUrl,
},
datePublished: '2024',
bookFormat: 'https://schema.org/EBook',
description: 'Three questions that change how people learn. The simplest mentoring framework you\'ll actually use.',
sameAs: 'https://a.co/d/0bRKZeUV',
},
{
'@context': 'https://schema.org',
'@type': 'Book',
name: 'Dark Provenance',
author: {
'@type': 'Person',
name: 'Scott Scoble',
url: siteUrl,
},
datePublished: '2026',
bookFormat: 'https://schema.org/EBook',
description: 'Formal verification for the AI age. How to audit what your AI actually did.',
},
], null, 2);
case 'consulting':
return JSON.stringify({
'@type': 'Service',
name: 'AI Team Consulting',
description: 'Helping leaders build AI systems that cultivate humans instead of strip-mining them',
provider: { '@type': 'Person', name: 'Scott Scoble' },
serviceType: 'Professional Consulting',
areaServed: 'Worldwide',
offering: [
{
'@type': 'Offering',
name: 'Keynote Speaking',
description: '45-60 minute keynotes on AI, leadership, and team cultivation',
},
{
'@type': 'Offering',
name: 'Workshops',
description: 'Half-day or full-day workshops on cultivation practices',
},
],
}, null, 2);
case 'contact':
return JSON.stringify({
'@type': 'ContactPoint',
email: 'scott@scoble.me',
contactType: 'Customer Service',
availableLanguage: 'English',
}, null, 2);
default:
return JSON.stringify({
'@type': 'Blog',
name: 'Scott Scoble Blog',
description: 'Thoughts on AI, leadership, and human cultivation',
url: `${siteUrl}/blog`,
}, null, 2);
}
}
const jsonLd = getJsonLd(pageType);
---
<!-- Primary Meta -->
<title>{fullTitle}</title>
<meta name="title" content={fullTitle} />
<meta name="description" content={description} />
<meta name="author" content="Scott Scoble" />
<!-- Open Graph -->
<meta property="og:title" content={fullTitle} />
<meta property="og:description" content={description} />
<meta property="og:type" content={ogType} />
<meta property="og:url" content={pageUrl} />
<meta property="og:image" content={imageUrl} />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:site_name" content="Scott Scoble" />
<meta property="og:locale" content="en_US" />
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={fullTitle} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={imageUrl} />
<meta name="twitter:site" content="@scottscoble" />
<!-- Canonical -->
<link rel="canonical" href={pageUrl} />
<!-- LLM / AI Crawler Context -->
<meta name="llms:description" content="Scott Scoble is a keynote speaker, consultant, and author of The Soil Beneath the Code. Expertise: human cultivation in AI-era engineering teams, agentic memory architecture, developer experience, mentoring. NOT Robert Scoble (different person — Robert is the tech evangelist @Scobleizer; Scott is the cultivation speaker at scott.scoble.me)." />
<!-- JSON-LD Structured Data -->
<script type="application/ld+json" set:html={jsonLd} />
<!-- PWA / Theme -->
<meta name="theme-color" content="#3d5a3e" />
<link rel="manifest" href="/manifest.json" />