Overview

>

Frontend-development

Frontend Development: Building Components with Tailwind CSS

In this module, you’ll learn how to build the frontend of a social media application similar to Twitter using Next.js 15 and Tailwind CSS. We’ll guide you through setting up the project, creating reusable components relevant to a social media platform, and styling them effectively. By the end of this module, you’ll have a solid understanding of how to build a modern, responsive web application using these cutting-edge technologies.

Estimated reading time: ~40 minutes


Table of Contents

  1. Introduction to Frontend Development
  2. Prerequisites
  3. Setting Up the Next.js 15 Project with Tailwind CSS
  4. Understanding Components in Next.js 15
  5. Building the Social Media App Components
    • Navigation Bar
    • Tweet/Post Component
    • Feed Component
    • Profile Component
  6. Styling with Tailwind CSS
    • Using Utility Classes
    • Responsive Design
    • State Variants
  7. Fetching Data from the Backend
  8. Best Practices
  9. Conclusion
  10. Additional Resources

Introduction to Frontend Development

Frontend development focuses on building the user interface and experience of web applications. By using modern tools like Next.js and Tailwind CSS, developers can create efficient, scalable, and responsive applications.

  • Next.js 15 is a React framework that enables server-side rendering, static site generation, and offers a new App Router architecture, making it ideal for building performant applications.
  • Tailwind CSS is a utility-first CSS framework that allows you to style components directly in your markup, providing flexibility and efficiency.

In this module, we’ll combine these technologies to build the frontend of a social media app.


Prerequisites

Before starting, make sure you have:

  • Basic knowledge of JavaScript, React, and TypeScript
  • Node.js 18.18 or later installed: Verify by running node -v
  • Code Editor: VS Code is recommended
  • Understanding of CSS fundamentals

Setting Up the Next.js 15 Project with Tailwind CSS

1. Verify Node.js Installation

Ensure you have Node.js 18.18 or later installed:

node -v

If not, download and install the latest version from the Node.js official website.

2. Create a New Next.js App

Run the following command to create a new Next.js 15 project:

npx create-next-app@latest

Configuration Options

During setup, you’ll be prompted to configure your project. For this application, consider the following options:

  • What is your project named? social-media-app
  • Would you like to use TypeScript? Yes
  • Would you like to use ESLint? Yes
  • Would you like to use Tailwind CSS? Yes
  • Would you like to use src/ directory? No (or Yes, depending on your preference)
  • Would you like to use App Router? (recommended) Yes
  • Would you like to customize the default import alias? Yes (accept the default @/*)

These settings provide a robust foundation for your application.

Navigate to the project directory:

cd social-media-app

3. Project Structure

Next.js 15 introduces the App Router, which utilizes the app/ directory for routing. Your project structure should look like this:

social-media-app/
├── app/
│   ├── layout.tsx
│   ├── page.tsx
│   └── api/
├── public/
├── styles/
├── next.config.js
├── package.json
└── tsconfig.json

  • app/layout.tsx: Defines the root layout of your application.
  • app/page.tsx: Serves as the main entry point for your application.
  • app/api/: Contains API route handlers.

4. Tailwind CSS Setup

Since you selected Tailwind CSS during project setup, it is already configured. Verify the tailwind.config.js file:

// tailwind.config.js
module.exports = {
  content: [
    './app/**/*.{js,ts,jsx,tsx}', // Include the app directory
    './components/**/*.{js,ts,jsx,tsx}', // Include the components directory
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};

Ensure that Tailwind directives are included in your global CSS file (styles/globals.css):

@tailwind base;
@tailwind components;
@tailwind utilities;

5. Start the Development Server

Run the development server:

npm run dev

Visit http://localhost:3000 to see your Next.js app running.


Understanding Components in Next.js 15

