Final Project

Final Project

This is a fantastic roadmap for learning full-stack development by building a Blog Application using HTML, CSS, Python (Flask), and SQL. Let's begin our step-by-step journey toward mastering full-stack development! 🚀


📌 Step 1: Understanding Full-Stack Development & Project Planning

Before diving into coding, let's understand the core concepts of full-stack development and how different technologies interact.

🔹 What is Full-Stack Development?

A Full-Stack Application consists of three main components:

  1. Frontend (Client-Side) – The part users interact with (HTML, CSS, JavaScript).
  1. Backend (Server-Side) – The logic that processes user requests and connects to the database (Python + Flask).
  1. Database – Stores user information, blog posts, and comments (SQL).

🔹 Technologies Used in Our Blog App

We'll use the following technologies:

Frontend → HTML (structure), CSS (styling), JavaScript (optional for interactivity).

Backend → Python with Flask (lightweight web framework).

Database → SQL (we’ll use SQLite for simplicity, but PostgreSQL/MySQL can also be used).


🔹 The architecture of Our Blog Application

Here’s how our blog app will function:

  1. Users register/log in to access their dashboard.
  1. Logged-in users can create, edit, and delete blog posts.
  1. Visitors can view all blogs without logging in.
  1. Users can comment on blog posts.
  1. Admins can manage users and blogs.
  1. The app will be deployed online.

🚀 Next Step: Frontend Development

🔹 Now that we understand the project structure, let's start building the front end using HTML & CSS. In the next lesson, we'll:

✔ Create the basic structure of the blog (Homepage, Blog Page, Login Page).

✔ Design a simple responsive layout using CSS.


📌 Step 2: Building the Frontend (HTML & CSS)

Before we jump into Flask and SQL, we need to design the user interface (UI) using HTML & CSS. This will define the structure and appearance of our blog application.


🛠 2.1 Setting Up the Project Folder

First, create a project folder and organize it like this:

blog-app/
│── static/         # CSS, images, and JavaScript files
│   ├── styles.css  # Main CSS file
│── templates/      # HTML files
│   ├── index.html  # Home page
│   ├── login.html  # Login page
│   ├── register.html # Registration page
│   ├── dashboard.html  # User Dashboard
│   ├── blog.html  # Single Blog Page
│── app.py         # Flask backend (we’ll add this later)
│── database.db    # SQLite database (we’ll add this later)

📝 2.2 Creating the Homepage (index.html)

Let’s start by creating a homepage that displays a list of blog posts.

📌 Create a new file: templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My Blog</title>
    <link rel="stylesheet" href="../static/css/styles.css">
</head>
<body>
    <header>
        <div class="header-container">
            <div class="logo">
                <h1>My Blog</h1>
            </div>
            <nav>
                <a href="index.html">Home</a>
                <a href="article.html">Article</a>
                <a href="login.html">Login</a>
                <a href="register.html">Register</a>
            </nav>
            <div class="user-profile">
                <img src="../static/images/1.jpg" alt="User Profile">
                <span class="username">Akash Tiwari</span>
            </div>
        </div>
    </header>
    

    <main>
        <section class="hero">
            <h2>Welcome to My Blog</h2>
            <p>Explore the latest articles, thoughts, and ideas from our community.</p>
            <a href="register.html"class="btn">Get Started</a>
        </section>

        <h2 class="section-title">Latest Blogs</h2>
        <div class="blog-list">
            <div class="blog">
                <img src="../static/blog1.jpg" alt="Blog Image">
                <h3>Blog Title 1</h3>
                <p>Short description of the blog post...</p>
                <a href="blog.html" class="read-more">Read More</a>
            </div>
            <div class="blog">
                <img src="../static/blog2.jpg" alt="Blog Image">
                <h3>Blog Title 2</h3>
                <p>Another short description...</p>
                <a href="blog.html" class="read-more">Read More</a>
            </div>
        </div>
    </main>

    <footer>
        <p>© 2025 My Blog | Designed by Coder By Heart</p>
    </footer>
</body>
</html>

📝 2.3 Creating the Register (register.html)

Now let’s create a Registration page

📌 Create a new file: templates/register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Register | My Blog</title>
    <link rel="stylesheet" href="../static/css/styles.css">
