Open In App

Blogging Platform using Next JS

Last Updated : 13 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

In this project, we will explore the process of building The Blogging Platform with Next.js. Blogging Platform is a web application that allows users to create and publish blog posts. The platform provides a user-friendly interface for managing blog content and includes functionalities to create new blogs, search for blogs, and read the detailed content of specific blogs.

Output Preview: Let us have a look at how the final output will look like.

gfg-blog

Prerequisites:

Approach to Create Blogging Platform:

  • Setup the Project by Creating a new NextJS project Install the necessary libraries.
  • Design the layout of blogging platform, including components like Navbar, BlogList, Blogdetail, SearchBar, etc.
  • We will use local storage to store the blog details.
  • We will utilize useState and useEffect hooks to manage state and fetch blog data. we will use useRouter hook to access route parameters such as blog id.
  • Implement a search feature for filtering blog posts based on the search query.
  • We will implement Next.js routing to navigate between different pages (e.g., list of blogs, individual blog posts, create new blogs).
  • We will style the application using bootstrap.

Steps to Create the Blogging Platform:

Step 1: Create a application of NextJS using the following command.

npx create-next-app blog-app

Step 2: Navigate to project directory

cd blog-app

Step 3: Install the necessary package in your project using the following command.

npm install bootstrap

Step 4: Create the folder structure as shown below and create the files in respective folders.

Project Structure:

Screenshot-(18)

The updated dependencies in package.json file will look like:

"dependencies": {
"bootstrap": "^5.3.3",
"next": "14.1.3",
"react": "^18",
"react-dom": "^18"
}

Example: Below are the components which describes the implementation of the Blogging platform.

  • Navbar.js: This component defines a navigation bar for blogging platform. It uses the Link component from Next.js to create links to different pages of the website.
  • Createblog.js: This component allows users to add new blog posts by entering blog details.
  • BlogList.js: This component is responsible to retrieve and display a list of published blog posts.
  • [id].js: This component displays the details of a specific blog post using dynamic routing.
Javascript
// page.js

import React from 'react'
import BlogList from '@/Components/BlogList';

const page = () => {
    return (
        <>
            <BlogList />
        </>
    )
}

export default page
Javascript
// Navbar.js

import React from 'react';
import Link from 'next/link';

const Navbar = () => {
    return (
        <div>
            <nav className="navbar navbar-expand-lg navbar-light 
                bg-dark bg-opacity-75 fixed-top text-light">
                <div className="container">
                    <Link className="navbar-brand 
                        text-light font-bold" href="/">
                        GFG Blogs
                    </Link>
                    <button className="navbar-toggler"
                        type="button" 
                        data-toggle="collapse"
                        data-target="#navbarNav" 
                        aria-controls="navbarNav"
                        aria-expanded="false" 
                        aria-label="Toggle navigation">
                        <span className="navbar-toggler-icon"></span>
                    </button>
                    <div className="collapse navbar-collapse" 
                         id="navbarNav">
                        <ul className="navbar-nav mr-auto">
                            <li className="nav-item">
                                <Link href="/"
                                    className="nav-item nav-link 
                                               text-light">
                                    Home
                                </Link>
                            </li>
                            <li className="nav-item">
                                <Link href="/Createblog"
                                    className="nav-item nav-link 
                                               text-light">
                                    Create new Blog
                                </Link>
                            </li>
                        </ul>
                    </div>
                </div>
            </nav>
        </div>
    );
};

export default Navbar;
Javascript
// BlogList.js

'use client'
import React,
{
    useState,
    useEffect
} from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import Navbar from '@/Components/Navbar';
import Link from 'next/link';

function BlogList() {
    const [data, setData] = useState([]);
    const [expandedId, setExpandedId] = useState(null);
    const [searchQuery, setSearchQuery] = useState('');

    useEffect(() => {
        const blogs =
            JSON.parse(localStorage.getItem('myData') || '[]');
        setData(blogs);
    }, []);



    const toggleExpanded = (id) => {
        setExpandedId(expandedId === id ? null : id);
    };

    let filteredData = data;
    if (searchQuery.trim() !== '') {
        filteredData = data.filter(item =>
            item.title.toLowerCase()
                .includes(searchQuery.toLowerCase())
        );
    }

    return (
        <div>
            <Navbar />
            <div className="container bg-light"
                style={{ marginTop: '5rem' }}>
                <input
                    type="text"
                    className="form-control mb-2"
                    placeholder="Search..."
                    value={searchQuery}
                    onChange={(e) => setSearchQuery(e.target.value)}
                />
                <div className="row">
                    {
                        filteredData.map((item) => (
                            <div key={item.id} className="col-md-4">
                                <div className="card mb-3">
                                    <img src={item.imageUrl} 
                                        className="card-img-top" 
                                        alt="Blog" />
                                    <div className="card-body">
                                        <h5 className="card-title">
                                            {item.title}
                                        </h5>
                                        <p className="card-text">
                                            {
                                                expandedId ===
                                                    item.id ?
                                                    item.description :
                                                    `${item.description.substring(0, 50)}...`
                                            }
                                        </p>
                                        <div className="d-flex justify-content-between 
                                            align-items-center row">
                                            <div>
                                                <p className="m-0 small col">
                                                    {"posted by "}
                                                    {item.author}
                                                </p>
                                                <small className="text-muted">
                                                    {item.date}
                                                </small>
                                            </div>
                                        </div>
                                        <Link href={`/blog/${item.id}`}>
                                            <button className='btn btn-primary'>
                                                Read more
                                            </button>
                                        </Link>
                                    </div>
                                </div>
                            </div>
                        ))}
                </div>
            </div>
        </div>
    );
}