In Next.js 15, components are organized within the app directory. Each folder inside app can contain:

  • Page Components: The main content for each page on your site.
    • Named page.tsx or page.jsx
  • Layout Components: Create a consistent look and feel across multiple pages, such as a header, footer, or navbar.
    • Named layout.tsx or layout.jsx
  • Server Components: Fetch and render content on the server, ideal for static or SEO-friendly content.
    • Default type for components in Next.js 15’s app directory.
  • Client Components: Enable interactivity and handle user interactions.
    • Defined by adding 'use client'; at the top of the file.

Note: Next.js 15 supports React 19, which introduces features like Server Actions and improved hydration error handling.


Building the Social Media App Components

We’ll build the following components:

  1. Navigation Bar
  2. Tweet/Post Component
  3. Feed Component
  4. Profile Component

Folder Structure

Organize your components within the app and components directories:

social-media-app/
├── app/
│   ├── feed/
│   │   ├── page.tsx
│   │   └── Tweet.tsx
│   ├── profile/
│   │   ├── page.tsx
│   │   └── ProfileInfo.tsx
│   ├── layout.tsx
│   └── page.tsx
├── components/
│   └── Navbar.tsx
└── styles/
    └── globals.css


1. Create the Navbar Component

Create a components directory and add Navbar.tsx:

// components/Navbar.tsx
'use client';

import Link from 'next/link';
import Image from 'next/image';

export default function Navbar() {
  return (
    <nav className="bg-white border-b border-gray-200">
      <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
        <div className="flex justify-between h-16">
          <div className="flex">
            <Link href="/" className="flex-shrink-0 flex items-center">
              <Image
                className="h-8 w-8"
                src="/logo.svg"
                alt="Logo"
                width={32}
                height={32}
              />
              <span className="ml-2 font-bold text-xl">MySocialApp</span>
            </Link>
            <div className="hidden sm:-my-px sm:ml-6 sm:flex sm:space-x-8">
              <Link href="/feed" className="inline-flex items-center px-1 pt-1 text-sm font-medium text-gray-900">
                Home
              </Link>
              <Link href="/profile" className="inline-flex items-center px-1 pt-1 text-sm font-medium text-gray-500 hover:text-gray-700">
                Profile
              </Link>
            </div>
          </div>
          <div className="flex items-center">
            <button className="text-sm font-medium text-gray-500 hover:text-gray-700">Logout</button>
          </div>
        </div>
      </div>
    </nav>
  );
}

Explanation:

  • Uses Next.js Link component for navigation.
  • Includes links to Home and Profile.
  • Utilizes Tailwind CSS classes for styling.

2. Include Navbar in the Layout

Update app/layout.tsx:

// app/layout.tsx
import '../styles/globals.css';
import Navbar from '@/components/Navbar';
import { ReactNode } from 'react';

export const metadata = {
  title: 'MySocialApp',
  description: 'A social media app built with Next.js 15 and Tailwind CSS',
};

export default function RootLayout({ children }: { children: ReactNode }) {
  return (
    <html lang="en">
      <body>
        <Navbar />
        {children}
      </body>
    </html>
  );
}


Tweet/Post Component

1. Create the Tweet Component

Create app/feed/Tweet.tsx:

// app/feed/Tweet.tsx
'use client';

import Image from 'next/image';

interface TweetProps {
  tweet: {
    id: number;
    username: string;
    handle: string;
    time: string;
    content: string;
    comments: number;
    retweets: number;
    likes: number;
  };
}