</head>
<body>

    <!-- Header -->
    <header>
        <div class="header-container">
            <div class="logo">
                <h1>My Blog</h1>
            </div>
            <nav>
                <a href="index.html">Home</a>
                <a href="article.html">Article</a>
                <a href="login.html">Login</a>
                <a href="register.html">Register</a>
            </nav>
            <div class="user-profile">
                <img src="../static/images/login.png" alt="Login">
                <span class="username">Guest</span>
            </div>
        </div>
    </header>

    <div class="register-container">
        <!-- Left Section: Image & Info -->
        <div class="register-info">
            <h2>Join Our Blog Community!</h2>
            <p>Share your thoughts, connect with others, and explore amazing content.</p>
            <img src="../static/images/register_page.avif" alt="Blogging Community">
        </div>

        <!-- Right Section: Registration Form -->
        <div class="register-form">
            <h2>Create an Account</h2>
            <form action=" " method="POST" enctype="multipart/form-data">
                

                <label for="name">Full Name</label>
                <input type="text" id="name" name="name" placeholder="Enter your full name" required>

                <label for="username">Username</label>
                <input type="text" id="username" name="username" placeholder="Choose a username" required>

                <label for="email">Email</label>
                <input type="email" id="email" name="email" placeholder="Enter your email" required>

                <label for="phone_no">Phone Number</label>
                <input type="tel" id="phone_no" name="phone_no" placeholder="Enter your phone number" required>

                <label for="profile_picture">Profile Picture</label>
                <input type="file" id="profile_picture" name="profile_picture" accept="image/*" required>

                <label for="password">Password</label>
                <input type="password" id="password" name="password" placeholder="Create a password" required>

                <label for="confirm_password">Confirm Password</label>
                <input type="password" id="confirm_password" name="confirm_password" placeholder="Confirm your password" required>

                <button type="submit">Register</button>
            </form>
        </div>
    </div>

    <!-- Footer -->

    <footer>
        <p>© 2025 My Blog | Designed by Coder By Heart</p>
    </footer>

    <script>
        // Password Validation
        document.querySelector("form").addEventListener("submit", function(event) {
            let password = document.getElementById("password").value;
            let confirmPassword = document.getElementById("confirm_password").value;

            if (password !== confirmPassword) {
                alert("Passwords do not match!");
                event.preventDefault();
            }
        });
    </script>

</body>
</html>

📝 2.4 Creating the login (login.html)

Now let’s create a login page

📌 Create a new file: templates/login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login | My Blog</title>
    <link rel="stylesheet" href="../static/css/styles.css">
</head>
<body>

    <!-- Header -->
    <header>
        <div class="header-container">
            <div class="logo">
                <h1>My Blog</h1>
            </div>
            <nav>
                <a href="index.html">Home</a>
                <a href="article.html">Article</a>
                <a href="login.html">Login</a>
                <a href="register.html">Register</a>
            </nav>
            <div class="user-profile">
                <img src="../static/images/login.png" alt="Login">
                <span class="username">Guest</span>
            </div>
        </div>
    </header>

    <div class="login-container">
        <!-- Left Section: Image & Info -->
        <div class="login-info">
            <h2>Welcome Back!</h2>
            <p>Login to continue sharing and exploring amazing blogs.</p>
            <img src="../static/images/login_page.avif" alt="Welcome Back">
        </div>

        <!-- Right Section: Login Form -->
        <div class="login-form">
            <h2>Login to Your Account</h2>
            <form action="" method="POST">
                
                <label for="email">Email</label>
                <input type="email" id="email" name="email" placeholder="Enter your email" required>

                <label for="password">Password</label>
                <input type="password" id="password" name="password" placeholder="Enter your password" required>

                <div class="button-group">
                    <button type="submit">Login</button>
                    <a href="register.html" ><button class="register-btn">Register</button></a>
                </div>
            </form>
        </div>
    </div>

    <!-- Footer -->
    <footer>
        <p>© 2025 My Blog | Designed by Coder By Heart</p>
    </footer>
</body>
</html>

📝 2.5 Creating the article.html

Now let’s create a page where we will show all the articles/blogs

📌 Create a new file: templates/article.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Articles</title>
    <link rel="stylesheet" href="../static/css/styles.css">
    <link rel="stylesheet" href="../static/css/article.css">
