Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
6fdef6d
Blog about better using AI Infrastructure via MIG
shkatara Jul 15, 2026
b60af2a
hostname
shkatara Jul 15, 2026
881d707
Add Dashboard
shkatara Jul 15, 2026
d3dcdde
Rework MIG post: GPU sharing story, full command lifecycle, light dia…
saiyam1814 Jul 17, 2026
2869365
MIG post: replace reconstructed outputs with real captures from the box
saiyam1814 Jul 17, 2026
84c5e1e
Regenerate vercel.json redirects (draft post excluded)
saiyam1814 Jul 17, 2026
bfab3d9
MIG post: explain sharing mechanisms from CUDA-context first principles
saiyam1814 Jul 19, 2026
38e5fb2
MIG post: correct time-slicing with preemption history and switch cost
saiyam1814 Jul 19, 2026
5ac89e3
MIG post: align sharing section with GPU book, add fairness and MPS n…
saiyam1814 Jul 19, 2026
5d69437
Merge main, regenerate feeds and redirects
saiyam1814 Jul 20, 2026
a50e5db
Support co-authored posts; credit Shubham and Saiyam on the MIG post
saiyam1814 Jul 20, 2026
5206b4d
MIG post: technical fixes + Utho hardware-partner callouts
saiyam1814 Jul 20, 2026
c6ef5c1
MIG post: move Utho thank-you CTA above the author bios
saiyam1814 Jul 20, 2026
53afc23
MIG post: real Utho UTM link + theme-aware logo in the sponsor CTA
saiyam1814 Jul 20, 2026
af72dc2
MIG post: use official Utho logo in the sponsor CTA
saiyam1814 Jul 20, 2026
2f2c53d
MIG post: use the full Utho CTA card at the top too (bookend the post)
saiyam1814 Jul 20, 2026
63c4788
MIG post: fix Utho UTM campaign (S -> Saiyam) per Utho
saiyam1814 Jul 20, 2026
737508d
Publish MIG post: flip draft off, regenerate feeds and redirects
saiyam1814 Jul 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 60 additions & 38 deletions app/blog/[slug]/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import BlogToc from '@/components/BlogToc';
import BlogShareBar from '@/components/BlogShareBar';
import CodeBlockEnhancer from '@/components/CodeBlockEnhancer';
import NewsletterCTA from '@/components/NewsletterCTA';
import SponsorCallout from '@/components/SponsorCallout';
import AuthorSocials from '@/components/AuthorSocials';
import Comments from '@/components/Comments';

