import Hero from "@/components/home-page/hero";
import FeaturedPosts from "@/components/home-page/featured-posts";
export default function HomePage() {
return (
<>
<Hero />
<FeaturedPosts />
</>
);
}
// 1) Hero : 환영 섹션, 주요 상품을 소개. => 자기소개
// 2) Featured Posts: 더미 포스트 표시, 나중에 실제 게시물로 교체.
import Image from "next/image";
import classes from "./hero.module.css";
export default function Hero() {
return (
<section className={classes.hero}>
<div className={classes.image}>
<Image
src="/images/site/rui.png"
alt="An image showing Zoe"
width={300}
height={300}
/>
</div>
<h1>Hi, I'm Zoe</h1>
<p>
I blog about web development - especially frontend frameworkes like
React.
</p>
</section>
);
}
<Image/>
컴포넌트는 표시하는 스크린의 크기 등에 따라 크기가 다른 이미지를 표시할 수 없다면, 해당 문서를 참고하여 이미지에 대한 여러 구성 방법을 알아볼 수 있다.
import MainNavigation from "./main-navigation";
export default function Layout({ children }) {
return (
<>
<MainNavigation />
<main>{children}</main>
</>
);
}
import "../styles/globals.css";
import Layout from "@/components/layout/layout";
function MyApp({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
);
}
export default MyApp;
import Logo from "./logo";
import Link from "next/link";
import classes from "./main-navigation.module.css";
export default function MainNavigation() {
return (
<header className={classes.header}>
<Link href="/">
<Logo />
</Link>
<nav>
<ul>
<li>
<Link href="/posts">Posts</Link>
</li>
<li>
<Link href="/contact">Contact</Link>
</li>
</ul>
</nav>
</header>
);
}
import classes from "./logo.module.css";
export default function Logo() {
return <div className={classes.logo}>Zoe's Next Blog</div>;
}
import Hero from "@/components/home-page/hero";
import FeaturedPosts from "@/components/home-page/featured-posts";
const DUMMY_POSTS = [
{
title: "Getting Started With NextJS",
image: "getting-started-nextjs.png",
slug: "getting-started-with-nextjs",
excerpt: "NextJS is a the React framework for production.",
date: "2024-04-15",
},
{
title: "Getting Started With NextJS",
image: "getting-started-nextjs.png",
slug: "getting-started-with-nextjs2",
excerpt: "NextJS is a the React framework for production.",
date: "2024-04-15",
},
{
title: "Getting Started With NextJS",
image: "getting-started-nextjs.png",
slug: "getting-started-with-nextjs3",
excerpt: "NextJS is a the React framework for production.",
date: "2024-04-15",
},
{
title: "Getting Started With NextJS",
image: "getting-started-nextjs.png",
slug: "getting-started-with-nextjs4",
excerpt: "NextJS is a the React framework for production.",
date: "2024-04-15",
},
];
export default function HomePage() {
return (
<>
<Hero />
<FeaturedPosts posts={DUMMY_POSTS} />
</>
);
}
DUMMY_POSTS 데이터 추가
import classes from "./featured-posts.module.css";
import PostsGrid from "../posts/posts-grid";
export default function FeaturedPosts({ posts }) {
return (
<section className={classes.latest}>
<h2>Featured Posts</h2>
<PostsGrid posts={posts} />
</section>
);
}
import PostItem from "./post-item";
import classes from "./posts-grid.module.css";
export default function PostsGrid({ posts }) {
return (
<ul className={classes.grid}>
{posts.map((post) => (
<PostItem key={post.slug} post={post} />
))}
</ul>
);
}
import classes from "./post-item.module.css";
import Link from "next/link";
import Image from "next/image";
export default function PostItem({ post }) {
const { title, image, excerpt, date, slug } = post;
const formatted_date = new Date(date).toLocaleDateString("ko-KR", {
day: "numeric",
month: "long",
year: "numeric",
});
return (
<li className={classes.post}>
<Link href={`/posts/${slug}`}>
<div className={classes.image}>
<Image
src={`/images/posts/${slug}/${image}`}
alt={title}
width={300}
height={200}
/>
</div>
<div className={classes.content}>
<h3>{title}</h3>
<time>{formatted_date}</time>
<p>{excerpt}</p>
</div>
</Link>
</li>
);
}
<Image/>
의 layout
은 기본적으로 intrisic으로 설정되어 있다. 이를 responsive로 설정하여 이미지가 더 보기 좋게 설정한다.// components/posts/all-posts.js
import classes from "./all-posts.module.css";
import PostsGrid from "./posts-grid";
export default function AllPosts({ posts }) {
return (
<section className={classes.posts}>
<h1>All Posts</h1>
<PostsGrid posts={posts} />
</section>
);
}
// pages/posts/index.js
import AllPosts from "@/components/posts/all-posts";
const DUMMY_POSTS = [
{
title: "Getting Started With NextJS",
image: "getting-started-nextjs.png",
slug: "getting-started-with-nextjs",
excerpt: "NextJS is a the React framework for production.",
date: "2024-04-15",
},
{
title: "Getting Started With NextJS",
image: "getting-started-nextjs.png",
slug: "getting-started-with-nextjs2",
excerpt: "NextJS is a the React framework for production.",
date: "2024-04-15",
},
{
title: "Getting Started With NextJS",
image: "getting-started-nextjs.png",
slug: "getting-started-with-nextjs3",
excerpt: "NextJS is a the React framework for production.",
date: "2024-04-15",
},
{
title: "Getting Started With NextJS",
image: "getting-started-nextjs.png",
slug: "getting-started-with-nextjs4",
excerpt: "NextJS is a the React framework for production.",
date: "2024-04-15",
},
];
export default function AllPostsPage() {
return <AllPosts posts={DUMMY_POSTS} />;
}
// components/posts/post-detail/post-header.js
import classes from "./post-header.module.css";
import Image from "next/image";
export default function PostHeader({ title, image }) {
return (
<header className={classes.header}>
<h1>{title}</h1>
<Image src={image} alt={title} width={200} height={150} />
</header>
);
}
// components/posts/post-detail/post-content.js
import classes from "./post-content.module.css";
import PostHeader from "./post-header";
const DUMMY_POST = {
title: "Getting Started With NextJS",
image: "getting-started-nextjs.png",
slug: "getting-started-with-nextjs",
content: "# This is a first post.",
date: "2024-04-15",
};
export default function PostContent() {
return (
<article className={classes.content}>
<PostHeader
title={DUMMY_POST.title}
image={`/images/posts/${DUMMY_POST.slug}/${DUMMY_POST.image}`}
/>
{DUMMY_POST.content}
</article>
);
}
// pages/posts/[slug].js
import PostContent from "@/components/posts/post-detail/post-content";
export default function PostDetailPage() {
return <PostContent />;
}