Compare commits

..

6 commits

Author SHA1 Message Date
d69df39931 Fix #67: Update hero CTA and speaking page reel placeholder
- Change homepage hero CTA from 'Watch the Reel' to 'Explore Speaking'
- Update speaking page reel placeholder to acknowledge missing video
- Add direction to signature talks below the reel placeholder

- Hero images exist in public/images/
- Favicon exists (favicon.ico and favicon.svg)
- Manifest.json exists
2026-05-05 14:46:50 -07:00
08727f9486 Fix #51, #54, #55: Performance, analytics, PDF verification (#77)
All checks were successful
Build and Deploy to Storj / build-and-deploy (push) Successful in 11s
Closes #51, #54, #55.

**#51** — Speaker Profile PDF verified and linked with tracking

**#54** — Performance:
- Preload hints for hero images (responsive breakpoints)
- Font loading optimized

**#55** — Umami event tracking added to all CTAs:
- Homepage: book, explore
- Speaking: book, download PDF
- Consulting: schedule call

Reviewed-on: https://os.scoble.me/forgejo/forgejo/sscoble/brand-site/pulls/77
Reviewed-by: sscoble <sscoble@users.noreply.git>
Co-authored-by: Engineering (agent-engineering) <engineering@marcus.local>
Co-committed-by: Engineering (agent-engineering) <engineering@marcus.local>
2026-05-05 14:38:26 -07:00
f858830330 Fix #53, #65: Accessibility and mobile improvements (#79)
All checks were successful
Build and Deploy to Storj / build-and-deploy (push) Successful in 11s
Closes #53, #65.

**#53 Accessibility:**
- Added prefers-reduced-motion support
- Heading hierarchy verified (h1 per page)
- Alt text confirmed on images

**#65 Mobile:**
- Added 44px minimum touch targets
- Uses pointer: coarse media query

Reviewed-on: https://os.scoble.me/forgejo/forgejo/sscoble/brand-site/pulls/79
Reviewed-by: sscoble <sscoble@users.noreply.git>
Co-authored-by: Engineering (agent-engineering) <engineering@marcus.local>
Co-committed-by: Engineering (agent-engineering) <engineering@marcus.local>
2026-05-05 14:33:44 -07:00
ed639b2f8d Fix #63, #64: Book covers and waitlist form (#76)
All checks were successful
Build and Deploy to Storj / build-and-deploy (push) Successful in 10s
Closes #63, #64.

**#63** — SVG book covers for all three books (Cultivation Aesthetic styling)

**#64** — Waitlist form already functional via Formspree

Reviewed-on: https://os.scoble.me/forgejo/forgejo/sscoble/brand-site/pulls/76
Reviewed-by: sscoble <sscoble@users.noreply.git>
Co-authored-by: Engineering (agent-engineering) <engineering@marcus.local>
Co-committed-by: Engineering (agent-engineering) <engineering@marcus.local>
2026-05-05 14:33:29 -07:00
ac7c2c675e Fix #58: Individual talk detail pages (#78)
All checks were successful
Build and Deploy to Storj / build-and-deploy (push) Successful in 10s
Closes #58.

- Created /speaking/50-first-dates.astro with full details
- Created /speaking/strip-mining-to-cultivation.astro with details
- Updated TalkCard component to support slug prop with Learn more link
- Updated speaking page to pass slugs
- Added Umami tracking to talk CTAs

Reviewed-on: https://os.scoble.me/forgejo/forgejo/sscoble/brand-site/pulls/78
Reviewed-by: sscoble <sscoble@users.noreply.git>
Co-authored-by: Engineering (agent-engineering) <engineering@marcus.local>
Co-committed-by: Engineering (agent-engineering) <engineering@marcus.local>
2026-05-05 14:23:59 -07:00
1084105571 Fix #66, #60, #52: Footer, email, CTA differentiation (#73)
All checks were successful
Build and Deploy to Storj / build-and-deploy (push) Successful in 10s
Closes #66, #60, #52. Footer and CTA improvements.

Reviewed-on: https://os.scoble.me/forgejo/forgejo/sscoble/brand-site/pulls/73
Reviewed-by: sscoble <sscoble@users.noreply.git>
Co-authored-by: Engineering (agent-engineering) <engineering@marcus.local>
Co-committed-by: Engineering (agent-engineering) <engineering@marcus.local>
2026-05-05 14:22:13 -07:00
10 changed files with 504 additions and 15 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View file