Expand All @@ -32,7 +33,7 @@ export async function generateMetadata({ params }) {
title: post.seoTitle || post.title,
description: post.seoDescription || undefined,
keywords: post.tags,
authors: [{ name: post.author.name, url: post.author.url }],
authors: post.authors.map((a) => ({ name: a.name, url: a.url })),
alternates: { canonical: url },
openGraph: {
type: 'article',
Expand All @@ -42,7 +43,7 @@ export async function generateMetadata({ params }) {
siteName: SITE.name,
images: [{ url: ogImage, width: 1200, height: 630, alt: post.title }],
publishedTime: post.datePublished,
authors: [post.author.name],
authors: post.authors.map((a) => a.name),
tags: post.tags,
},
twitter: {
Expand Down Expand Up @@ -84,15 +85,15 @@ export default async function BlogPost({ params }) {
dateModified: post.datePublished,
inLanguage: 'en-US',
isAccessibleForFree: true,
author: {
author: post.authors.map((a) => ({
'@type': 'Person',
'@id': post.author.url,
name: post.author.name,
url: post.author.url,
image: post.author.avatar?.startsWith('http') ? post.author.avatar : `${SITE.url}${post.author.avatar}`,
sameAs: post.author.sameAs?.length ? post.author.sameAs : undefined,
...(post.author.bio ? { description: post.author.bio } : {}),
},
'@id': a.url,
name: a.name,
url: a.url,
image: a.avatar?.startsWith('http') ? a.avatar : `${SITE.url}${a.avatar}`,
sameAs: a.sameAs?.length ? a.sameAs : undefined,
...(a.bio ? { description: a.bio } : {}),
})),
publisher: {
'@type': 'Organization',
'@id': 'https://kubesimplify.com#org',
Expand Down Expand Up @@ -189,16 +190,31 @@ export default async function BlogPost({ params }) {
</p>
)}
<div className="flex items-center gap-3 text-sm" style={{ color: 'var(--text-muted)' }}>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={post.author.avatar} alt="" className="w-8 h-8 rounded-full" />
<div className="flex -space-x-2">
{post.authors.map((a) => (
/* eslint-disable-next-line @next/next/no-img-element */
<img
key={a.handle}
src={a.avatar}
alt=""
className="w-8 h-8 rounded-full ring-2"
style={{ '--tw-ring-color': 'var(--bg-base)' }}
/>
))}
</div>
<div>
<Link
href={`/blog/author/${post.author.handle}`}
className="font-semibold hover:text-[var(--accent)] transition-colors"
style={{ color: 'var(--text-primary)' }}
>
{post.author.name}
</Link>
{post.authors.map((a, i) => (
<span key={a.handle}>
{i > 0 && <span className="mx-1">&amp;</span>}
<Link
href={`/blog/author/${a.handle}`}
className="font-semibold hover:text-[var(--accent)] transition-colors"
style={{ color: 'var(--text-primary)' }}
>
{a.name}
</Link>
</span>
))}
<span className="mx-2">·</span>
<time dateTime={post.datePublished}>{formatDate(post.datePublished)}</time>
<span className="mx-2">·</span>
Expand All @@ -223,6 +239,8 @@ export default async function BlogPost({ params }) {
/>
)}

<SponsorCallout sponsor={post.sponsor} variant="cta" />

<SeriesBanner info={seriesInfo} />

{/* Mobile TOC (desktop has it in the right sidebar) */}
Expand All @@ -249,25 +267,29 @@ export default async function BlogPost({ params }) {

<hr className="my-12" style={{ borderColor: 'var(--border-subtle)' }} />

<section className="glass-card rounded-2xl p-6 mb-10 flex items-start gap-4 flex-wrap">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={post.author.avatar} alt="" className="w-14 h-14 rounded-full object-cover" />
<div className="flex-1 min-w-0">
<Link
href={`/blog/author/${post.author.handle}`}
className="font-bold mb-1 inline-block hover:text-[var(--accent)] transition-colors"
style={{ color: 'var(--text-primary)' }}
>
{post.author.name}
</Link>
{post.author.bio && (
<p className="text-sm mb-3" style={{ color: 'var(--text-secondary)' }}>
{post.author.bio}
</p>
)}
<AuthorSocials socials={post.author.socials} />
</div>
</section>
<SponsorCallout sponsor={post.sponsor} variant="cta" />

{post.authors.map((a) => (
<section key={a.handle} className="glass-card rounded-2xl p-6 mb-10 flex items-start gap-4 flex-wrap">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={a.avatar} alt="" className="w-14 h-14 rounded-full object-cover" />
<div className="flex-1 min-w-0">
<Link
href={`/blog/author/${a.handle}`}
className="font-bold mb-1 inline-block hover:text-[var(--accent)] transition-colors"
style={{ color: 'var(--text-primary)' }}
>
{a.name}
</Link>
{a.bio && (
<p className="text-sm mb-3" style={{ color: 'var(--text-secondary)' }}>
{a.bio}
</p>
)}
<AuthorSocials socials={a.socials} />
</div>
</section>
))}

<NewsletterCTA variant="inline" />

Expand Down
6 changes: 6 additions & 0 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -522,3 +522,9 @@ a:focus-visible, button:focus-visible {
border-right: 1px solid var(--border-subtle);
border-bottom: 1px solid var(--border-subtle);
}

/* Sponsor logo: show the dark-colored mark on light theme, the white mark on dark theme */
.sponsor-logo--light { display: inline-block; }
.sponsor-logo--dark { display: none; }
.dark .sponsor-logo--light { display: none; }
.dark .sponsor-logo--dark { display: inline-block; }
10 changes: 7 additions & 3 deletions components/BlogCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,14 @@ export default function BlogCard({ post, featured = false }) {
)}
<div className="mt-auto pt-3 border-t flex items-center justify-between" style={{ borderColor: 'var(--border-subtle)' }}>
<div className="flex items-center gap-2">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={post.author.avatar} alt={post.author.name} className="w-5 h-5 rounded-full object-cover" />
<div className="flex -space-x-1.5">
{(post.authors || [post.author]).map((a) => (
/* eslint-disable-next-line @next/next/no-img-element */
<img key={a.handle} src={a.avatar} alt={a.name} className="w-5 h-5 rounded-full object-cover" />
))}
</div>
<span className="text-[11px]" style={{ color: 'var(--text-muted)' }}>
{post.author.name} · {post.readMinutes} min
{(post.authors || [post.author]).map((a) => a.name).join(' & ')} · {post.readMinutes} min
</span>
</div>
<span className="text-xs font-semibold text-[var(--accent)] opacity-0 group-hover:opacity-100 transition-opacity">
Expand Down
91 changes: 91 additions & 0 deletions components/SponsorCallout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**
* Sponsor / hardware-partner callout, driven by a post's `sponsor` frontmatter:
*
* sponsor:
* name: Utho
* url: https://utho.com/... # full link (UTM params included)
* blurb: "One-line thank-you shown in the end CTA."
*
* `variant="strip"` renders a slim disclosure line (placed near the top).
* `variant="cta"` renders the end-of-post thank-you card.
* Renders nothing unless name + url are present, so non-sponsored posts are unaffected.
* Links use rel="sponsored" per Google's paid-link guidance.
*/
export default function SponsorCallout({ sponsor, variant = 'strip' }) {
if (!sponsor || !sponsor.name || !sponsor.url) return null;
const { name, url, blurb, logoLight, logoDark } = sponsor;
const hasLogo = logoLight && logoDark;

if (variant === 'strip') {
return (
<div
className="rounded-xl px-4 py-3 mb-8 flex items-center gap-x-3 gap-y-1 flex-wrap text-sm"
style={{ background: 'var(--bg-elevated)', border: '1px solid var(--border-subtle)' }}
>
<span
className="text-[11px] font-bold uppercase tracking-[0.15em]"
style={{ color: 'var(--text-muted)' }}
>
Hardware partner
</span>
<span style={{ color: 'var(--text-secondary)' }}>
The GPU node in this post was provided by{' '}
<a
href={url}
target="_blank"
rel="noopener sponsored"
className="font-semibold text-[var(--accent)] hover:underline"
>
{name}
</a>
.
</span>
</div>
);
}

return (
<section
className="rounded-2xl p-8 my-12 text-center"
style={{
background: 'linear-gradient(135deg, var(--accent-secondary)15, var(--accent)15)',
border: '1px solid var(--border-subtle)',
}}
>
<p
className="text-[11px] font-bold uppercase tracking-[0.2em] mb-3"
style={{ color: 'var(--accent)' }}
>
Thanks to our hardware partner
</p>
{hasLogo ? (
<div className="mb-4 flex justify-center">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={logoLight} alt={name} className="sponsor-logo--light h-10 w-auto" />
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={logoDark} alt={name} className="sponsor-logo--dark h-10 w-auto" />
</div>
) : (
<h3 className="text-2xl md:text-3xl font-bold mb-3" style={{ color: 'var(--text-primary)' }}>
{name}
</h3>
)}
{blurb && (
<p className="text-base mb-6 max-w-xl mx-auto" style={{ color: 'var(--text-secondary)' }}>
{blurb}
</p>
)}
<a
href={url}
target="_blank"
rel="noopener sponsored"
className="inline-flex items-center gap-2 rounded-full px-6 py-3 text-sm font-semibold text-white gradient-bg transition-transform hover:scale-105"
>
Explore {name}
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
</svg>
</a>
</section>
);
}
Loading
Loading