Weblog is a blogging platform I built with Django. It started as a way to practice a full content workflow end to end — writing posts, moderating comments, handling users — and grew into something closer to a small magazine, with an editorial review queue and a ticket-based support system on top.
The whole thing is RTL-first and designed around Persian content. The frontend is plain Django templates with vanilla CSS and JavaScript — no frontend frameworks — mostly because I wanted to understand how far you can get without them.
Stack: Django 6 · PostgreSQL · server-rendered templates · vanilla CSS/JS · Pillow
Writing and publishing
- Blog posts with a featured image, excerpt, tags, and an estimated reading time
- Categories in a parent → child tree, each with its own listing page
- Colored tags with their own pages and a tag cloud
- Search, a yearly archive, and "popular" / "recent" feeds
- An editorial workflow: a post moves through draft → pending → published (or rejected), and staff get a review queue to approve what's pending
Community
- Comments from both guests and registered users, with an active/inactive moderation flag
- User profiles with an avatar, cover image, bio, social links, and some live stats
- An author directory ranked by activity
- In-app notifications with an unread counter
Support
- A ticketing system with priorities, a four-stage status flow, and threaded staff/user replies
- A staff dashboard with content stats, pending-post approval, and the latest tickets
Look and feel
- Dark / light theme that remembers your choice
- Scroll-reveal animations, animated counters, ripple buttons, and a glassmorphism header
- Responsive layout with a mobile navigation drawer
The design leans on a single CSS-variable–driven stylesheet (static/css/style.css), so the whole site can be re-themed by editing one :root block. I took a lot of visual cues from Smashing Magazine — the signature red, the heavy headings, and the post cards that tilt slightly on hover.
You'll need Python 3.13+ and PostgreSQL running locally on port 5432.
git clone https://github.com/mohammadreza829/weblog.git
cd weblog
python -m venv venv
source venv/bin/activate # on Windows: venv\Scripts\activate
pip install -r requirements.txtCreate the database (connection settings live in blog_project/settings.py under DATABASES — change the password before you put this anywhere real):
CREATE DATABASE blog_db;
CREATE USER blog_admin WITH PASSWORD '123456789';
GRANT ALL PRIVILEGES ON DATABASE blog_db TO blog_admin;Then migrate and run:
python manage.py migrate
python manage.py seed_demo # optional — fills the site with demo content
python manage.py runserverOpen http://127.0.0.1:8000 and you should see a fully populated homepage.
Since an empty blog is hard to judge, I wrote a seed_demo management command that fills the database with realistic Persian content in a few seconds:
python manage.py seed_demo
python manage.py seed_demo --posts 100 --users 20 --tickets 10| Option | Default | What it controls |
|---|---|---|
--posts |
48 | Blog posts to generate |
--users |
10 | Demo users |
--tickets |
10 | Support tickets |
It creates an admin superuser (if one doesn't exist), demo users with Persian names and bios, a handful of categories and colored tags, posts with SEO-friendly slugs and publish dates spread over six months, plus comments, ticket threads, and notifications. It's idempotent, so running it more than once won't create duplicates.
weblog/
├── blog_project/ # settings, root URLconf, context processors
├── blog/ # posts, tags, dashboard, search, archive (+ the seed_demo command)
├── accounts/ # auth, profiles, notifications, author directory
├── categories/ # hierarchical categories
├── comments/ # comment submission & moderation
├── ticket/ # support tickets & replies
├── templates/ # base layout + all page templates
├── static/ # style.css (the whole design system) + main.js
└── media/ # user uploads, created at runtime
Each app is fairly self-contained: blog holds the post model with its status workflow, reading time, and view counter; accounts auto-creates a profile for every user via signals; categories is a self-referencing parent/child tree; comments handles guest and authenticated commenting; and ticket is the support side with its status flow and replies.
The seed_demo command sets these up for local development only:
| Role | Username | Password |
|---|---|---|
| Admin | admin |
admin1234 |
| Demo users | user1 … userN |
demo1234 |
Don't ship these — rotate them and set DEBUG = False before this goes anywhere public.
Released under the MIT License — feel free to use, modify, and learn from it.