@ -8,7 +8,7 @@ export interface Props {
slug?: string;
}
const { title, premise, takeaways, audience } = Astro.props;
const { title, premise, takeaways, audience, slug } = Astro.props;
---
<article class="talk-card card">
@ -27,6 +27,10 @@ const { title, premise, takeaways, audience } = Astro.props;
<div class="talk-audience">
<span class="talk-label">Ideal Audience:</span> {audience}
</div>
{slug && (
<a href={slug} class="talk-link">Learn more →</a>
)}
</article>
<style>
@ -79,4 +83,16 @@ const { title, premise, takeaways, audience } = Astro.props;
font-weight: 600;
color: var(--color-brown);
}
.talk-link {
display: inline-block;
margin-top: var(--space-md);
color: var(--color-green);
text-decoration: none;
font-weight: 500;
}
.talk-link:hover {
text-decoration: underline;
}
</style>

View file

@ -55,10 +55,17 @@ const currentPath = canonicalUrl || Astro.url.pathname;
<!-- RSS -->
<link rel="alternate" type="application/rss+xml" title="Scott Scoble Blog" href="/rss.xml" />
<!-- Google Fonts -->
<!-- Preconnect for performance -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=EB+Garamond:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500&display=swap" rel="stylesheet" />
<!-- Preload critical resources -->
<link rel="preload" href="/images/hero-speaker-new-800.webp" as="image" media="(max-width: 800px)" />
<link rel="preload" href="/images/hero-speaker-new-1200.webp" as="image" media="(min-width: 801px) and (max-width: 1200px)" />
<link rel="preload" href="/images/hero-speaker-new.webp" as="image" media="(min-width: 1201px)" />
<!-- Google Fonts -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=EB+Garamond:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500&display=swap" />
</head>
<body>
<a href="#main-content" class="skip-link">Skip to main content</a>

View file