export default BlogList;
Javascript
// Createblog.js

'use client'
import React, { useState, useEffect } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import Navbar from '@/Components/Navbar';

const Createblog = () => {
    const [author, setAuthor] = useState('');
    const [title, setTitle] = useState('');
    const [description, setDescription] = useState('');
    const [imageUrl, setImageUrl] = useState('');
    const initialBlogs =
        typeof window !== 'undefined' ?
            JSON.parse(localStorage.getItem('myData')) || [] : [];
    const [data, setData] = useState(initialBlogs);

    useEffect(() => {
        // Save habits to localStorage whenever they change
        localStorage.setItem('myData', JSON.stringify(data));
    }, [data]);

    const addData = () => {
        const currentDate = new Date().toLocaleDateString();
        const newData =
        {
            id: data.length + 1,
            author: author,
            date: currentDate,
            title: title,
            description: description,
            imageUrl: imageUrl
        };
        const updatedData = [...data, newData];
        setData(updatedData);
        setAuthor('');
        setTitle('');
        setDescription('');
        setImageUrl('');
    };

    return (
        <div>
            <Navbar />
            <div className="container bg-light" 
                 style={{ marginTop: '5rem' }}>
                <div className="row">
                    <div className="col">
                        <input
                            type="text"
                            className="form-control mb-2"
                            placeholder="Author"
                            value={author}
                            onChange={(e) => setAuthor(e.target.value)}
                        />
                        <input
                            type="text"
                            className="form-control mb-2"
                            placeholder="Title"
                            value={title}
                            onChange={(e) => setTitle(e.target.value)}
                        />
                        <textarea
                            className="form-control mb-2"
                            placeholder="Description"
                            value={description}
                            onChange={(e) => setDescription(e.target
                                                             .value)}
                        />
                        <input
                            type="text"
                            className="form-control mb-2"
                            placeholder="Image URL"
                            value={imageUrl}
                            onChange={(e) =>setImageUrl(e.target.value)}
                        />
                        <button onClick={addData} 
                                className="btn btn-primary mb-2">
                            Add Data
                        </button>
                    </div>
                </div>
            </div>
        </div>
    );
};

export default Createblog;
Javascript
// pages/[id].js

import React,
{
    useEffect,
    useState
} from 'react';
import { useRouter } from 'next/router';
import Navbar from '@/Components/Navbar';
import 'bootstrap/dist/css/bootstrap.min.css';

const BlogDetails = () => {

    const [blogDetail, setBlogDetail] = useState([]);
    const router = useRouter();
    const { id } = router.query;
    useEffect(() => {
        const blogs = JSON.parse(localStorage.getItem('myData'));
        const selectedBlog=blogs.find(blog => blog.id === parseInt(id));
        setBlogDetail(selectedBlog);
    }, [id]);


    if (!blogDetail) {
        return <div>Loading...</div>;
    }

    return (
        <div className="container bg-light" 
             style={{ marginTop: '5rem' }}>
            <Navbar />
            <div className="card mt-5">
                <img src={blogDetail.imageUrl}
                    style={
                        {
                            maxWidth: '100%',
                            maxHeight: '300px'
                        }}
                    className="card-img-top" alt="Blog" />
                <div className="card-body">
                    <h1 className="card-title">{blogDetail.title}</h1>
                    <p className="card-text">
                        {blogDetail.description}
                    </p>
                    <p className="card-text">
                        Author: {blogDetail.author}
                    </p>
                    <p className="card-text">Date: {blogDetail.date}</p>
                </div>
            </div>
        </div>
    );
};

export default BlogDetails;

Start your application using the following command:

npm run dev

Output: Naviage to the URL http://localhost:3000:

gfg-blog-live



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads