Setup {#setup}
Create a new Next.js 14 project:
npx create-next-app@latest nextjs-blog
cd nextjs-blog
npm run dev
Blog Listing Page
Create app/blog/page.js:
```jsx
import Link from 'next/link';
async function getPosts() {
const res = await fetch('https://jsonplaceholder.typicode.com/posts');
return res.json();
}
export default async function BlogPage() {
const posts = await getPosts();
return (
<div>
<h1>Our Blog</h1>
<ul>
{posts.slice(0, 5).map((post) => (
<li key={post.id}>
<Link href={`/blog/${post.id}`}>
<h2>{post.title}</h2>
<p>{post.body.substring(0, 50)}...</p>
</Link>
</li>
))}
</ul>
</div>
);
}
Dynamic Blog Pages {#dynamic-pages}
Create app/blog/[slug]/page.js:
async function getPost(slug) {
const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${slug}`);
return res.json();
}
export async function generateMetadata({ params }) {
const post = await getPost(params.slug);
return {
title: `${post.title} | Next.js Blog`,
description: post.body.substring(0, 160),
};
}
export default async function BlogPost({ params }) {
const post = await getPost(params.slug);
return (
<article>
<h1>{post.title}</h1>
<p>{post.body}</p>
</article>
);
}
Deployment {#deployment}
- Push code to GitHub
- Import project on Vercel
- Deploy automatically
Your blog will be live at your-app.vercel.app