</head>
<body>

    <!-- Header -->
    <header>
        <div class="header-container">
            <div class="logo">
                <h1>My Blog</h1>
            </div>
            <nav>
                <a href="{{ url_for('index')}}">Home</a>
                <a href="{{url_for('article')}}">Article</a>
                <a href="{{ url_for('login') }}" {% if user %} style="display: none;" {% endif %}>Login</a>
                <a href="{{ url_for('register') }}" {% if user %} style="display: none;" {% endif %}>Register</a>
            </nav>
            <div class="user-profile">
                {% if user %}
                    <img src="{{ user.profile_pic }}" alt="User Profile">
                    <span class="username">{{ user.username }}</span>
                    <a href="{{ url_for('logout') }}" class="logout-btn h-link"><Button id="Logout" class="h-btn">Logout</Button></a>
                    <a class="create-blog h-link" href="{{ url_for('create_post')}}"><button id="newBlog" class="h-btn"><img src="../static/images/cAd29bV1wGyF.gif" alt=""><Span>New</Span></button></a>
                {% else %}
                    <img src="../static/images/login.png" alt="Guest">
                    <span class="username">Guest</span>
                {% endif %}
            </div>
        </div>
    </header>

    <main class="article-container">
        <!-- Left Sidebar: Users List -->
        <aside class="article-sidebar article-users">
            <h2>Users</h2>
            <ul class="article-user-list">
                <li><img src="user1.jpg" alt="User 1"> John Doe</li>
                <li><img src="user2.jpg" alt="User 2"> Jane Smith</li>
                <li><img src="user3.jpg" alt="User 3"> Alice Brown</li>
                <li><img src="user4.jpg" alt="User 4"> David Wilson</li>
            </ul>
        </aside>

        <!-- Main Content: Blogs Section -->
        <section class="article-content">
            <h2>Latest Blogs</h2>
            <div class="article-blog-list">
                {% for article in articles %}
                <div class="article-blog-card">
                    <img src="{{ article.image_filename }}" alt="Blog Image">
                    <h3> article.author </h3>
                    <p><b>{{ article.category }}</b> | {{ article.created_at.strftime('%b %d, %Y') }}</p>
                    <p>{{ article.content }}</p>
                    <button class="article-read-more">Read More</button>
                </div>
                {% endfor %}
            </div>
            <button class="article-load-more">Load More</button>
        </section>

        <!-- Right Sidebar: Blog Categories -->
        <aside class="article-sidebar article-categories">
            <h2>Categories</h2>
            <ul class="article-category-list">
                <li>Technology</li>
                <li>Health</li>
                <li>Travel</li>
                <li>Business</li>
                <li>Education</li>
            </ul>
        </aside>
    </main>

    <!-- Footer -->
    <footer class="footer">
        <p>&copy; 2025 My Blog Platform. All Rights Reserved.</p>
    </footer>

</body>
</html>

📝 2.5 Creating the create_blog.html

Now let’s create a page where we can create new articles/blogs

📌 Create a new file: templates/create_blog.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Create Blog Post</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
    <link rel="stylesheet" href="{{ url_for('static', filename='css/create_blog.css') }}">

</head>
<body >

      <!-- Header -->
    <header>
        <div class="header-container">
            <div class="logo">
                <h1>My Blog</h1>
            </div>
            <nav>
                <a href="index.html">Home</a>
                <a href="article.html">Article</a>
                <a href="login.html">Login</a>
                <a href="register.html">Register</a>
            </nav>
            <div class="user-profile">
                <img src="../static/images/login.png" alt="Login">
                <span class="username">Guest</span>
            </div>
        </div>
    </header>

    <div class="cb-body">
        <div class="cb-container">
            <h2 class="cb-heading">Create a New Blog Post</h2>       
            <form action="{{ url_for('create_post') }}" method="POST" enctype="multipart/form-data" class="cb-form">
                <label for="title" class="cb-label">Title:</label>
                <input type="text" id="title" name="title" class="cb-input" required>
    
                <label for="content" class="cb-label">Content:</label>
                <textarea id="content" name="content" class="cb-textarea" rows="5" required></textarea>
    
                <label for="category" class="cb-label">Category:</label>
                <input type="text" id="category" name="category" class="cb-input" required>
    
                <label for="image" class="cb-label">Upload Image:</label>
                <input type="file" id="image" name="image" class="cb-file-input" accept="image/*">
    
                <button type="submit" class="cb-button">Create Post</button>
            </form>
        </div>
    </div>

    <footer>
        <p>© 2025 My Blog | Designed by Coder By Heart</p>
    </footer>

</body>
</html>

Now let’s Decorate Our web pages Using Some CSS

For That inside Project Folder (Blog_app) Create new folder named ‘static’ and then inside the static folder create folder name ‘css’

Now in css folder create new file styles.css

/* General Styles */
body {
    font-family: 'Poppins', sans-serif;
    margin: 0;
    padding: 0;
    background-color: #f4f4f4;
    color: #333;
}

/* Header */
/* Header */
header {
    background: linear-gradient(135deg, #6e8efb, #a777e3);
    color: white;
    padding: 15px 20px;
    box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
}

.header-container {
    display: flex;
    justify-content: space-between;
    align-items: center;
    max-width: 1200px;
    margin: auto;
}

/* Logo */
.logo h1 {
    font-size: 24px;
    font-weight: bold;
}

/* Navigation Links */
nav a {
    color: white;
    margin: 0 15px;
    text-decoration: none;
    font-weight: bold;
    transition: 0.3s;
}

nav a:hover {
    text-decoration: underline;
}

/* User Profile */
.user-profile {
    display: flex;
    align-items: center;
    gap: 10px;
}

.user-profile img {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 2px solid white;
    object-fit: cover;
}

.username {
    font-weight: bold;
    font-size: 16px;
}


/* Hero Section */
.hero {
    text-align: center;
    padding: 50px;
    background: #fdfdfd;
    box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
    margin-bottom: 20px;
    border-radius: 10px;
}

.hero h2 {
    margin-bottom: 10px;
    color: #555;
}

.hero p {
    color: #777;
    font-size: 16px;
}

.btn {
    display: inline-block;
    padding: 12px 24px;
    background: #6e8efb;
    color: white;
    text-decoration: none;
    border-radius: 5px;
    font-weight: bold;
    transition: 0.3s;
}

.btn:hover {
    background: #a777e3;
}

/* Blog Section */
.section-title {
    text-align: center;
    color: #444;
}

.blog-list {
    display: flex;
    justify-content: center;
    gap: 20px;
    flex-wrap: wrap;
    margin: 20px auto;
}

.blog {
    background: white;
    border-radius: 10px;
    overflow: hidden;
    box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
    width: 300px;
    padding: 15px;
    text-align: center;
}

.blog img {
    width: 100%;
    height: 150px;
    object-fit: cover;
    border-radius: 10px;
}

.blog h3 {
    margin: 10px 0;
    color: #444;
}

.blog p {
    color: #666;
    font-size: 14px;
}

.read-more {
    display: inline-block;
    margin-top: 10px;
    color: #6e8efb;
    font-weight: bold;
    text-decoration: none;
    transition: 0.3s;
}

.read-more:hover {
    color: #a777e3;
}

/* Footer */
footer {
    text-align: center;
    padding: 15px;
    background: #ddd;
    position: fixed;
    bottom: 0;
    width: 100%;
    font-size: 14px;
}


/* ```````````````````````````````````````Register Page start here ```````````````````````````````````````````````` */



/* Register Page Layout */
.register-container {
    display: flex;
    width: 80%;
    margin: 50px auto;
    /* background: white; */
    background: linear-gradient(135deg, #6e8efb, #a777e3);
    border-radius: 10px;
    overflow: hidden;
    box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
}

/* Left Section */
.register-info {
    width: 45%;
    /* background: linear-gradient(135deg, #6e8efb, #a777e3); */
    color: white;
    padding: 40px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    text-align: center;
}

.register-info h2 {
    margin-bottom: 10px;
    font-size: 24px;
}

.register-info p {
    font-size: 16px;
    margin-bottom: 20px;
}

.register-info img {
    width: 100%;
    border-radius: 10px;
}

/* Right Section (Form) */
.register-form {
    color:white;
    width: 55%;
    padding: 40px;
    background-color: #44444457;
    /* background: transparent; */
}

.register-form h2 {
    text-align: center;
    margin-bottom: 20px;
}

form {
    display: flex;
    flex-direction: column;
}

label {
    margin: 10px 0 5px;
    font-weight: bold;
}

input {
    width: 100%;
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 5px;
}

button {
    width: 100%;
    padding: 10px;
    margin-top: 15px;
    border: none;
    background-color: #6e8efb;
    color: white;
    font-size: 16px;
    cursor: pointer;
    border-radius: 5px;
    transition: 0.3s;
}

button:hover {
    background-color: #4a6ed1;
}


/* ```````````````register page end here``````````````````````````````````````````````````` */


/* ````````````````````login page starts here ```````````````````````````````````````````````` */

/* Login Page Layout */
.login-container {
    display: flex;
    width: 80%;
    margin: 50px auto;
    background: linear-gradient(135deg, #ff758c, #ff7eb3);
    border-radius: 10px;
    overflow: hidden;
    box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
}

/* Left Section */
.login-info {
    width: 45%;
    /* background: linear-gradient(135deg, #ff758c, #ff7eb3); */
    color: white;
    padding: 40px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    text-align: center;
}

.login-info h2 {
    margin-bottom: 10px;
    font-size: 24px;
}

.login-info p {
    font-size: 16px;
    margin-bottom: 20px;
}

.login-info img {
    width: 100%;
    border-radius: 10px;
}

/* Right Section (Form) */
.login-form {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    width: 55%;
    padding: 40px;
    /* background-color: #ffffff62 */
    ;
}

.login-form h2 {
    text-align: center;
    margin-bottom: 20px;
    font-weight: 900;
}

form {
    width:80%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    background-color: #ffffff62;
    padding:20px;
    border-radius: 20px;

}

label {
    margin: 10px 0 5px;
    font-weight: bold;
}

input {
    width: 80%;
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 5px;
}

/* Button Group for Login and Register */
.button-group {
    display: flex;    
    margin-top: 15px;
}

button {
    width: 40%;
    padding: 10px;
    border: none;
    background-color: #ff758c;
    color: white;
    font-size: 16px;
    cursor: pointer;
    border-radius: 5px;
    transition: 0.3s;
    margin-bottom: 5px;
}

button:hover {
    background-color: #444;
    
}

/* Register Button (Styled as Link) */
.register-btn {
    width: 100%;
    background-color: #444;
    margin-left: 10px;

    
}

.register-btn:hover {
    background-color: #ff758c;

}

/* Footer Styling */
footer {
    text-align: center;
    padding: 15px;
    background: gainsboro;
    position: fixed;
    bottom: 0;
    width: 100%;
}
/* `````````````````````````````````````login page end here ```````````````````````````````````````````` */

Now in css folder create another file article.css

/* General Styles */
body {
    font-family: 'Arial', sans-serif;
    margin: 0;
    padding: 0;
    background-color: #f4f4f4;
}


/* Main Layout */
.article-container {
    display: flex;
    max-width: 1200px;
    margin: 20px auto;
    gap: 20px;
}

/* Sidebar (Users List & Categories) */
.article-sidebar {
    background: white;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.1);
    width: 20%;
}

.article-sidebar h2 {
    font-size: 18px;
    margin-bottom: 10px;
}

/* Users List */
.article-user-list {
    list-style: none;
    padding: 0;
}

.article-user-list li {
    display: flex;
    align-items: center;
    margin-bottom: 10px;
}

.article-user-list img {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    margin-right: 10px;
}

/* Blog Content */
.article-content {
    width: 76%;
    background: white;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.1);
}

/* Blog List using Flexbox */
.article-blog-list {
    display: flex;
    flex-wrap: wrap;
    flex-direction: column;
    justify-content: space-between;
    gap: 15px;
}

/* Individual Blog Card */
.article-blog-card {
    background: #d6e1e6;
    padding: 15px;
    border-radius: 8px;
    box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.1);
    flex: 1 1 calc(33.33% - 10px);  /* Responsive 3-column layout */
    width: 500px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}

