Forge Your Content Empire - A modern, secure blog management system built with PHP and MySQL
π Portfolio Project - This project demonstrates full-stack PHP development, enterprise-grade security practices, and modern web application architecture. Built to showcase professional-level coding standards and security awareness.
π Live Demo β’ Quick Start β’ Features β’ Screenshots β’ Tech Stack β’ Security
Try PostForge live: https://postforge.infinityfree.me
Demo Credentials:
- Email:
admin@blog.com - Password:
admin123
PostForge features a smart demo mode that protects showcase content while allowing full CRUD testing:
- β Protected Demo Data: Existing posts and categories cannot be deleted
- β Full CRUD Testing: Create your own posts/categories to test all features
- β Session-Based Isolation: Your content is isolated from other visitors
- β Auto-Cleanup: Temporary content automatically removed after 24 hours
Try it: Attempt to delete a demo post, then create your own and delete it! Your changes won't affect other visitors.
What you can explore:
- β Admin dashboard with real-time analytics
- β Create, edit, and manage blog posts (with demo mode protection)
- β Category and comment management
- β Profile settings with image upload
- β Security features (rate limiting - try 5 wrong passwords!)
- β Responsive design on mobile and desktop
- Live Demo
- Quick Start (60 seconds)
- Screenshots
- Overview
- Key Highlights
- Features
- Technical Challenges Solved
- Tech Stack
- Installation
- Demo Credentials
- Project Structure
- Security Features
- Production Deployment
- Contributing
- License
Get PostForge running on your local machine in under a minute - no configuration needed!
# 1. Clone the repository
git clone https://github.com/mrajguruu/PostForge.git
cd PostForge
# 2. Create database
mysql -u root -p -e "CREATE DATABASE blog_management CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"
# 3. Import database schema
mysql -u root -p blog_management < sql/database.sql
# 4. Place in web server directory (XAMPP example)
# Copy to C:\xampp\htdocs\PostForge
# 5. Open in browser
# http://localhost/PostForge/public/index.phpπ That's it! No .env file needed, no complex configuration. Login with:
- Email:
admin@blog.com - Password:
admin123
Note: Works out-of-the-box with default XAMPP/WAMP settings (localhost, root user, no password)
Real-time analytics with post stats, categories, comments, and recent activity
Complete CRUD operations with rich text editor, image uploads, and category assignment
Secure login with rate limiting (5 attempts lockout) and session management
Responsive 3-column grid layout with featured posts and category filtering
WhatsApp-style profile picture upload with password management
Note: Screenshots showcase the actual working application. Clone and run to see it live!
PostForge is a comprehensive blog management system designed to provide a complete blogging platform with an intuitive admin panel. Built with security-first principles, this system offers robust content management capabilities, comment moderation, and a beautiful, responsive user interface.
- Production-Ready: Industry best practices with clean, maintainable code
- Complete CRUD: Full create, read, update, delete operations for posts and categories
- Security-Focused: Implements OWASP security standards (CSRF, XSS, SQL injection prevention)
- Modern UI/UX: Clean, professional design using Bootstrap 5
- Profile Management: WhatsApp-style profile picture upload with intelligent time displays
|
|
- Lines of Code: 3,500+
- Security Features: 10+
- PHP Files: 21
- Database Tables: 4 (normalized design)
- Security Score: A+ Grade
- Secure login system with password hashing (bcrypt)
- Session management with timeout protection
- CSRF protection on all forms
- Remember me functionality
- Secure logout
- Full CRUD Operations
- Create, read, update, and delete blog posts
- Rich text editor for content creation
- Featured image upload with validation
- Auto-slug generation from titles
- Excerpt generation
- Post Organization
- Category assignment
- Draft/Published status management
- View counter
- Search and filter capabilities
- Advanced Features
- Pagination (10 posts per page)
- Bulk actions support
- Image preview before upload
- Responsive table layout
- Demo mode protection (session-based content isolation)
- Create and manage post categories
- Category-wise post count
- Edit and delete categories
- Protection against deleting categories with posts
- SEO-friendly URL slugs
- Comment Moderation
- Approve/reject comments
- Mark as spam
- Filter by status (pending, approved, spam)
- Delete permanently
- Public Comment Form
- Name and email validation
- Content sanitization
- Auto-pending status
- Admin Dashboard
- Recent comments overview
- Quick moderation actions
- Link to parent post
- Real-time Statistics
- Total posts count
- Published vs draft posts
- Total categories
- Pending comments count
- Total views across all posts
- Total admin users count
- Recent Activity
- Latest 5 posts
- Recent comments with moderation options
- Quick action buttons
- Visual Design
- Color-coded stat cards
- Responsive grid layout
- Icon-based navigation
- Profile Management
- Profile picture upload with preview
- WhatsApp-style camera overlay interface
- Circular image cropping
- Gradient placeholder with initials
- Account Settings
- Change password functionality
- View account information
- Last login tracking
- Profile Display
- Profile pictures on public posts
- Author avatars in admin header
- About Author sidebar widget
- Homepage
- Featured post showcase
- 3-column responsive grid
- Post cards with thumbnails
- Category badges
- View and comment counts
- Single Post View
- Full-width featured image
- Formatted content display
- Author and date information
- Comment section
- Related posts
- Category Pages
- Filter posts by category
- Breadcrumb navigation
- Intelligent Time Display
- "Just now" for recent activity (0-10 seconds)
- Seconds ago (10-59 seconds)
- Minutes ago (1-59 minutes)
- Hours ago (1-23 hours)
- Days ago (1-6 days)
- Weeks ago (1-4 weeks)
- Months ago (1-11 months)
- Years ago (1-4 years)
- Full date for 5+ years old content
- Timezone Handling
- Configurable timezone support
- Automatic synchronization with MySQL
- Works globally with any timezone
- Accurate relative time calculations
- Color Palette
- Primary Blue:
#2563eb - Success Green:
#10b981 - Warning Orange:
#f59e0b - Danger Red:
#ef4444
- Primary Blue:
- Typography
- Font: Inter, Segoe UI, Roboto
- Responsive font sizes
- Optimized readability
- Components
- Bootstrap 5 framework
- Bootstrap Icons
- Custom CSS enhancements
- Smooth transitions and hover effects
Problem: Login systems are vulnerable to automated password-guessing attacks that can try thousands of combinations.
Solution Implemented:
- Session-based rate limiting tracking failed attempts
- 5-attempt threshold with 15-minute account lockout
- Countdown timer showing remaining lockout time
- 0.5-second delay on each failed attempt to slow attackers
- Remaining attempts counter to warn legitimate users
Code Reference: admin/login.php:22-38, admin/login.php:86-98
Impact: Prevents automated attacks while maintaining usability for legitimate users
Problem: Users across different timezones seeing incorrect "time ago" displays (e.g., "5 hours ago" for posts just created).
Solution Implemented:
- Centralized timezone configuration in
config/config.php - PHP timezone synchronized with MySQL server timezone
- Intelligent time calculation using Unix timestamps
- Progressive time display (seconds β minutes β hours β days β weeks β months β years)
- Fallback to full date for very old content (5+ years)
Code Reference: includes/functions.php:109-179, config/config.php:42
Impact: Accurate time displays globally, better user experience
Problem: User-uploaded files can contain malicious code or exploit server vulnerabilities.
Solution Implemented:
- MIME type verification using
finfo(not just extension checking) - File size limits (2MB) to prevent resource exhaustion
- Random filename generation (32-byte hex) to prevent overwriting
- Extension whitelist (jpg, jpeg, png, gif only)
- Separate upload directories for posts and profiles
- Server-side validation before client-side
Code Reference: includes/functions.php:211-268
Impact: Prevents malicious uploads while allowing legitimate user content
Problem: Attackers can trick authenticated users into performing unwanted actions.
Solution Implemented:
- Cryptographically secure token generation using
random_bytes(32) - Timing-safe token comparison with
hash_equals()to prevent timing attacks - Token regeneration on each form display
- Token validation on all state-changing operations
Code Reference: includes/functions.php:20-37
Impact: Protects against cross-site request forgery attacks
Problem: Need different settings for development (show errors) vs production (hide errors), without code changes.
Solution Implemented:
- Environment detection using
getenv()with sensible defaults .envfile support for production deployment- Automatic error handling based on environment
- Database credentials fallback for local development
- Zero-configuration local setup
Code Reference: config/config.php:9-59
Impact: Works out-of-box locally, easily deployable to production
Problem: User input in database queries can allow attackers to execute arbitrary SQL commands.
Solution Implemented:
- PDO prepared statements for all database operations
- Parameter binding for user inputs
- No string concatenation in SQL queries
- Input validation and type checking
Code Reference: All database operations use PDO, example: admin/login.php:53-54
Impact: Complete protection against SQL injection attacks
- PHP 7.4+
- Object-Oriented Programming
- PDO for database operations
- Prepared statements (SQL injection prevention)
- Session management
- File upload handling
- MySQL 5.7+ / MariaDB 10.3+
- Normalized database design
- Foreign key constraints
- Indexes for performance
- UTF-8 character support
- HTML5 - Semantic markup
- CSS3 - Custom styling with CSS variables
- Bootstrap 5.3 - Responsive framework
- JavaScript (ES6+) - Client-side validation and interactivity
- Bootstrap Icons - Comprehensive icon library
- XAMPP/WAMP - Local development environment
- Git - Version control
- VS Code - Code editor
Before you begin, ensure you have the following installed:
- PHP >= 7.4
- MySQL >= 5.7 or MariaDB >= 10.3
- Apache web server
- Composer (optional, for dependency management)
git clone https://github.com/mrajguruu/PostForge.git
cd PostForge-
Create Database
# Access MySQL mysql -u root -p # Create database CREATE DATABASE blog_management CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-
Import Database Schema
# Import the SQL file mysql -u root -p blog_management < sql/database.sql
Or use phpMyAdmin:
- Open phpMyAdmin
- Select
blog_managementdatabase - Go to Import tab
- Choose
sql/database.sqlfile - Click Go
-
Environment Configuration (Recommended)
Copy the
.env.examplefile to.env:cp .env.example .env
Edit
.envwith your settings:# Environment APP_ENV=development # Site Configuration SITE_NAME=PostForge SITE_URL=http://localhost/PostForge ADMIN_EMAIL=admin@postforge.com # Database DB_HOST=localhost DB_NAME=blog_management DB_USER=root DB_PASS=your_password_here # Timezone TIMEZONE=Asia/Kolkata
Important: Never commit
.envto version control! It's already in.gitignore. -
Alternative: Direct Configuration
If not using
.env, editconfig/config.phpdirectly:define('DB_HOST', 'localhost'); define('DB_NAME', 'blog_management'); define('DB_USER', 'root'); define('DB_PASS', 'your_password_here');
-
Configure Timezone Settings
Edit
config/config.phpand set the timezone to match your MySQL server:// Set this to your server's timezone date_default_timezone_set('Asia/Kolkata'); // Change as needed
Common Timezones:
Asia/Kolkata- India (IST)America/New_York- US EasternEurope/London- UKUTC- Universal TimeAsia/Tokyo- JapanAustralia/Sydney- Australia
Important: This must match your MySQL server timezone for accurate time calculations and "time ago" displays.
-
Set Up File Permissions
# Make uploads and logs directories writable chmod 755 uploads/ chmod 755 uploads/posts/ chmod 755 uploads/profiles/ chmod 755 logs/
# Create necessary directories (if not exists)
mkdir -p uploads/posts
mkdir -p uploads/profiles
mkdir -p logs- Copy project folder to
C:\xampp\htdocs\ - Start Apache and MySQL from XAMPP Control Panel
- Access:
http://localhost/PostForge/
- Copy project folder to
C:\wamp64\www\ - Start WAMP services
- Access:
http://localhost/PostForge/
php -S localhost:8000 -t public/Access at: http://localhost:8000
- Public Site:
http://localhost/PostForge/public/index.php - Admin Panel:
http://localhost/PostForge/admin/login.php
Email: admin@blog.com
Password: admin123
Note: Change these credentials in production! The password hash in the database uses bcrypt.
PostForge/
β
βββ π config/
β βββ config.php # Site configuration
β βββ database.php # Database connection (PDO)
β
βββ π admin/
β βββ login.php # Admin login page
β βββ logout.php # Logout script
β βββ dashboard.php # Main admin dashboard
β βββ posts.php # All posts listing
β βββ post-form.php # Add/Edit post form
β βββ categories.php # Category management
β βββ comments.php # Comment moderation
β βββ settings.php # Admin settings & profile
β βββ π includes/
β βββ header.php # Admin header
β βββ sidebar.php # Admin sidebar
β βββ footer.php # Admin footer
β
βββ π public/
β βββ index.php # Homepage
β βββ post.php # Single post view
β βββ category.php # Category posts
β βββ π includes/
β βββ header.php # Public header
β βββ footer.php # Public footer
β
βββ π assets/
β βββ π css/
β β βββ admin.css # Admin panel styles
β β βββ public.css # Public site styles
β βββ π js/
β β βββ admin.js # Admin JavaScript
β β βββ public.js # Public JavaScript
β βββ π images/
β βββ logo.png # Site logo
β
βββ π uploads/
β βββ π posts/ # Uploaded post images
β βββ π profiles/ # Admin profile pictures
β
βββ π includes/
β βββ functions.php # Helper functions
β βββ auth.php # Authentication middleware
β
βββ π sql/
β βββ database.sql # Database schema & demo data
β
βββ .gitignore # Git ignore rules
βββ README.md # This file
// Password hashing with bcrypt
$hashed = password_hash($password, PASSWORD_BCRYPT);
// Verification
password_verify($input, $hashed);// Using prepared statements
$stmt = $pdo->prepare("SELECT * FROM posts WHERE id = :id");
$stmt->execute(['id' => $id]);// Output escaping
echo htmlspecialchars($data, ENT_QUOTES, 'UTF-8');// Token generation
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
// Validation
hash_equals($_SESSION['csrf_token'], $_POST['csrf_token']);session_start([
'cookie_httponly' => true,
'cookie_samesite' => 'Strict'
]);
session_regenerate_id(true);- File type checking (MIME type)
- File size limits (2MB maximum)
- Random filename generation
- Extension whitelist
// Protect demo data from deletion
if ($post['is_demo'] == 1) {
redirect('posts.php', 'Cannot delete demo content...', 'warning');
}
// Session-based content isolation
$_SESSION['user_created_posts'][] = $newPostId;
// Auto-cleanup temporary content
DELETE FROM posts WHERE is_demo = 0 AND created_at < DATE_SUB(NOW(), INTERVAL 24 HOUR);Features:
- Session-based temporary content tracking
- Protected demo data (cannot be deleted by visitors)
- Auto-cleanup of visitor-created content after 24 hours
- Content isolation between different users
Before deploying to production, complete these critical steps:
-
Environment Configuration
# Copy .env.example to .env cp .env.example .env # Edit .env and set: APP_ENV=production SITE_URL=https://yourdomain.com DB_PASS=strong_password_here
-
Security Hardening
- β
Ensure
APP_ENV=productionin.env(disables error display) - β Set strong database password
- β Change default admin password after first login
- β
Update
ADMIN_EMAILto real email address - β Enable HTTPS (use Let's Encrypt or similar)
- β Review and restrict file permissions
- β
Ensure
-
File Permissions (Linux/Unix)
# Set directory permissions find . -type d -exec chmod 755 {} \; # Set file permissions find . -type f -exec chmod 644 {} \; # Make uploads and logs writable chmod 755 uploads/ uploads/posts/ uploads/profiles/ logs/
-
Database Security
- Create a dedicated MySQL user (don't use root)
- Grant only necessary privileges
CREATE USER 'postforge_user'@'localhost' IDENTIFIED BY 'strong_password'; GRANT SELECT, INSERT, UPDATE, DELETE ON blog_management.* TO 'postforge_user'@'localhost'; FLUSH PRIVILEGES;
-
Apache Configuration (Recommended) Create
.htaccessin root directory:# Disable directory listing Options -Indexes # Protect sensitive files <FilesMatch "\.(env|log|sql|md)$"> Order allow,deny Deny from all </FilesMatch> # Enable HTTPS redirect RewriteEngine On RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
-
Monitoring & Maintenance
- Monitor
logs/php-errors.logregularly - Set up automated database backups
- Keep PHP and MySQL updated
- Review security logs periodically
- Monitor
Solution: Check config/config.php and verify MySQL credentials
Solution: chmod 755 uploads/ uploads/posts/
Solution: Check PHP error logs, ensure session is started
Solution: Verify UPLOAD_URL in config.php matches your server path
Problem: Comments or posts showing "5 hours ago" when just posted
Solution: Set timezone in config/config.php to match MySQL server
Example: date_default_timezone_set('Asia/Kolkata');
Solution:
1. Create uploads/profiles/ directory
2. Set permissions: chmod 755 uploads/profiles/
3. Verify PROFILE_UPLOAD_DIR in config.php
Contributions are welcome! This is a portfolio project, but I'm open to improvements and suggestions.
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'feat: Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Please read CONTRIBUTING.md for details on the code of conduct and development process.
- Unit tests with PHPUnit
- API endpoints for mobile app
- Multi-language support
- Email notifications
- Dark mode theme
This project is licensed under the MIT License - see the LICENSE file for details.
MIT License - Copyright (c) 2025 PostForge
Developer: Mohit Rajguru
- LinkedIn: https://www.linkedin.com/in/mohitrajguru
- GitHub: https://github.com/mrajguruu
Project Links:
- Repository: https://github.com/mrajguruu/PostForge
- Issues: https://github.com/mrajguruu/PostForge/issues
- Documentation: README.md, SECURITY.md, DEPLOYMENT_GUIDE.md
Made with β€οΈ using PHP & MySQL
If you found this project helpful, please give it a β!
This project demonstrates:
- β Full-stack PHP development
- β Enterprise-grade security (OWASP standards)
- β Modern web architecture
- β Production-ready code quality
- β Professional documentation