From 2d5241040229a778e7b87e9e76b287aa35f34a97 Mon Sep 17 00:00:00 2001 From: Scott Scoble Date: Fri, 1 May 2026 22:45:54 -0700 Subject: [PATCH] fix: repair broken imports, rewrite SharedForm/SEO for Astro SSG, restore Umami, add manifest link - Remove invalid 'astro:collection-utils' import (doesn't exist) - Rewrite SharedForm.astro: no React hooks, proper Astro component with client-side + \ No newline at end of file diff --git a/src/components/SEO.astro b/src/components/SEO.astro index 21b1fe0..792c205 100644 --- a/src/components/SEO.astro +++ b/src/components/SEO.astro @@ -1,11 +1,9 @@ --- -import { useState } from 'astro:collection-utils'; - interface SEOProps { title: string; description: string; ogImage?: string; - ogType?: 'website' | 'article' | 'book' | 'profile'; + ogType?: string; url?: string; pageType?: 'home' | 'speaking' | 'books' | 'consulting' | 'contact' | 'blog'; } @@ -15,19 +13,105 @@ const { description, ogImage = '/social-card.png', ogType = 'website', - url = Astro.url.pathname, + canonicalUrl, pageType = 'home', } = Astro.props; const siteUrl = 'https://scott.scoble.me'; const fullTitle = title.includes('Scott Scoble') ? title : `${title} — Scott Scoble`; const imageUrl = new URL(ogImage, siteUrl).href; -const pageUrl = new URL(url, siteUrl).href; +const pageUrl = canonicalUrl ? new URL(canonicalUrl, siteUrl).href : `${siteUrl}${Astro.url.pathname}`; + +// Build JSON-LD based on page type +const person = { + '@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', + ], +}; + +const website = { + '@type': 'WebSite', + '@id': `${siteUrl}#website`, + name: 'Scott Scoble', + description: 'Human Cultivation Expert for the AI Age', + url: siteUrl, +}; + +let jsonLd: any; +switch (pageType) { + case 'home': + jsonLd = [person, website]; + break; + case 'speaking': + jsonLd = { + ...person, + '@id': `${siteUrl}#speaker`, + jobTitle: 'Keynote Speaker', + description: 'Human Cultivation Expert speaking on AI, leadership, and team cultivation', + }; + break; + case 'books': + jsonLd = [ + { + '@type': 'Book', + name: 'The Soil Beneath the Code', + author: { '@type': 'Person', name: 'Scott Scoble' }, + datePublished: '2023', + bookFormat: 'EBook, Hardcover', + }, + { + '@type': 'Book', + name: 'A Walk in Mentoring', + author: { '@type': 'Person', name: 'Scott Scoble' }, + datePublished: '2024', + bookFormat: 'EBook, Paperback', + }, + ]; + break; + case 'consulting': + jsonLd = { + '@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', + }; + break; + case 'contact': + jsonLd = { + '@type': 'ContactPoint', + email: 'scott@scoble.me', + contactType: 'Customer Service', + availableLanguage: 'English', + }; + break; + case 'blog': + default: + jsonLd = { + '@type': 'Blog', + name: 'Scott Scoble Blog', + description: 'Thoughts on AI, leadership, and human cultivation', + url: `${siteUrl}/blog`, + }; + break; +} --- + @@ -45,179 +129,4 @@ const pageUrl = new URL(url, siteUrl).href; - - - - ---- -function JsonLd({ pageType }: { pageType: SEOProps['pageType'] }) { - const person = { - '@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', - 'https://amzn.com/author/scottscoble', - ], - }; - - const website = { - '@type': 'WebSite', - '@id': `${siteUrl}#website`, - name: 'Scott Scoble', - description: 'Human Cultivation Expert for the AI Age', - url: siteUrl, - }; - - switch (pageType) { - case 'home': - return ( - - ); - - case 'speaking': - return ( - - ); - - case 'books': - return ( - - ); - - case 'consulting': - return ( - - ); - - case 'contact': - return ( - - ); - - case 'blog': - default: - return ( - - ); - } -} \ No newline at end of file + + diff --git a/src/pages/sitemap.xml.ts b/src/pages/sitemap.xml.ts index cd2489f..537e5af 100644 --- a/src/pages/sitemap.xml.ts +++ b/src/pages/sitemap.xml.ts @@ -1,37 +1,28 @@ ---- -import { getCollection } from 'astro:content'; -import { getSortedPosts } from '../utils/posts'; - -const posts = await getCollection('blog'); -const speakingPosts = await getCollection('speaking'); +// Static sitemap for scott.scoble.me +// Generated at build time const pages = [ - { url: '/', lastmod: new Date().toISOString() }, - { url: '/speaking', lastmod: new Date().toISOString() }, - { url: '/consulting', lastmod: new Date().toISOString() }, - { url: '/books', lastmod: new Date().toISOString() }, - { url: '/contact', lastmod: new Date().toISOString() }, - ...posts.map(post => ({ - url: `/blog/${post.slug}`, - lastmod: post.data.updated || post.data.date, - })), - ...speakingPosts.map(talk => ({ - url: `/speaking#talk-${talk.slug}`, - lastmod: new Date().toISOString(), - })), + { url: '/', changefreq: 'weekly', priority: '1.0' }, + { url: '/speaking', changefreq: 'weekly', priority: '0.9' }, + { url: '/consulting', changefreq: 'weekly', priority: '0.8' }, + { url: '/books', changefreq: 'monthly', priority: '0.8' }, + { url: '/about', changefreq: 'monthly', priority: '0.7' }, + { url: '/blog', changefreq: 'weekly', priority: '0.7' }, + { url: '/contact', changefreq: 'monthly', priority: '0.6' }, + { url: '/privacy', changefreq: 'yearly', priority: '0.3' }, ]; -// Render the sitemap XML +const siteUrl = 'https://scott.scoble.me'; +const today = new Date().toISOString().split('T')[0]; + const xml = ` - ${pages.map(page => ` - - ${new URL(page.url, 'https://scott.scoble.me').href} - ${typeof page.lastmod === 'string' ? page.lastmod : new Date(page.lastmod).toISOString().split('T')[0]} - weekly - ${page.url === '/' ? '1.0' : '0.8'} - - `).join('')} +${pages.map(page => ` + ${siteUrl}${page.url} + ${today} + ${page.changefreq} + ${page.priority} + `).join('\n')} `; export const GET = () => { @@ -41,4 +32,4 @@ export const GET = () => { 'Cache-Control': 'public, max-age=3600', }, }); -}; +}; \ No newline at end of file