.article-blog-card img {
    width: 100%;
    /* height: 150px; */
    border-radius: 5px;
    object-fit: cover;
}

.article-blog-card h3 {
    margin: 10px 0;
    font-size: 18px;
    text-align: center;
}

/* Read More Button */
.article-read-more {
    background: #FF6F3C;
    color: white;
    padding: 7px 12px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    margin-top: auto; /* Push button to the bottom */
}

.article-read-more:hover {
    background: #e65b2b;
}

/* Load More Button */
.article-load-more {
    display: block;
    margin: 20px auto;
    padding: 10px 15px;
    background: #5A189A;
    color: white;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    text-align: center;
}

.article-load-more:hover {
    background: #4a1281;
}

/* Categories */
.article-category-list {
    list-style: none;
    padding: 0;
}

.article-category-list li {
    padding: 10px;
    background: #003366;
    color: white;
    margin-bottom: 5px;
    text-align: center;
    border-radius: 5px;
}

.article-category-list li:hover {
    background: #002255;
}

/* Footer */
.article-footer {
    text-align: center;
    padding: 10px;
    background: #003366;
    color: white;
    margin-top: 20px;
}


Now in css folder create another file creat_blog.css

/* General Page Styling */
.cb-body {
    font-family: Arial, sans-serif;
    background-color: #f8f9fa;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
}

