NextJS For Beginners

back

Designing the Homepage

post image

The Homepage

The code for out homepage is located at pages/index.tsx and its role is to display a grid of all blog posts. The page consists of several key components including post cards that display titles, excerpts, metadata, a responsive grid layout, and sorting functionality by date.

const Home = ({ posts }: HomeProps) => { return ( <div> <Head> <title>Next.js For Beginners</title> </Head> <div className="posts"> {posts.map((post, index) => ( <Post key={index} post={post} /> ))} </div> </div> ); }; export default Home;

Data Fetching Implementation

The homepage uses static generation to fetch post data at build time through the getStaticProps function. This function reads markdown files from the posts directory, extracts their frontmatter, and returns the processed posts sorted by date.

export async function getStaticProps(): Promise<{ props: HomeProps }> { const files = fs.readdirSync(path.join("posts")); const posts = files.map((filename) => { const slug = filename.replace(".md", ""); const markdownWithMeta = fs.readFileSync( path.join("posts", filename), "utf-8" ); const { data: frontmatter } = matter(markdownWithMeta) as unknown as { data: Frontmatter; }; return { slug, frontmatter, }; }); return { props: { posts: posts.sort(sortByDate), }, }; }

Posts are sorted chronologically using a utility function that compares dates. This ensures that the oldest post appears first in the grid layout.

export const sortByDate = ( a: { frontmatter: { date: string | number | Date } }, b: { frontmatter: { date: string | number | Date } } ): number => { return ( (new Date(a.frontmatter.date) as unknown as number) - (new Date(b.frontmatter.date) as unknown as number) ); };

The Post Component

The reusable Post component, located at components/Post.tsx, displays post previews in a consistent format. Each post card includes a cover image, publication date, title, excerpt, and a link to read the full article.

const greyBlur: string = "data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAQAAAAfQ//73v/+BiOh/AAA="; const Post = ({ post }: PostProps) => { return ( <div className="card"> <div style={{ position: "relative", width: "100%", height: "15rem", marginBottom: "3rem", }} > <Image src={post.frontmatter.cover_image} alt="cover image" fill style={{ objectFit: "cover" }} unoptimized placeholder="blur" blurDataURL={greyBlur} /> </div> <div className="post-date">Posted on {post.frontmatter.date}</div> <h3>{post.frontmatter.title}</h3> <p>{post.frontmatter.excerpt}</p> <Link href={`/blog/${post.slug}`} className="btn"> read </Link> </div> ); }; export default Post;

Responsive Considerations

The design employs a breakpoint strategy that switches from a two-column layout to a single column at 800px (50rem) viewport width. Images within cards scale responsively and benefit from Next.js's built-in lazy loading capabilities through the Image component.

Performance Optimizations

Static generation provides significant performance benefits by pre-rendering content at build time. This approach eliminates the need for client-side data fetching, resulting in faster initial page loads. The implementation keeps bundle sizes small by avoiding heavy libraries and loading only essential components.

Accessibility Features

The homepage follows accessibility best practices by using semantic HTML elements. It maintains a proper heading hierarchy with h1 for the page title and h3 for post titles. Interactive elements include meaningful link text and clear visual focus states for keyboard navigation. All images include descriptive alt text.

Future Enhancements

Potential improvements to the homepage include implementing pagination for blogs with many posts, adding filtering by category or tag, creating a featured posts section, and incorporating search functionality. These enhancements would improve navigation and content discovery as the blog grows.