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:
- Frontend (Client-Side) – The part users interact with (HTML, CSS, JavaScript).
- Backend (Server-Side) – The logic that processes user requests and connects to the database (Python + Flask).
- 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:
- Users register/log in to access their dashboard.
- Logged-in users can create, edit, and delete blog posts.
- Visitors can view all blogs without logging in.
- Users can comment on blog posts.
- Admins can manage users and blogs.
- 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>© 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
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
- sqlite
- 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'}