/* Form Container */
.cb-container {
    background: #ffffff;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    width: 400px;
    text-align: center;
}

/* Heading */
.cb-heading {
    color: #333;
    margin-bottom: 20px;
}

/* Labels */
.cb-label {
    display: block;
    text-align: left;
    font-weight: bold;
    margin-top: 10px;
}

/* Input Fields */
.cb-input, .cb-textarea, .cb-file-input {
    width: 100%;
    padding: 10px;
    margin-top: 5px;
    border: 1px solid #ccc;
    border-radius: 5px;
}

/* Button */
.cb-button {
    background-color: #007bff;
    color: white;
    border: none;
    padding: 10px;
    width: 100%;
    margin-top: 15px;
    cursor: pointer;
    border-radius: 5px;
    font-size: 16px;
}

.cb-button:hover {
    background-color: #0056b3;
}

Now Update your .html file header with this code

Note you have to update every .html file

    <!-- Header -->
    <header>
        <div class="header-container">
            <div class="logo">
                <h1>My Blog</h1>
            </div>
            <nav>
                <a href="{{ url_for('index')}}">Home</a>
                <a href="{{url_for('article')}}">Article</a>
                <a href="{{ url_for('login') }}" {% if user %} style="display: none;" {% endif %}>Login</a>
                <a href="{{ url_for('register') }}" {% if user %} style="display: none;" {% endif %}>Register</a>
            </nav>
            <div class="user-profile">
                {% if user %}
                    <img src="{{ user.profile_pic }}" alt="User Profile">
                    <span class="username">{{ user.username }}</span>
                    <a href="{{ url_for('logout') }}" class="logout-btn h-link"><Button id="Logout" class="h-btn">Logout</Button></a>
                    <a class="create-blog h-link" href="{{ url_for('create_post')}}"><button id="newBlog" class="h-btn"><img src="../static/images/cAd29bV1wGyF.gif" alt=""><Span>New</Span></button></a>
                {% else %}
                    <img src="../static/images/login.png" alt="Guest">
                    <span class="username">Guest</span>
                {% endif %}
            </div>
        </div>
    </header>

Now Lets Create Our Own Server

Now Lets Create Our Own Server

For that create new file inside your blog_application folder

from flask import Flask, render_template, request, redirect, url_for

app = Flask(__name__, template_folder="templates")
user = {"email":"a@gmail.com", "password":'@a@123'}

@app.route('/',methods=['GET'])
def index():
    return render_template("index.html")

@app.route('/login',methods=['GET','POST'])
def login():
    if request.method == 'POST':
        email = request.form["email"]
        password = request.form['password']
        if user['email']==email or user['password']==password:
            return redirect(url_for("index"))
        else:
            return render_template("login.html")
        
@app.route('/register', methods =['GET'])
def register():
    return render_template("register.html")

@app.route('/article',methods=['GET'])
def article():
    return render_template('article.html')

if __name__=="__main__":
    app.run(host="0.0.0.0",port=5500,debug=True)
    

Now Update header of your HTML Files (index.html,register.html,login.html, article.html.create_blog.html)

    <!-- Header -->
    <header>
        <div class="header-container">
            <div class="logo">
                <h1>My Blog</h1>
            </div>
            <nav>
                <a href="{{ url_for('index')}}">Home</a>
                <a href="{{url_for('article')}}">Article</a>
                <a href="{{ url_for('login') }}" {% if user %} style="display: none;" {% endif %}>Login</a>
                <a href="{{ url_for('register') }}" {% if user %} style="display: none;" {% endif %}>Register</a>
            </nav>
            <div class="user-profile">
                {% if user %}
                    <img src="{{ user.profile_pic }}" alt="User Profile">
                    <span class="username">{{ user.username }}</span>
                    <a href="{{ url_for('logout') }}" class="logout-btn h-link"><Button id="Logout" class="h-btn">Logout</Button></a>
                    <a class="create-blog h-link" href="{{ url_for('create_post')}}"><button id="newBlog" class="h-btn"><img src="../static/images/cAd29bV1wGyF.gif" alt=""><Span>New</Span></button></a>
                {% else %}
                    <img src="../static/images/login.png" alt="Guest">
                    <span class="username">Guest</span>
                {% endif %}
            </div>
        </div>
    </header>

Now lets connect it with Database

For that inside your Blog_Application Folder create new file models.py