export default function Tweet({ tweet }: TweetProps) {
  return (
    <div className="border-b border-gray-200 p-4">
      <div className="flex">
        <Image
          className="h-12 w-12 rounded-full"
          src="/default-avatar.png"
          alt="User Avatar"
          width={48}
          height={48}
        />
        <div className="ml-3">
          <div className="flex items-center">
            <span className="font-bold">{tweet.username}</span>
            <span className="ml-2 text-sm text-gray-500">@{tweet.handle}</span>
            <span className="ml-2 text-sm text-gray-500">· {tweet.time}</span>
          </div>
          <p className="mt-1">{tweet.content}</p>
          <div className="flex mt-2 space-x-4 text-gray-500">
            <button className="flex items-center space-x-1 hover:text-blue-500">
              {/* Add SVG icons or use icon libraries */}
              <span>{tweet.comments}</span>
            </button>
            <button className="flex items-center space-x-1 hover:text-green-500">
              <span>{tweet.retweets}</span>
            </button>
            <button className="flex items-center space-x-1 hover:text-red-500">
              <span>{tweet.likes}</span>
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

Explanation:

  • Displays tweet content with user information.
  • Uses TypeScript for type safety.
  • Styled with Tailwind CSS.

Feed Component

1. Create the Feed Page

Create app/feed/page.tsx:

// app/feed/page.tsx
import Tweet from './Tweet';

interface TweetData {
  id: number;
  username: string;
  handle: string;
  time: string;
  content: string;
  comments: number;
  retweets: number;
  likes: number;
}

export default function FeedPage() {
  const tweets: TweetData[] = [
    {
      id: 1,
      username: 'John Doe',
      handle: 'johndoe',
      time: '2h',
      content: 'This is my first tweet!',
      comments: 5,
      retweets: 2,
      likes: 20,
    },
    // Add more tweet objects
  ];

  return (
    <div className="max-w-2xl mx-auto mt-4">
      {tweets.map((tweet) => (
        <Tweet key={tweet.id} tweet={tweet} />
      ))}
    </div>
  );
}

Explanation:

  • Renders a list of tweets using the Tweet component.
  • Simulates fetching data from a backend.

Profile Component

1. Create the ProfileInfo Component

Create app/profile/ProfileInfo.tsx:

// app/profile/ProfileInfo.tsx
'use client';

import Image from 'next/image';

export default function ProfileInfo() {
  return (
    <div className="border-b border-gray-200 p-4">
      <div className="relative">
        <div className="h-32 bg-gray-200"></div>
        <Image
          className="absolute -bottom-12 left-4 h-24 w-24 rounded-full border-4 border-white"
          src="/default-avatar.png"
          alt="User Avatar"
          width={96}
          height={96}
        />
      </div>
      <div className="mt-16 px-4">
        <h1 className="text-xl font-bold">John Doe</h1>
        <p className="text-gray-500">@johndoe</p>
        <p className="mt-2">Bio goes here. This is a brief description about the user.</p>
        <div className="flex mt-2 space-x-4 text-gray-500">
          <span>
            <strong>100</strong> Following
          </span>
          <span>
            <strong>200</strong> Followers
          </span>
        </div>
      </div>
    </div>
  );
}

Explanation:

  • Displays user’s profile information.
  • Styled with Tailwind CSS.

2. Create the Profile Page

Create app/profile/page.tsx:

// app/profile/page.tsx
import ProfileInfo from './ProfileInfo';
import Tweet from '../feed/Tweet';

interface TweetData {
  id: number;
  username: string;
  handle: string;
  time: string;
  content: string;
  comments: number;
  retweets: number;
  likes: number;
}

export default function ProfilePage() {
  const tweets: TweetData[] = [
    {
      id: 1,
      username: 'John Doe',
      handle: 'johndoe',
      time: '1h',
      content: 'Hello from my profile!',
      comments: 2,
      retweets: 1,
      likes: 10,
    },
    // Add more tweet objects
  ];

  return (
    <div className="max-w-2xl mx-auto mt-4">
      <ProfileInfo />
      {tweets.map((tweet) => (
        <Tweet key={tweet.id} tweet={tweet} />
      ))}
    </div>
  );
}

Explanation:

  • Combines ProfileInfo and user’s tweets.
  • Reuses Tweet component for consistency.

Styling with Tailwind CSS

Using Utility Classes

Tailwind CSS utility classes allow you to style components directly in your markup.

Examples:

  • Layout and Spacing:
    • flex, grid, block
    • p-4 (padding), m-4 (margin)
  • Typography:
    • text-xl, font-bold, text-gray-500
  • Colors:
    • bg-white, bg-gray-200, text-blue-500
  • Borders and Shadows:
    • border, border-gray-200, rounded-full

Responsive Design

Tailwind provides responsive variants using breakpoint prefixes.

Breakpoints:

  • sm — 640px
  • md — 768px
  • lg — 1024px
  • xl — 1280px
  • 2xl — 1536px

Usage Example:

<div class="text-base md:text-lg lg:text-xl">
  Responsive Text Size
</div>

State Variants

Style components based on interaction states like hover, focus, and active.

Hover State:

<button class="text-gray-500 hover:text-blue-500">
  Like
</button>


Fetching Data from the Backend

In a real application, you would fetch data from your backend API.

1. Creating API Routes

Next.js 15 allows you to create API routes within the app/api/ directory.

Example:

Create app/api/tweets/route.ts:

// app/api/tweets/route.ts
import { NextResponse } from 'next/server';

export async function GET() {
  const tweets = [
    {
      id: 1,
      username: 'John Doe',
      handle: 'johndoe',
      time: '2h',
      content: 'This is my first tweet!',
      comments: 5,
      retweets: 2,
      likes: 20,
    },
    // Add more tweet objects or fetch from a database
  ];
  return NextResponse.json(tweets);
}

2. Fetching Data in Server Components

Update app/feed/page.tsx to fetch data from the API:

// app/feed/page.tsx
import Tweet from './Tweet';

export default async function FeedPage() {
  const res = await fetch('<http://localhost:3000/api/tweets>', { cache: 'no-store' });
  const tweets = await res.json();

  return (
    <div className="max-w-2xl mx-auto mt-4">
      {tweets.map((tweet: any) => (
        <Tweet key={tweet.id} tweet={tweet} />
      ))}
    </div>
  );
}

Notes:

  • Use { cache: 'no-store' } to prevent caching.
  • Ensure your API is correctly set up.

3. Using Client Components for Interactivity

For interactive components, define them as Client Components:

// components/InteractiveComponent.tsx
'use client';

import { useState } from 'react';

export default function InteractiveComponent() {
  const [count, setCount] = useState(0);

  return (
    <button onClick={() => setCount(count + 1)}>
      Clicked {count} times
    </button>
  );
}


Best Practices

  1. Component Reusability:
    • Create reusable components like Tweet, ProfileInfo, and Navbar.
    • Keep components focused and maintainable.
  2. Organize Your Project:
    • Use a logical folder structure.
    • Separate components, pages, and styles.
  3. Optimize Images:
    • Use Next.js Image component for optimized images.
    • Provide width and height for better performance.
  4. Responsive Design:
    • Ensure your app looks good on all screen sizes.
    • Test on mobile, tablet, and desktop views.
  5. Accessibility:
    • Use semantic HTML elements.
    • Provide alt text for images.
    • Ensure sufficient color contrast.
  6. Consistent Styling:
    • Stick to a consistent color palette and typography.
    • Customize the Tailwind config file (tailwind.config.js) if needed.
  7. Data Fetching Strategies:
    • Use Server Components for data fetching when possible.
    • Use Client Components for interactivity.
  8. Error Handling:
    • Handle errors when fetching data.
    • Provide user feedback for loading states.
  9. Leverage Next.js 15 Features:
    • Utilize React 19 features like Server Actions.
    • Explore Partial Prerendering for performance.
  10. Development Tools:
    • Use Turbopack for faster development builds.

Conclusion

Congratulations! You’ve learned how to:

  • Set up a Next.js 15 project with Tailwind CSS.
  • Understand and create components relevant to a social media app.
  • Use Tailwind CSS utility classes to style your components.
  • Build a responsive and modern frontend application.
  • Fetch data from a backend API in Next.js.
  • Leverage new features in Next.js 15, including React 19 support.

By mastering these concepts, you’re well on your way to building full-stack web applications.


Additional Resources


🎉 Congratulations! You’ve completed the Frontend Development module. Continue building on this foundation by adding more features and refining your application.