Write, share, and discover stories β complete with user profiles, profile pictures, comments, and likes.
Features β’ Security β’ Demo β’ Try it β’ Getting Started β’ Configuration β’ Project Structure β’ Roadmap
SocialBlog is a full-featured, multi-user blogging web app. Users can sign up, personalize their profile with an avatar, publish posts, and engage with the community through comments and likes. It's built with a clean, blueprint-based Flask architecture and a responsive Bootstrap 5 interface.
Full walkthrough: browse the feed, register, log in, personalize your profile with an avatar, publish a post, then like and comment.
Don't want to clone anything? Run the full app in the cloud with GitHub Codespaces β nothing to download or install:
- Click the badge above (or Code β Codespaces β Create codespace on main).
- Wait ~1 minute while it installs dependencies and seeds demo content.
- The app starts automatically and a browser tab opens on port 5000 β sign up and start posting.
Pre-seeded with sample users, posts, comments, and likes. Comment & post moderation runs with the built-in offline screen, so it works with no API key.
- π Authentication β register, log in, and log out with securely hashed passwords (Werkzeug)
- π§βπ¨ User profiles β upload a profile picture that's automatically resized (Pillow); supports JPG, JPEG, PNG, WebP, and GIF
- βοΈ Blog posts β full create, read, update, and delete (CRUD), restricted to each post's author
- π¬ Comments β any logged-in user can comment; a comment can be removed by its author or the post owner
- π‘οΈ Comment & post moderation β every post and comment is screened for toxicity before it's published via Google's free Perspective API, with an offline fallback so it works with zero setup
- β€οΈ Likes β one-click toggle like/unlike per user, with a live like count
- βοΈ React interactivity β polished React "islands" enhance the server-rendered pages: live toxicity preview as you type, async likes and comments (no page reload), and toast notifications
- π Pagination β clean, paginated feeds on the home page and user pages
- π¨ Modern UI β responsive Bootstrap 5 design with a styled confirmation modal for deletes
- π§ Custom error pages β friendly
403and404screens - ποΈ Migrations β schema managed with Flask-Migrate (Alembic)
| Layer | Technology |
|---|---|
| Backend | Flask, Flask-SQLAlchemy, Flask-Login, Flask-Migrate |
| Frontend | React 18 islands (Vite build) over Jinja2 + Bootstrap 5 |
| Forms | Flask-WTF, WTForms, email-validator |
| Images | Pillow |
| Database | SQLite (dev) / PostgreSQL (production on Render) |
| Auth | Werkzeug password hashing, session-based login |
| Moderation | Google Perspective API (with offline keyword fallback) |
Safety is built in at every layer β essential for a multi-user social app:
- π‘οΈ Toxicity moderation β every post and comment is screened for toxic or abusive language before it's saved (see the Content Moderation section below).
- π Hashed passwords β credentials are never stored in plain text (Werkzeug password hashing).
- π‘οΈ CSRF protection β every form is guarded with Flask-WTF CSRF tokens.
- π Authorization checks β only a post's author can edit or delete it, and a comment can be removed only by its author or the post owner (otherwise a
403). - ποΈ No insecure defaults β
SECRET_KEYis required (the app refuses to start without it) and secrets load from a git-ignored.env, never committed. - π§― Fails safe β if the moderation API is unavailable a local screen still runs, and moderation errors never break posting or commenting.
Posts and comments are screened before they're saved, so toxic or abusive content never reaches the page.
- Primary engine β Google Perspective API:
each comment is scored for
TOXICITY,SEVERE_TOXICITY,INSULT,PROFANITY,THREAT, andIDENTITY_ATTACK. If any score crosses its threshold, the comment is rejected with a friendly message. - Zero-config fallback: with no
PERSPECTIVE_API_KEYset (or if the API is unreachable), a lightweight offline keyword screen keeps the app safe by default β the feature works the moment you clone the repo. - Fails open: an unexpected moderation error never blocks commenting.
Enable the full API with a free key:
export PERSPECTIVE_API_KEY="your-key" # https://developers.perspectiveapi.comLogic lives in socialblog/moderation.py; the tests
mock the API so they run offline:
python -m unittest tests.test_moderationThe pages are server-rendered with Jinja2 + Bootstrap, then progressively enhanced with small React 18 "islands" built by Vite. This keeps the app fast and SEO-friendly while adding a modern, app-like feel:
- Live toxicity preview β as you type a post or comment, a debounced call to
/api/moderateshows a real-time "Looks respectful β" / "May be flagged β " pill. - Async likes β like/unlike updates instantly without a page reload.
- Async comments β comments post and appear in place, no reload.
- Toast notifications β server flash messages and client actions surface as elegant toasts.
Each island mounts onto a data-island="β¦" element, so pages still work if
JavaScript is disabled (forms fall back to normal submits). Flask injects the
hashed bundle via a manifest (socialblog/vite.py).
Develop / rebuild the frontend:
cd frontend
npm install
npm run build # outputs to socialblog/static/dist/ (committed so Render needs no Node)
npm run dev # optional: Vite dev server with HMRThe built bundle in
socialblog/static/dist/is committed, so the deployed app (and Codespaces) serves it directly β no Node step required in production.
- Python 3.10 or newer
pipandvenv
# 1. Clone the repository
git clone https://github.com/<your-username>/Social_Blog_Flask.git
cd Social_Blog_Flask
# 2. Create and activate a virtual environment
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 3. Install dependencies
pip install -r requirements.txt
# 4. Configure your environment (SECRET_KEY is required; auto-loaded from .env)
cp .env.example .env
python -c "import secrets; print(secrets.token_hex(32))" # paste as SECRET_KEY in .env
# 5. Create the database tables
flask --app app.py db upgrade
# 6. Run the app
python app.pyThen open https://social-blog-dmrg.onrender.com/ in your browser. π
π‘ macOS note: port
5000is used by AirPlay Receiver. If the server won't start, disable it in System Settings β General β AirDrop & Handoff β AirPlay Receiver, or run on another port withflask --app app.py run --port 5001.
Configuration is read from environment variables. A .env file at the project
root is auto-loaded on startup (via python-dotenv), so the easiest setup is
to copy the template and fill it in:
cp .env.example .env # then edit .env| Variable | Description | Default |
|---|---|---|
SECRET_KEY |
Flask secret key used for sessions & CSRF | required (no default) |
DATABASE_URL |
SQLAlchemy database URI | sqlite:///socialblog/data.sqlite |
PERSPECTIVE_API_KEY |
Google Perspective API key that enables toxicity moderation | offline fallback if unset |
MODERATION_OFFLINE_FALLBACK |
Set to 0 to disable the offline keyword screen |
1 (enabled) |
Generate a strong secret with:
python -c "import secrets; print(secrets.token_hex(32))"π
SECRET_KEYis required β the app refuses to start without it. Never commit your real.env.
| Method | Route | Description |
|---|---|---|
GET |
/ |
Home feed (paginated posts) |
GET |
/info |
About page |
GET/POST |
/register |
Create an account |
GET/POST |
/login |
Log in |
GET |
/logout |
Log out |
GET/POST |
/account |
Edit profile & upload picture |
GET |
/<username> |
A user's posts |
GET/POST |
/create |
Create a new post |
GET |
/<int:id> |
View a post (likes & comments) |
GET/POST |
/<int:id>/update |
Edit a post (author only) |
POST |
/<int:id>/delete |
Delete a post (author only) |
POST |
/<int:id>/like |
Like / unlike a post |
POST |
/<int:id>/comment |
Add a comment |
POST |
/comment/<int:id>/delete |
Delete a comment (author/owner) |
Social_Blog_Flask/
βββ app.py # Application entry point
βββ requirements.txt # Python dependencies
βββ migrations/ # Alembic database migrations
βββ frontend/ # React islands source (Vite)
β βββ package.json
β βββ vite.config.js
β βββ src/ # main.jsx + components (LikeButton, etc.)
βββ docs/screenshots/ # πΈ Put your README images here
βββ socialblog/
βββ __init__.py # App setup, config & blueprint registration
βββ models.py # User, BlogPost, Comment, Like models
βββ moderation.py # Perspective API toxicity screening
βββ vite.py # Injects the built React bundle into templates
βββ core/ # Home & info pages
β βββ views.py
βββ users/ # Auth, profiles & picture upload
β βββ forms.py
β βββ views.py
β βββ picture_handler.py
βββ blog_posts/ # Posts, comments, likes & JSON API
β βββ forms.py
β βββ views.py
β βββ api.py
βββ error_pages/ # 403 / 404 handlers
β βββ handlers.py
βββ templates/ # Jinja2 templates (Bootstrap 5)
βββ static/
βββ dist/ # Built React bundle (committed)
βββ profile_pics/ # Uploaded profile images
Ideas for future improvements:
- Edit comments
- Show who liked a post
- Tags & categories for posts
- Search and filtering
- Rich-text / Markdown post editor
- Email verification & password reset
Contributions are welcome! Feel free to open an issue or submit a pull request.
- Fork the project
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Distributed under the MIT License.
Tania Tatis
βοΈ If you like this project, consider giving it a star!