from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    username = db.Column(db.String(50), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    phone_no = db.Column(db.String(15), unique=True, nullable=False)
    profile_picture = db.Column(db.String(255), nullable=True)  # Stores image filename
    password = db.Column(db.String(100), nullable=False)  # Hashed password
    posts = db.relationship('Post', backref='author', lazy=True)

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(200), nullable=False)
    content = db.Column(db.Text, nullable=False)
    category = db.Column(db.String(100), nullable=False)
    image_filename = db.Column(db.String(255))  # Stores the image filename
    created_at = db.Column(db.DateTime, default=db.func.current_timestamp())
    updated_at = db.Column(db.DateTime, default=db.func.current_timestamp(), onupdate=db.func.current_timestamp())

    # Foreign key linking Post to User
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)

    def __repr__(self):
        return f"<Post {self.title} by {self.author.username}>"

Now create another file routers.py

from flask import render_template,url_for,request,redirect,current_app
from werkzeug.utils import secure_filename
from models import User
import os

def register_route(app,db):

    @app.route('/',methods=['GET'])
    def index():
        return render_template("index.html")


    @app.route('/login',methods=['GET','POST'])
    def login():
        if request.method=="POST":
            
            email=request.form['email']
            password=request.form['password']
            
            return redirect(url_for("index"))
        else:
            return render_template("login.html")


    @app.route('/register', methods=['GET', 'POST'])
    def register():
        if request.method == 'POST':
            name = request.form['name']
            username = request.form['username']
            email = request.form['email']
            phone_no = request.form['phone_no']
            password = request.form['password']
            confirm_password = request.form['confirm_password']
            profile_picture = request.files['profile_picture']

            # Check if passwords match
            if password != confirm_password:
                message="Passwords do not match!"
                return render_template('register.html',message=message)

            # Hash password using bcrypt
            hashed_password = bcrypt.generate_password_hash(password).decode('utf-8')

            # Handle profile picture upload
            if profile_picture and allowed_file(profile_picture.filename):
                filename = secure_filename(profile_picture.filename)
                profile_picture_path = os.path.join(current_app.config['PROFILE_UPLOAD_FOLDER'], filename)
                profile_picture.save(profile_picture_path)
            else:
                profile_picture_path = None  # Default if no picture uploaded

            # Check if username or email already exists
            existing_user = User.query.filter((User.username == username) | (User.email == email)).first()
            if existing_user:
                message = "Username or email already taken."
                return render_template('register.html',message=message)

            # Create new user and add to database
            new_user = User(
                name=name,
                username=username,
                email=email,
                phone_no=phone_no,
                password=hashed_password,
                profile_picture=profile_picture_path
            )
            db.session.add(new_user)
            db.session.commit()

            message = "Registration successful! You can now log in."
            return render_template('login.html',message=message)

        return render_template('register.html')

    @app.route('/article',methods=['GET'])
    def article():
        return render_template("article.html")
    

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in {'png', 'jpg', 'jpeg', 'gif'}
    

Now Create Another file
config.py


class Config:
    SECRET_KEY='SECRET'
    SQLALCHEMY_DATABASE_URI='sqlite:///blog.db'
    SQLALCHEMY_TRACK_MODIFICATIONS=False
    PROFILE_UPLOAD_FOLDER='static/uploads/Profile_image'
    BLOG_UPLOAD_FOLDER='static/uploads/Blog_image'
    ALLOWED_EXTENSIONS={'png','jpg','jpeg','gif'}

Now Update app.py File

from flask import Flask
from routers import register_route
from config import Config
from models import db
from flask_bcrypt import Bcrypt

bcrypt = Bcrypt() 


def create_app():
    app=Flask(__name__,template_folder="templates")
    app.config.from_object(Config)
    db.init_app(app)  #To registered current flask app with this 'SQLAlchemy' instance
    app.secret_key='My_Secret_Key'

    bcrypt.init_app(app) #To registered current flask app with this 'Bcrypt' instance
    register_route(app,db,bcrypt) #fn call


    return app

Now Create New File
run.py

from app import create_app

flask_app = create_app()



if __name__ == '__main__':
    flask_app.run(host='0.0.0.0',port=5500,debug=True)

Now Create new file
create_db.py

from app import create_app
from models import db

app=create_app()
with app.app_context():
    db.create_all()
    print("DATABASE CREATED SUCCESSFULLY")

Now In Terminal Write Command to

pip install flask_bcrypt, flask_sqlalchemy, werkzeug

Now To Create Database run Command in terminal

