brand-site/src/components/SEO.astro
Scott Scoble b2be9aba9e chore: remove Dark Provenance book references (book shelved)
The Dark Provenance book is shelved for now. Per Scott: remove the book
reference, keep the dark provenance idea.

This commit removes the book artifact references — the cards, the waitlist
CTAs, the Book schema entry, the SharedForm waitlist message — but does
not touch the underlying concept. The 'dark provenance' idea continues
to live in:
- /blog/the-taste-problem (dark-factory series post #5)
- /blog/spec-first-audit-surface (existing)
- the Speckl project card on /about
- the Speckl knowsAbout / project references in the SEO schema

Cover SVG at public/images/book-cover-dark-provenance.svg is intentionally
kept; un-shelving the book is a one-line restore across the four pages
when Scott calls it back.

Removed:
- src/pages/books.astro: full 'Dark Provenance' coming-soon card with
  cover, waitlist CTA, and mailto link
- src/pages/index.astro: 'Dark Provenance' book card on homepage
- src/pages/about.astro: 'Dark Provenance' book card in published-books grid
- src/components/SEO.astro: @type: Book schema entry
- src/components/Form/SharedForm.astro: 'we'll let you know when Dark
  Provenance is available' waitlist success message (was unreachable; form
  is only rendered with type=speaking or type=contact)

Build: 40 pages, 2.8s, clean. No remaining 'Dark Provenance' string in src/.
2026-07-16 16:40:31 -07:00

317 lines
11 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/wscoble',
'https://www.amazon.com/stores/Scott-Scoble/author/B0GKSSBDMK',
],
knowsAbout: ['AI leadership', 'human cultivation', 'engineering teams', 'formal specifications', 'provenance systems'],
knowsLanguage: ['en'],
memberOf: [
{
'@type': 'Organization',
name: 'Greybeard Holdings, LLC',
},
],
owns: [
{
'@type': 'SoftwareSourceCode',
name: 'Speckl',
description: 'A state machine specification language compiler producing auditable code with embedded provenance',
url: 'https://speckl.scoble.me',
},
{
'@type': 'SoftwareSourceCode',
name: 'ScobleClaw',
description: 'Agentic engineering framework for building with AI agents',
url: 'https://os.scoble.me/forgejo/sscoble/scobleclaw',
},
{
'@type': 'CreativeWork',
name: 'Beyond the Prompt',
description: 'Workshop presentation on Skills and Subagents for AI-assisted development',
url: 'https://os.scoble.me/forgejo/sscoble/beyond-the-prompt',
},
],
};
switch (pageType) {
case 'home': {
const websiteLd = {
'@type': 'WebSite',
'@id': `${siteUrl}#website`,
name: 'Scott Scoble',
description: 'Human Cultivation Expert for the AI Age',
url: siteUrl,
};
const speakableSchema = {
'@context': 'https://schema.org',
'@type': 'SpeakableSpecification',
cssSelector: ['h1', '.hero p', '.hero-description'],
};
return JSON.stringify([personLd, websiteLd, speakableSchema], null, 2);
}
case 'blog': {
const blogSchema = {
'@context': 'https://schema.org',
'@type': 'Blog',
'@id': `${siteUrl}#blog`,
name: 'Scott Scoble Blog',
description: 'Articles and essays by Scott Scoble on AI leadership, team cultivation, developer experience, and the human side of technology.',
url: `${siteUrl}/blog`,
author: {
'@type': 'Person',
name: 'Scott Scoble',
url: siteUrl,
},
blogPost: [
{
'@type': 'BlogPosting',
headline: 'Why Cultivation Over Strip Mining',
description: 'Gallup 2026: 80% of the global workforce is disengaged. The $438B cost is not a tool problem; it is a people problem.',
url: `${siteUrl}/blog/strip-mining-cultivation`,
datePublished: '2026-05-18',
author: { '@type': 'Person', name: 'Scott Scoble' },
},
{
'@type': 'BlogPosting',
headline: '50 First Dates with AI',
description: "Every conversation with most AI systems is a first date. Here's the three-layer memory model that actually compounds.",
url: `${siteUrl}/blog/50-first-dates-with-ai`,
datePublished: '2026-05-24',
author: { '@type': 'Person', name: 'Scott Scoble' },
},
{
'@type': 'BlogPosting',
headline: 'The Soil Under Your Team',
description: "Tall stalks, ground cover, nitrogen fixers, pollinators, deep roots. Here's how to read the soil under your team.",
url: `${siteUrl}/blog/soil-health-teams`,
datePublished: '2026-05-18',
author: { '@type': 'Person', name: 'Scott Scoble' },
},
{
'@type': 'BlogPosting',
headline: 'The Soil Beneath the Code is Out',
description: 'A three-layer framework for understanding what makes engineering organizations healthy — or not.',
url: `${siteUrl}/blog/the-soil-beneath-the-code`,
datePublished: '2026-04-28',
author: { '@type': 'Person', name: 'Scott Scoble' },
},
],
};
return JSON.stringify([personLd, blogSchema], 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',
},
], 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" />