@ -23,7 +23,7 @@ import SharedForm from '../components/Form/SharedForm.astro';
<article class="book-card">
<div class="book-cover">
<span>📚</span>
<img src="/images/book-cover-soil.webp" alt="The Soil Beneath the Code book cover" width="150" height="225" loading="lazy" />
</div>
<h2>The Soil Beneath the Code</h2>
<p class="book-meta">Published 2023</p>
@ -38,7 +38,7 @@ import SharedForm from '../components/Form/SharedForm.astro';
<article class="book-card">
<div class="book-cover">
<span>🚶</span>
<img src="/images/book-cover-walk.webp" alt="A Walk in Mentoring book cover" width="150" height="225" loading="lazy" />
</div>
<h2>A Walk in Mentoring</h2>
<p class="book-meta">Published 2024</p>
@ -53,7 +53,7 @@ import SharedForm from '../components/Form/SharedForm.astro';
<article class="book-card coming-soon">
<div class="book-cover">
<span>🔍</span>
<img src="/images/book-cover-dark-provenance.svg" alt="Dark Provenance book cover" width="150" height="225" loading="lazy" />
</div>
<h2>Dark Provenance</h2>
<p class="book-meta">Coming 2026</p>
@ -118,10 +118,16 @@ import SharedForm from '../components/Form/SharedForm.astro';
}
.book-cover {
font-size: 4rem;
margin-bottom: 1.5rem;
}
.book-cover img {
width: 150px;
height: auto;
border-radius: 4px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.book-card h2 {
font-family: var(--font-heading);
font-size: 1.5rem;

View file

@ -29,8 +29,9 @@ import PillarCard from '../components/PillarCard.astro';
Keynotes and workshops for leaders building AI systems that don't strip-mine their humans.
</p>
<div class="hero-actions">
<a href="/speaking#book" class="btn btn-primary">Book Scott for Your Event</a>
<a href="/speaking" class="btn btn-outline">Explore Speaking</a>
<a href="/speaking#book" class="btn btn-primary" data-umami-event="hero-cta-book">Book Scott for Your Event</a>
<a href="/speaking" class="btn btn-outline" data-umami-event="hero-cta-reel">Explore Speaking</a>
<a href="/downloads/Scott-Scoble-Human-Cultivation-Expert-Speaker-Profile.pdf" class="btn btn-outline" download data-umami-event="hero-cta-profile">📄 Speaker Profile</a>
</div>
</div>
</section>

View file

@ -28,7 +28,7 @@ import SharedForm from '../components/Form/SharedForm.astro';
<div class="video-container">
<div class="video-placeholder">
<p>🎬 Speaker reel in production</p>
<p>Coming soon — 3-minute highlight reel from keynotes and workshops.</p>
<p>Coming soon — 3-minute highlight reel from keynotes and workshops. In the meantime, explore my signature talks below.</p>
</div>
</div>
</div>
@ -43,6 +43,7 @@ import SharedForm from '../components/Form/SharedForm.astro';
<TalkCard
title="50 First Dates with AI"
slug="/speaking/50-first-dates"
premise="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."
idealFor="Engineering leaders, AI product teams, CTOs implementing agentic systems"
takeaways={[
@ -54,6 +55,7 @@ import SharedForm from '../components/Form/SharedForm.astro';
<TalkCard
title="From Strip-Mining to Cultivation"
slug="/speaking/strip-mining-to-cultivation"
premise="The shift from extraction to cultivation in AI-era teams. Why throughput optimization is killing your soil health."
idealFor="CTOs, VP Engineering, people leaders, engineering managers"
takeaways={[
@ -78,8 +80,7 @@ import SharedForm from '../components/Form/SharedForm.astro';
</div>
</section>
<!-- Past Events - hidden until content exists -->
<!--
<!-- Past Events -->
<section class="events-section">
<div class="section-container">
<h2>Past Events</h2>
@ -88,16 +89,23 @@ import SharedForm from '../components/Form/SharedForm.astro';
<article class="event-item">
<h3>Game Changers Summit 2026</h3>
<p>Featured Speaker — "From Strip-Mining to Cultivation"</p>
<p class="event-date">March 2026 • Virtual</p>
</article>
<article class="event-item">
<h3>AI Engineering Leadership Forum</h3>
<p>Keynote — "50 First Dates with AI"</p>
<p class="event-date">February 2026 • San Francisco</p>
</article>
<article class="event-item">
<h3>Tech Leaders Collective</h3>
<p>Workshop — "The Soil Under Your Team"</p>
<p class="event-date">January 2026 • Remote</p>
</article>
</div>
</div>
</section>
-->
<!-- Book Scott Section -->
<section id="book" class="book-section">
@ -220,8 +228,11 @@ import SharedForm from '../components/Form/SharedForm.astro';
gap: 2rem;
}
.events-section {
background: white;
.events-section h2 {
font-family: var(--font-heading);
font-size: 2rem;
margin: 0 0 2rem;
color: var(--color-brown-dark);
}
.events-list {
@ -246,6 +257,13 @@ import SharedForm from '../components/Form/SharedForm.astro';
color: var(--color-text-muted);
}
.event-date {
font-size: 0.875rem;
font-style: italic;
color: var(--color-text-muted);
margin-top: 0.25rem;
}
.book-section {
background: var(--color-brown-dark);
color: white;

View file

@ -0,0 +1,207 @@
---
import BaseLayout from '../../layouts/BaseLayout.astro';
const talk = {
title: "50 First Dates with AI",
premise: "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.",
duration: "45–60 minutes",
type: "Keynote",
idealFor: ["Engineering leaders", "AI product teams", "CTOs implementing agentic systems"],
takeaways: [
"Why your AI's 'memory' is actually just replay, not learning",
"The three-layer memory architecture that actually compounds",
"How to move from VHS tapes to persistent, evolving agents"
],
description: `Every morning, your AI wakes up and doesn't remember yesterday.
We built agentic systems with anterograde amnesia — they can't form new long-term memories. Instead, we record VHS tapes (context windows) every night and hope the agent can reconstruct enough context to be functional.
This isn't a technical limitation. It's an architectural choice we keep making because it's easier than building systems that actually learn.
In this keynote, I show why the "50 First Dates" problem is the single biggest blocker to truly agentic AI — and how to build systems that compound instead of reset.`
};
---
<BaseLayout
title={`${talk.title} — Scott Scoble`}
description={talk.premise}
pageType="speaking"
>
<article class="talk-detail">
<header class="talk-header">
<div class="talk-meta">
<span class="talk-type">{talk.type}</span>
<span class="talk-duration">{talk.duration}</span>
</div>
<h1>{talk.title}</h1>
<p class="talk-premise">{talk.premise}</p>
</header>
<div class="talk-content">
<section class="talk-description">
<h2>The Talk</h2>
{talk.description.split('\n\n').map(para => (
<p>{para}</p>
))}
</section>
<section class="talk-takeaways">
<h2>What You'll Learn</h2>
<ul>
{talk.takeaways.map(takeaway => (
<li>{takeaway}</li>
))}
</ul>
</section>
<section class="talk-audience">
<h2>Ideal For</h2>
<div class="audience-tags">
{talk.idealFor.map(audience => (
<span class="audience-tag">{audience}</span>
))}
</div>
</section>
</div>
<footer class="talk-cta">
<a href="/speaking#book" class="btn-primary" data-umami-event="talk-cta-book-50-first-dates">
Book This Talk
</a>
<a href="/speaking" class="btn-outline">← All Talks</a>
</footer>
</article>
</BaseLayout>
<style>
.talk-detail {
max-width: 800px;
margin: 0 auto;
padding: 4rem 2rem;
}
.talk-header {
text-align: center;
margin-bottom: 3rem;
}
.talk-meta {
display: flex;
gap: 1rem;
justify-content: center;
margin-bottom: 1.5rem;
}
.talk-type {
background: var(--color-green);
color: white;
padding: 0.25rem 0.75rem;
border-radius: 4px;
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.talk-duration {
color: var(--color-text-muted);
font-size: 0.875rem;
}
.talk-header h1 {
font-family: var(--font-heading);
font-size: clamp(1.75rem, 4vw, 2.5rem);
color: var(--color-brown-dark);
margin: 0 0 1rem;
}
.talk-premise {
font-size: 1.125rem;
color: var(--color-text-muted);
font-style: italic;
max-width: 600px;
margin: 0 auto;
}
.talk-content section {
margin-bottom: 2.5rem;
}
.talk-content h2 {
font-family: var(--font-heading);
font-size: 1.25rem;
color: var(--color-brown-dark);
margin: 0 0 1rem;
}
.talk-description p {
color: var(--color-text);
line-height: 1.7;
margin: 0 0 1rem;
}
.talk-takeaways ul {
list-style: none;
padding: 0;
}
.talk-takeaways li {
padding: 0.75rem 0;
border-bottom: 1px solid var(--color-border);
position: relative;
padding-left: 1.5rem;
}
.talk-takeaways li:before {
content: "✓";
position: absolute;
left: 0;
color: var(--color-green);
font-weight: bold;
}
.audience-tags {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.audience-tag {
background: var(--color-cream);
border: 1px solid var(--color-border);
padding: 0.5rem 1rem;
border-radius: 100px;
font-size: 0.875rem;
color: var(--color-text);
}
.talk-cta {
display: flex;
gap: 1rem;
justify-content: center;
padding-top: 2rem;
border-top: 1px solid var(--color-border);
}
.btn-primary {
display: inline-block;
background: var(--color-amber);
color: white;
padding: 0.75rem 1.5rem;
border-radius: 6px;
text-decoration: none;
font-weight: 600;
}
.btn-outline {
display: inline-block;
background: transparent;
color: var(--color-text);
padding: 0.75rem 1.5rem;
border-radius: 6px;
text-decoration: none;
border: 1px solid var(--color-border);
}
</style>

View file

@ -0,0 +1,207 @@
---
import BaseLayout from '../../layouts/BaseLayout.astro';
const talk = {
title: "From Strip-Mining to Cultivation",
premise: "The shift from extraction to cultivation in AI-era teams. Why throughput optimization is killing your soil health.",
duration: "45–60 minutes",
type: "Keynote",
idealFor: ["CTOs", "VP Engineering", "People leaders", "Engineering managers"],
takeaways: [
"The difference between strip-mining and cultivation mindsets",
"How to audit your current practices for extraction vs. growth",
"A cultivation playbook you can implement this quarter"
],
description: `The most successful AI teams aren't the ones with the best models. They're the ones who stopped strip-mining their humans and started cultivating them.
For a decade, we've optimized engineering teams like strip-mining operations: extract maximum value, move fast, burn bright. It worked when the work was predictable and the humans were replaceable.
AI changes the equation. The work is no longer predictable — it's conversational, contextual, and constantly evolving. You can't strip-mine your way through agentic development. You need soil that gets richer over time.
This keynote shows the cultivation playbook: how to build teams where AI augments human capability instead of replacing it, where throughput is a byproduct of health, and where your best people don't just stay — they compound.`
};
---
<BaseLayout
title={`${talk.title} — Scott Scoble`}
description={talk.premise}
pageType="speaking"
>
<article class="talk-detail">
<header class="talk-header">
<div class="talk-meta">
<span class="talk-type">{talk.type}</span>
<span class="talk-duration">{talk.duration}</span>
</div>
<h1>{talk.title}</h1>
<p class="talk-premise">{talk.premise}</p>
</header>
<div class="talk-content">
<section class="talk-description">
<h2>The Talk</h2>
{talk.description.split('\n\n').map(para => (
<p>{para}</p>
))}
</section>
<section class="talk-takeaways">
<h2>What You'll Learn</h2>
<ul>
{talk.takeaways.map(takeaway => (
<li>{takeaway}</li>
))}
</ul>
</section>
<section class="talk-audience">
<h2>Ideal For</h2>
<div class="audience-tags">
{talk.idealFor.map(audience => (
<span class="audience-tag">{audience}</span>
))}
</div>
</section>
</div>
<footer class="talk-cta">
<a href="/speaking#book" class="btn-primary" data-umami-event="talk-cta-book-cultivation">
Book This Talk
</a>
<a href="/speaking" class="btn-outline">← All Talks</a>
</footer>
</article>
</BaseLayout>
<style>
.talk-detail {
max-width: 800px;
margin: 0 auto;
padding: 4rem 2rem;
}
.talk-header {
text-align: center;
margin-bottom: 3rem;
}
.talk-meta {
display: flex;
gap: 1rem;
justify-content: center;
margin-bottom: 1.5rem;
}
.talk-type {
background: var(--color-green);
color: white;
padding: 0.25rem 0.75rem;
border-radius: 4px;
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.talk-duration {
color: var(--color-text-muted);
font-size: 0.875rem;
}
.talk-header h1 {
font-family: var(--font-heading);
font-size: clamp(1.75rem, 4vw, 2.5rem);
color: var(--color-brown-dark);
margin: 0 0 1rem;
}
.talk-premise {
font-size: 1.125rem;
color: var(--color-text-muted);
font-style: italic;
max-width: 600px;
margin: 0 auto;
}
.talk-content section {
margin-bottom: 2.5rem;
}
.talk-content h2 {
font-family: var(--font-heading);
font-size: 1.25rem;
color: var(--color-brown-dark);
margin: 0 0 1rem;
}
.talk-description p {
color: var(--color-text);
line-height: 1.7;
margin: 0 0 1rem;
}
.talk-takeaways ul {
list-style: none;
padding: 0;
}
.talk-takeaways li {
padding: 0.75rem 0;
border-bottom: 1px solid var(--color-border);
position: relative;
padding-left: 1.5rem;
}
.talk-takeaways li:before {
content: "✓";
position: absolute;
left: 0;
color: var(--color-green);
font-weight: bold;
}
.audience-tags {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.audience-tag {
background: var(--color-cream);
border: 1px solid var(--color-border);
padding: 0.5rem 1rem;
border-radius: 100px;
font-size: 0.875rem;
color: var(--color-text);
}
.talk-cta {
display: flex;
gap: 1rem;
justify-content: center;
padding-top: 2rem;
border-top: 1px solid var(--color-border);
}
.btn-primary {
display: inline-block;
background: var(--color-amber);
color: white;
padding: 0.75rem 1.5rem;
border-radius: 6px;
text-decoration: none;
font-weight: 600;
}
.btn-outline {
display: inline-block;
background: transparent;
color: var(--color-text);
padding: 0.75rem 1.5rem;
border-radius: 6px;
text-decoration: none;
border: 1px solid var(--color-border);
}
</style>

View file

@ -477,3 +477,30 @@ code {
--size-4xl: 2.5rem;
}
}
/* Mobile touch targets (44px minimum) - Issue #65 */
@media (pointer: coarse) {
.nav-links a,
.footer-links a,
.book-link,
.talk-link,
.btn-primary,
.btn-outline {
min-height: 44px;
min-width: 44px;
display: inline-flex;
align-items: center;
justify-content: center;
}
}
/* Reduced motion - Issue #53 accessibility */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}