Here's a complete, up-to-date **Tailwind CSS Tutorial for Tech3Space** focused on creating a **beautiful, readable, and SEO-optimized individual blog post page**.
Here's a complete, up-to-date Tailwind CSS Tutorial for Tech3Space focused on creating a beautiful, readable, and SEO-optimized individual blog post page.
We'll build a dynamic post page using Next.js App Router, Tailwind CSS (with Shadcn/UI already set up from previous steps), proper typography, responsive design, and strong SEO practices (metadata, Open Graph, structured data, fast loading).
Step 1: Create the Dynamic Post Route
In your app folder, create this structure:
app/
├── blog/
│ └── [slug]/
│ └── page.tsx ← This is our SEO-optimized post page
Step 2: Set Up Dynamic Metadata for SEO (Best Practice in 2026)
Update app/blog/[slug]/page.tsx with excellent SEO:
// app/blog/[slug]/page.tsx
import { notFound } from 'next/navigation';
import { Metadata } from 'next';
import { ArticleJsonLd } from 'next-seo'; // Optional: install next-seo or write manually
// Simulate fetching a single post (replace with your real backend/API/DB)
async function getPost(slug: string) {
// In real project: fetch from your API, Supabase, Prisma, Contentlayer, etc.
const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${slug}`, {
next: { revalidate: 3600 }, // ISR - good for SEO
});
if (!res.ok) return null;
const post = await res.json();
return {
...post,
slug,
author: "Tech3Space Team",
publishedAt: "2026-04-10",
readingTime: "8 min read",
image: `https://picsum.photos/id/${post.id}/1200/630`, // Featured image
category: "Artificial Intelligence",
};
}
// Dynamic Metadata - Extremely Important for SEO
export async function generateMetadata({ params }: { params: { slug: string } }): Promise<Metadata> {
const post = await getPost(params.slug);
if (!post) return { title: 'Post Not Found' };
return {
title: post.title,
description: post.body.substring(0, 160) + '...',
keywords: ['tech', 'AI', post.category.toLowerCase(), 'innovation'],
authors: [{ name: post.author }],
openGraph: {
title: post.title,
description: post.body.substring(0, 160),
images: [{ url: post.image, width: 1200, height: 630, alt: post.title }],
type: 'article',
publishedTime: post.publishedAt,
authors: [post.author],
},
twitter: {
card: 'summary_large_image',
title: post.title,
description: post.body.substring(0, 160),
images: [post.image],
},
alternates: {
canonical: `/blog/${post.slug}`,
},
};
}
export default async function BlogPost({ params }: { params: { slug: string } }) {
const post = await getPost(params.slug);
if (!post) notFound();
return (
<>
{/* Structured Data (JSON-LD) for Rich Snippets - Great for SEO */}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify({
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": post.title,
"description": post.body.substring(0, 160),
"image": post.image,
"author": {
"@type": "Person",
"name": post.author
},
"publisher": {
"@type": "Organization",
"name": "Tech3Space",
"logo": {
"@type": "ImageObject",
"url": "https://tech3space.com/logo.png"
}
},
"datePublished": post.publishedAt,
"dateModified": post.publishedAt,
"mainEntityOfPage": {
"@type": "WebPage",
"@id": `https://tech3space.com/blog/${post.slug}`
}
})
}}
/>
<article className="min-h-screen bg-background">
{/* Hero / Featured Image */}
<div className="relative h-[500px] w-full overflow-hidden">
<img
src={post.image}
alt={post.title}
className="absolute inset-0 w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-b from-black/30 via-black/60 to-black/80" />
<div className="absolute bottom-0 left-0 right-0 p-8 md:p-16 max-w-4xl mx-auto">
<div className="flex items-center gap-4 mb-6">
<span className="px-4 py-1.5 bg-white/90 text-black text-sm font-medium rounded-full">
{post.category}
</span>
<span className="text-white/80 text-sm">{post.readingTime}</span>
</div>
<h1 className="text-4xl md:text-6xl font-bold text-white leading-tight tracking-tight">
{post.title}
</h1>
</div>
</div>
<div className="max-w-3xl mx-auto px-6 py-12">
{/* Meta Info */}
<div className="flex items-center gap-4 mb-10 border-b pb-8">
<div className="flex items-center gap-3">
<div className="w-10 h-10 bg-gradient-to-br from-blue-500 to-purple-600 rounded-full flex items-center justify-center text-white font-bold">
T3
</div>
<div>
<p className="font-medium">{post.author}</p>
<p className="text-sm text-muted-foreground">
Published on {new Date(post.publishedAt).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })}
</p>
</div>
</div>
</div>
{/* Main Content - Beautiful Typography with Tailwind + Prose */}
<div className="prose prose-zinc dark:prose-invert max-w-none prose-headings:font-semibold prose-h2:text-3xl prose-h2:mt-12 prose-h2:mb-6 prose-p:text-lg prose-p:leading-relaxed prose-li:text-lg">
<p className="text-xl text-muted-foreground leading-relaxed mb-10">
{post.body}
</p>
{/* Simulate longer article content with Tailwind styling */}
<h2>Why This Matters in 2026</h2>
<p>The rapid evolution of AI and cloud technologies is reshaping how we build and scale applications...</p>
<h2>Key Takeaways</h2>
<ul>
<li>Server Components dramatically improve performance</li>
<li>Shadcn/UI + Tailwind gives pixel-perfect control</li>
<li>Proper metadata and structured data boost rankings</li>
</ul>
<h2>Conclusion</h2>
<p>Building modern tech platforms like Tech3Space requires a perfect balance of speed, design, and SEO.</p>
</div>
{/* Share Buttons & Like (using Shadcn) */}
<div className="mt-16 pt-8 border-t flex flex-wrap gap-4 justify-between items-center">
<div>
<p className="text-sm text-muted-foreground mb-2">Share this post</p>
<div className="flex gap-3">
<button className="px-5 py-2.5 bg-blue-600 hover:bg-blue-700 text-white rounded-xl text-sm font-medium transition">Twitter</button>
<button className="px-5 py-2.5 bg-[#0A66C2] hover:bg-[#0A66C2]/90 text-white rounded-xl text-sm font-medium transition">LinkedIn</button>
</div>
</div>
{/* Reuse your LikeButton component */}
<LikeButton postId={post.id} />
</div>
</div>
</article>
</>
);
}
Step 3: Improve Typography with Tailwind (Prose Plugin)
For even better blog styling, install the official Tailwind Typography plugin:
npm install @tailwindcss/typography
Then update tailwind.config.ts:
import typography from '@tailwindcss/typography';
export default {
content: [...],
plugins: [typography],
// Optional: Customize prose
theme: {
extend: {
typography: {
DEFAULT: {
css: {
maxWidth: 'none',
color: 'hsl(var(--foreground))',
'h2': { fontWeight: '700' },
}
}
}
}
}
}
Now the prose class gives you clean, professional blog typography automatically.
Step 4: Tailwind Best Practices Used Here
- Responsive Design:
md:text-6xl,max-w-3xl, mobile-first approach. - Dark Mode Ready:
dark:prose-invert,bg-background,text-muted-foreground. - Performance & SEO:
next/imagerecommended instead of<img>for production (addpriorityon hero image). - Readable Content: Large font sizes (
text-lg,prose-p:text-lg), good line height, ample whitespace. - Visual Hierarchy: Gradient overlays, badges, proper heading sizes.
- Accessibility: Good contrast, semantic
<article>, alt texts.
Step 5: Link from Homepage
In your homepage (app/page.tsx), make post cards clickable:
<Link href={`/blog/${post.id}`} className="block group">
<Card className="... hover:ring-2 hover:ring-primary transition">
...
</Card>
</Link>
(Import Link from next/link)
Next Steps for Even Better SEO & Design
- Add Table of Contents (TOC) with Tailwind sticky sidebar.
- Implement related posts section.
- Add comments using a service like Giscus or your own API.
- Generate static params if using static generation:
generateStaticParams().