python create_db.py

if “DATABASE CREATED SUCCESSFULLY” it means your database is creates

and folder like this appear in your screen

Now install 2 Extensions

  1. sqlite
  1. sqlite Viewer

If This Is visible in your screen it means You Database is created perfectly

Now lets Update routers.py

from flask import render_template,url_for,request,redirect,current_app,session
from werkzeug.utils import secure_filename
from models import User,Post
import os

def register_route(app,db,bcrypt):

    @app.route('/',methods=['GET'])
    def index():
        if session.get("user"):
            user=session.get("user")
            return render_template("article.html",user=user)
        return render_template("index.html")


    @app.route('/login',methods=['GET','POST'])
    def login():
        if request.method=="POST":
            
            email=request.form['email']
            password=request.form['password']

            #FETCHING ALL USER DATA
            user=User.query.filter_by(email=email).first()
            if user and bcrypt.check_password_hash(user.password,password):
                #store user session excluding password(instagram session login
                # in current brower=>cookie file: user logged in ok)
                session['user']={
                    "id":user.id,
                    "username":user.username,
                    "profile_pic":user.profile_picture if user.profile_picture else "../static/image/default.png"
                }
            
                return redirect(url_for("index"))
            else:
                return render_template("login.html",error="INVALID EMAIL OR PASSWORD")
        else:
            return render_template("login.html")


    @app.route('/register', methods=['GET', 'POST'])
    def register():
        if request.method == 'POST':
            name = request.form['name']
            username = request.form['username']
            email = request.form['email']
            phone_no = request.form['phone_no']
            password = request.form['password']
            confirm_password = request.form['confirm_password']
            profile_picture = request.files['profile_picture']

            # Check if passwords match
            if password != confirm_password:
                message="Passwords do not match!"
                return render_template('register.html',message=message)

            # Hash password using bcrypt
            hashed_password = bcrypt.generate_password_hash(password).decode('utf-8')

            # Handle profile picture upload
            if profile_picture and allowed_file(profile_picture.filename):
                filename = secure_filename(profile_picture.filename)
                profile_picture_path = os.path.join(current_app.config['PROFILE_UPLOAD_FOLDER'], filename)
                profile_picture.save(profile_picture_path)
            else:
                profile_picture_path = None  # Default if no picture uploaded

            # Check if username or email already exists
            existing_user = User.query.filter((User.username == username) | (User.email == email)).first()
            if existing_user:
                message = "Username or email already taken."
                return render_template('register.html',message=message)

            # Create new user and add to database
            new_user = User(
                name=name,
                username=username,
                email=email,
                phone_no=phone_no,
                password=hashed_password,
                profile_picture=profile_picture_path
            )
            db.session.add(new_user)
            db.session.commit()

            message = "Registration successful! You can now log in."
            return render_template('login.html',message=message)

        return render_template('register.html')

    @app.route('/article',methods=['GET'])
    def article():
        if session.get('user'):
            user=session.get('user')
            articles=Post.query.all()  #fetching article from db
            return render_template("article.html",articles=articles, user=user)
        else:
            return render_template("index.html")
        
    @app.route('/create_blog',methods=['GET','POST'])
    def create_post():
        if session.get('user'):
            if request.method=='POST':
                title=request.form['title']
                content=request.form['content']
                category=request.form['category']
                user_id=session.get('user').id 
                image=request.files['image']
                filename=None
                blog_picture_path=None
                if image:
                    filename=secure_filename(image.filename) #1.jpg extract name of image
                    blog_picture_path=os.path.join(current_app.config["BLOG_UPLOAD_FOLDER"],filename) #server me uploaded file : path create
                    
                new_post= Post(
                    title=title,
                    content=content,
                    category=category,
                    user_id=user_id,
                    image_filename=blog_picture_path)
                db.session.add('new_post')  #2 or more post at one time ~~~>queue and saved one by one
                db.session.commit()
                return redirect(url_for("create_post"),success="POST CREATED SUCCESSFULLY")
            return render_template("create_post.html",success=request.args.get('success'))
        return render_template('login.html')
    
    @app.route('/logout',methods=['GET'])
    def logout():
        session.pop('user',None)
        return redirect(url_for('index'))
    
    def allowed_file(filename):
        return '.' in filename and filename.rsplit('.', 1)[1].lower() in {'png', 'jpg', 'jpeg', 'gif'}
    
def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in {'png', 'jpg', 'jpeg', 'gif'}
    

Scroll to Top