Tutorial Membuat Blog dengan Next.js, TailwindCSS dan Sanity CMS
Minggu, 22 Des 2024
Membangun blog modern tidak lagi serumit dulu. Dengan kombinasi Next.js, TailwindCSS, dan Sanity CMS, kamu bisa membuat blog yang cepat, SEO-friendly, dan mudah di-manage. Dalam tutorial ini, saya akan memandu kamu step-by-step dari nol hingga deploy.
Apa yang Akan Kita Bangun?
Kita akan membuat blog dengan fitur:
- Homepage dengan daftar artikel
- Halaman detail artikel dengan konten dari Sanity
- Styling modern dengan TailwindCSS
- CMS dashboard untuk mengelola konten
Prasyarat
- Node.js versi 18 atau lebih baru
- Text editor (VS Code recommended)
- Akun Sanity (gratis)
- Pengetahuan dasar React dan JavaScript
Step 1: Setup Project Next.js
Buka terminal dan jalankan command berikut untuk membuat project Next.js baru:
npx create-next-app@latest my-blog
cd my-blog

Saat ditanya, pilih opsi berikut:
- TypeScript: Yes
- ESLint: Yes
- Tailwind CSS: Yes
- src/ directory: Yes
- App Router: Yes
Step 2: Setup Sanity CMS
Install Sanity CLI dan buat project Sanity di dalam folder Next.js:
npm create sanity@latest -- --template clean --create-project "My Blog" --dataset production --output-path sanity

Ini akan membuat folder sanity di dalam project kamu dengan Sanity Studio.
Step 3: Buat Schema untuk Blog Post
Buat file schema untuk blog post di sanity/schemaTypes/post.ts:
import { defineField, defineType } from 'sanity'
export default defineType({
name: 'post',
title: 'Post',
type: 'document',
fields: [
defineField({
name: 'title',
title: 'Title',
type: 'string',
validation: (Rule) => Rule.required(),
}),
defineField({
name: 'slug',
title: 'Slug',
type: 'slug',
options: {
source: 'title',
maxLength: 96,
},
validation: (Rule) => Rule.required(),
}),
defineField({
name: 'excerpt',
title: 'Excerpt',
type: 'text',
rows: 3,
}),
defineField({
name: 'mainImage',
title: 'Main image',
type: 'image',
options: {
hotspot: true,
},
}),
defineField({
name: 'publishedAt',
title: 'Published at',
type: 'datetime',
}),
defineField({
name: 'body',
title: 'Body',
type: 'array',
of: [
{ type: 'block' },
{ type: 'image' },
],
}),
],
})

Lalu register schema di sanity/schemaTypes/index.ts:
import post from './post'
export const schemaTypes = [post]
Step 4: Jalankan Sanity Studio
Masuk ke folder sanity dan jalankan studio:
cd sanity
npm run dev

Buka http://localhost:3333 dan buat beberapa post untuk testing.
Step 5: Install Sanity Client di Next.js
Kembali ke root project dan install dependencies:
cd ..
npm install @sanity/client @sanity/image-url @portabletext/react
Buat file src/lib/sanity.ts untuk konfigurasi client:
import { createClient } from '@sanity/client'
import imageUrlBuilder from '@sanity/image-url'
export const client = createClient({
projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!,
dataset: 'production',
useCdn: true,
apiVersion: '2024-01-01',
})
const builder = imageUrlBuilder(client)
export function urlFor(source: any) {
return builder.image(source)
}
Tambahkan environment variable di .env.local:
NEXT_PUBLIC_SANITY_PROJECT_ID=your_project_id
Step 6: Buat Halaman Blog List
Edit src/app/page.tsx untuk menampilkan daftar blog:
import { client, urlFor } from '@/lib/sanity'
import Link from 'next/link'
import Image from 'next/image'
async function getPosts() {
const query = `*[_type == "post"] | order(publishedAt desc) {
_id,
title,
slug,
excerpt,
mainImage,
publishedAt
}`
return client.fetch(query)
}
export default async function Home() {
const posts = await getPosts()
return (
<main className="max-w-4xl mx-auto px-4 py-12">
<h1 className="text-4xl font-bold mb-8">My Blog</h1>
<div className="grid gap-8">
{posts.map((post: any) => (
<Link
key={post._id}
href={`/blog/${post.slug.current}`}
className="group"
>
<article className="border rounded-lg overflow-hidden hover:shadow-lg transition">
{post.mainImage && (
<Image
src={urlFor(post.mainImage).width(800).height(400).url()}
alt={post.title}
width={800}
height={400}
className="w-full h-48 object-cover"
/>
)}
<div className="p-6">
<h2 className="text-2xl font-semibold group-hover:text-blue-600">
{post.title}
</h2>
<p className="text-gray-600 mt-2">{post.excerpt}</p>
</div>
</article>
</Link>
))}
</div>
</main>
)
}

Step 7: Buat Halaman Detail Post
Buat file src/app/blog/[slug]/page.tsx:
import { client, urlFor } from '@/lib/sanity'
import { PortableText } from '@portabletext/react'
import Image from 'next/image'
import { notFound } from 'next/navigation'
async function getPost(slug: string) {
const query = `*[_type == "post" && slug.current == $slug][0] {
_id,
title,
slug,
mainImage,
publishedAt,
body
}`
return client.fetch(query, { slug })
}
export default async function BlogPost({
params
}: {
params: { slug: string }
}) {
const post = await getPost(params.slug)
if (!post) {
notFound()
}
return (
<article className="max-w-3xl mx-auto px-4 py-12">
{post.mainImage && (
<Image
src={urlFor(post.mainImage).width(1200).height(600).url()}
alt={post.title}
width={1200}
height={600}
className="w-full rounded-lg mb-8"
/>
)}
<h1 className="text-4xl font-bold mb-4">{post.title}</h1>
<time className="text-gray-500 mb-8 block">
{new Date(post.publishedAt).toLocaleDateString('id-ID', {
year: 'numeric',
month: 'long',
day: 'numeric'
})}
</time>
<div className="prose prose-lg max-w-none">
<PortableText value={post.body} />
</div>
</article>
)
}
Step 8: Styling dengan TailwindCSS
Install plugin typography untuk styling konten:
npm install @tailwindcss/typography

Tambahkan ke tailwind.config.ts:
import type { Config } from 'tailwindcss'
const config: Config = {
content: [
'./src/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {
extend: {},
},
plugins: [
require('@tailwindcss/typography'),
],
}
export default config
Step 9: Konfigurasi Next.js untuk Gambar
Tambahkan domain Sanity di next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'cdn.sanity.io',
},
],
},
}
module.exports = nextConfig
Step 10: Jalankan Project
Sekarang jalankan project Next.js:
npm run dev
Buka http://localhost:3000 dan lihat blog kamu!
Kesimpulan
Selamat! Kamu sudah berhasil membuat blog dengan Next.js, TailwindCSS, dan Sanity CMS. Kombinasi ini sangat powerful karena:
- Next.js memberikan performa dan SEO yang excellent
- TailwindCSS membuat styling cepat dan konsisten
- Sanity CMS memberikan dashboard yang user-friendly untuk mengelola konten
Ada pertanyaan? Reach out ke saya di Twitter @nayakayp!