Skip to main content

A Flask-based Articles Management System with SEO optimization, admin panel, and maintenance features

Project description

Article Management System

A comprehensive Flask-based Content Management System (CMS) designed for managing articles with advanced SEO optimization, admin panel, and automated maintenance features.

Features

Core Functionality

  • Article Management: Create, read, update, and delete articles with server-side rendering
  • SEO Optimization:
    • Meta tag management (title, description, keywords)
    • JSON-LD schema.org structured data
    • Self-canonicalization
    • Descriptive URLs (auto-generated slugs)
    • SEO scoring and recommendations
  • HTML Import: Automatically parse and extract article data from HTML with schema.org markup
  • Admin Panel: Full-featured admin interface for content management
  • Responsive Design: Mobile-friendly horizontal card layout with Bootstrap 5
  • Pagination: Efficiently display 9 articles per page with full pagination support
  • User Authentication: Secure login/registration system with role-based access control
  • Comments System: Integrated with rcomments package for threaded comments
  • Likes/Dislikes: User engagement tracking
  • View Tracking: Automatic view count incrementation
  • Maintenance Automation:
    • Auto-delete articles older than configurable threshold (default: 30 days)
    • Keep maximum number of articles (default: 90)
    • Scheduled daily maintenance with APScheduler
    • Manual maintenance trigger

API Endpoints

Full RESTful API for React/TypeScript frontend integration:

  • GET /api/articles - Paginated article listing
  • GET /api/article/<slug> - Single article details
  • GET /api/article/<slug>/comments - Comments with pagination
  • POST /api/article/<slug>/comment - Add comment (authenticated)
  • DELETE /api/comment/<id> - Delete comment
  • POST /api/article/<slug>/like - Toggle like/dislike
  • GET /api/admin/analytics - Admin analytics dashboard
  • POST /api/admin/maintenance/run - Manual maintenance trigger
  • POST /api/admin/seo/analyze - SEO score analysis

Installation

Prerequisites

  • Python 3.8+
  • PostgreSQL 10+
  • pip (Python package installer)

Basic Installation

# Install from PyPI
pip install article-management-system

Database Setup

  1. Create a PostgreSQL database:
CREATE DATABASE article_management;
CREATE USER article_user WITH PASSWORD 'your-password';
GRANT ALL PRIVILEGES ON DATABASE article_management TO article_user;
  1. Configure environment variables (or use .env file):
export DATABASE_URL=postgresql://article_user:your-password@localhost:5432/article_management
export SECRET_KEY=your-secret-key-here
export SITE_URL=http://yourdomain.com

Initialize Database

# Initialize database and create default admin user
flask init-db

# Or using the CLI command
ams-cli init-db

Configuration

Environment Variables

Variable Default Description
SECRET_KEY (required) Flask secret key for sessions
DATABASE_URL (required) PostgreSQL connection URL
SITE_URL http://localhost:5000 Base URL of your site
SITE_NAME Article Management System Site name for meta tags
ARTICLES_PER_PAGE 9 Number of articles per page
MAINTENANCE_DAYS_THRESHOLD 30 Delete articles older than X days
MAINTENANCE_MAX_ARTICLES 90 Maximum articles to keep
RCOMMENTS_ENABLED true Enable/disable comments

Database Configuration

The system supports flexible database configuration:

Option 1: Full DATABASE_URL

export DATABASE_URL=postgresql://user:password@localhost:5432/dbname

Option 2: Individual components

export DB_USER=myuser
export DB_PASSWORD=mypassword
export DB_HOST=localhost
export DB_PORT=5432
export DB_NAME=article_management

Option 3: SQLite for development (not recommended for production)

export DATABASE_URL=sqlite:///dev.db

Custom Configuration Class

You can create a custom configuration class to override any setting:

from article_management.config import Config

class CustomConfig(Config):
    ARTICLES_PER_PAGE = 12
    MAINTENANCE_DAYS_THRESHOLD = 60
    SITE_NAME = "My Custom Site"
    SITE_URL = "https://mywebsite.com"
    # Override any other settings

Then pass it to create_app():

from article_management import create_app
app = create_app('my_module.CustomConfig')

Customization Guide

Custom Authentication (OAuth, SSO, etc.)

The system is designed to be extensible. You can replace or extend the authentication system:

1. Create a custom User model (optional):

# models.py
from article_management import db
from flask_login import UserMixin

class CustomUser(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(120), unique=True, nullable=False)
    # Add OAuth fields: oauth_provider, oauth_id, avatar_url, etc.

2. Create custom auth routes:

# routes/custom_auth.py
from flask import Blueprint, redirect, url_for
from flask_login import login_user

custom_auth_bp = Blueprint('custom_auth', __name__)

@custom_auth_bp.route('/login/google')
def google_login():
    # Implement OAuth flow
    # Redirect to Google OAuth endpoint
    pass

@custom_auth_bp.route('/login/google/callback')
def google_callback():
    # Handle OAuth callback
    # Get or create user
    # login_user(user)
    return redirect(url_for('main.index'))

3. Override the auth blueprint:

# In your application factory
def create_app(config_class='article_management.config.Config'):
    app = Flask(__name__)
    app.config.from_object(config_class)
    
    # Don't register the default auth blueprint
    # from article_management.routes.auth import bp as auth_bp
    # app.register_blueprint(auth_bp, url_prefix='/auth')
    
    # Register your custom auth instead
    from myapp.routes.custom_auth import custom_auth_bp
    app.register_blueprint(custom_auth_bp, url_prefix='/auth')

4. Use Flask-Dance or Authlib (recommended for OAuth):

from flask_dance.contrib.google import make_google_blueprint

google_bp = make_google_blueprint(
    client_id=os.getenv('GOOGLE_CLIENT_ID'),
    client_secret=os.getenv('GOOGLE_CLIENT_SECRET'),
    scope=["profile", "email"]
)
app.register_blueprint(google_bp, url_prefix="/login")

Custom Templates

Override any template by creating a templates/ directory and setting TEMPLATES_PATH in your config:

class CustomConfig(Config):
    TEMPLATES_PATH = ['/path/to/custom/templates', 'article_management/templates']

Flask will search paths in order, allowing you to override specific templates while keeping the rest.

Custom Static Files

Add custom CSS/JS by placing files in your own static directory:

class CustomConfig(Config):
    STATIC_FOLDER = '/path/to/custom/static'

Or use Flask's send_static_file override for more control.

Adding New Routes

Create a new blueprint in routes/ and register it in your app factory:

# routes/custom.py
from flask import Blueprint, render_template

custom_bp = Blueprint('custom', __name__)

@custom_bp.route('/custom-page')
def custom_page():
    return render_template('custom_page.html')

Then in your app:

from myapp.routes.custom import custom_bp
app.register_blueprint(custom_bp)

Extending the Article Model

Add custom fields to the Article model by creating a migration:

# In a migration file
op.add_column('articles', sa.Column('custom_field', sa.String(500)))

Then update your forms and templates accordingly.

Latest Updates (v1.1.0)

Recent Improvements

  1. Enhanced Reading Experience (March 2026)

    • Fixed article content width alignment with title (now both 800px)
    • Improved typography with serif fonts (Georgia, Times New Roman)
    • Better line-height (1.8) and font size (1.125rem)
    • Text justification with hyphenation for clean flow
    • Enhanced heading hierarchy with visual styling
    • Improved blockquotes, lists, code blocks, and tables
    • Responsive design with mobile-friendly padding
  2. Maintenance Fixes (March 2026)

    • Fixed MaintenanceSettings.run_maintenance() to work regardless of is_enabled flag
    • Manual "Run Maintenance Now" button now always executes
    • Fixed missing MaintenanceSettings import in API routes
    • Removed CSRF exemption issue from API endpoint
  3. Bug Fixes

    • Fixed import errors in API routes
    • Improved error handling in maintenance tasks

API Reference

Authentication Endpoints

  • GET /auth/login - Login page
  • POST /auth/login - Login submission
  • GET /auth/register - Registration page
  • POST /auth/register - Registration submission
  • GET /auth/logout - Logout

Article Endpoints

  • GET /api/articles - Paginated article listing
    • Query params: page, per_page, sort_by (date_published, view_count), order (asc, desc)
  • GET /api/article/<slug> - Single article details with JSON-LD
  • GET /api/article/<slug>/comments - Paginated comments
  • POST /api/article/<slug>/comment - Add comment (requires auth)
  • DELETE /api/comment/<id> - Delete comment (requires admin or comment author)
  • POST /api/article/<slug>/like - Toggle like/dislike (requires auth)

Admin Endpoints

  • GET /api/admin/analytics - Analytics dashboard data
  • POST /api/admin/maintenance/run - Manually trigger maintenance (requires admin)
  • POST /api/admin/seo/analyze - SEO score analysis (requires admin)

CLI Commands

The package includes a powerful CLI:

# Initialize database and create admin
ams-cli init-db

# Create admin user
ams-cli create-admin

# List all articles
ams-cli list-articles

# Delete article by ID
ams-cli delete-article 123

# Run maintenance manually
ams-cli run-maintenance

# Export all articles to JSON
ams-cli export-articles -o backup.json

Project Structure

article_management/
├── __init__.py          # Application factory
├── config.py            # Configuration classes
├── models.py            # Database models
├── seo_utils.py         # SEO utilities
├── html_parser.py       # HTML content parser
├── forms.py             # WTForms definitions
├── decorators.py        # Custom decorators
├── cli.py               # CLI commands
├── routes/
│   ├── __init__.py
│   ├── main.py          # Public routes
│   ├── admin.py         # Admin routes
│   ├── auth.py          # Authentication routes
│   └── api.py           # API endpoints
├── templates/           # Jinja2 templates
│   ├── base.html
│   ├── index.html
│   ├── article_detail.html
│   ├── auth/
│   └── admin/
├── static/
│   ├── css/style.css
│   └── js/main.js
└── wsgi.py              # WSGI entry point

Database Schema

Main Tables

  • users: User accounts with authentication
  • articles: Article content with SEO fields
  • comments: Threaded comments (integrated with rcomments)
  • likes: User likes/dislikes tracking
  • maintenance_settings: Maintenance configuration

Relationships

  • User → Comments (one-to-many)
  • User → Likes (one-to-many)
  • Article → Comments (one-to-many, cascade delete)
  • Article → Likes (one-to-many, cascade delete)
  • Comment → Replies (self-referential)

Deployment

Production Configuration

  1. Environment Setup:
export FLASK_ENV=production
export SECRET_KEY=your-very-secure-secret-key
export DATABASE_URL=postgresql://user:pass@host:5432/db
  1. Use a Production WSGI Server:
# Using Gunicorn
pip install gunicorn
gunicorn -w 4 "article_management.wsgi:app" -b 0.0.0.0:8000
  1. Set up Systemd service (Linux):
[Unit]
Description=Article Management System
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/path/to/app
Environment="PATH=/path/to/venv/bin"
EnvironmentFile=/path/to/.env
ExecStart=/path/to/venv/bin/gunicorn -w 4 "article_management.wsgi:app" -b 127.0.0.1:8000

[Install]
WantedBy=multi-user.target
  1. Nginx Configuration:
server {
    listen 80;
    server_name yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Database Migrations

# Initialize migrations
flask db init

# Create migration
flask db migrate -m "Description"

# Apply migration
flask db upgrade

Testing

Run tests with pytest:

pytest tests/

Security Features

  • Password hashing with werkzeug
  • CSRF protection with Flask-WTF
  • SQL injection prevention with SQLAlchemy
  • XSS protection in templates
  • Authentication required for admin routes
  • Role-based access control (admin/user)
  • Secure session management

Extending the Package

Custom Templates

Override templates by creating a templates/ directory and setting TEMPLATES_PATH in config.

Custom Static Files

Add custom CSS/JS by placing files in static/ directory.

Adding New Routes

Create a new blueprint in routes/ and register it in __init__.py.

Troubleshooting

Common Issues

  1. Database connection error:

    • Check PostgreSQL is running
    • Verify credentials in DATABASE_URL
    • Ensure database exists
  2. Template not found:

    • Check Flask can find the templates directory
    • Verify package installation with pip install -e .
  3. Static files not loading:

    • Ensure static/ folder exists
    • Check file permissions
  4. Migrations fail:

    • Ensure database user has proper privileges
    • Check Flask-Migrate is installed

License

MIT License - see LICENSE file for details

Changelog

v1.1.0 (March 2026)

  • Reading Experience: Completely redesigned article layout with consistent 800px width, serif typography, and professional publishing-quality styling
  • Maintenance Fixes: Manual maintenance now works correctly regardless of auto-maintenance setting
  • Bug Fixes: Fixed missing MaintenanceSettings import in API routes
  • Code Quality: Removed problematic CSRF import, improved error handling

v1.0.0

  • Initial release
  • Full CRUD operations for articles
  • SEO optimization with schema.org
  • HTML import with automatic parsing
  • Admin dashboard
  • User authentication
  • Comments system (rcomments integration)
  • Likes/dislikes
  • Maintenance automation
  • REST API for frontend integration
  • Responsive Bootstrap 5 UI

Usage

Running the Application

# Set Flask app
export FLASK_APP=article_management.wsgi:app
export FLASK_ENV=development

# Run development server
flask run

Or using the WSGI file directly:

python -m article_management.wsgi

Admin Panel

Access the admin panel at /admin after logging in with admin credentials.

Features:

  • Dashboard with statistics
  • Create articles by uploading HTML or pasting content
  • Edit existing articles
  • Manage all articles with search/filter
  • Configure maintenance settings
  • Run maintenance manually
  • SEO analysis tool

Creating Articles

Method 1: HTML Upload

Upload an HTML file with schema.org Article markup:

<article itemscope itemtype="https://schema.org/Article">
    <header>
        <h1 itemprop="headline">Article Title</h1>
        <meta itemprop="datePublished" content="2026-03-24">
        <meta itemprop="dateModified" content="2026-03-24">
    </header>

    <div itemprop="articleBody">
        <h2>Section Title</h2>
        <p>Article content...</p>
    </div>
</article>

Method 2: Manual Entry

Fill in all fields manually through the admin form.

Required HTML Structure:

  • <article itemscope itemtype="https://schema.org/Article">
  • <h1 itemprop="headline"> - Article title
  • <meta itemprop="datePublished"> - Publication date
  • <meta itemprop="dateModified"> - Last modified date
  • <div itemprop="articleBody"> - Main content

The system will automatically:

  • Extract title, dates, and excerpt from HTML
  • Generate SEO-friendly slug from title
  • Create JSON-LD schema
  • Set canonical URL (self-canonicalization by default)

SEO Features

The system provides comprehensive SEO optimization:

  1. Meta Tags: Title, description, keywords
  2. JSON-LD Schema: Automatic generation of schema.org Article markup
  3. Canonical URLs: Self-canonicalization or custom URLs
  4. Descriptive Slugs: Auto-generated from title, unique
  5. SEO Scoring: Real-time analysis with recommendations
  6. Open Graph: Automatic OG tags for social sharing
  7. Twitter Cards: Enhanced Twitter sharing

Maintenance Automation

The system automatically cleans up old articles based on your settings:

  • Daily Schedule: Runs every day at 2 AM
  • Deletion Rules:
    1. Delete articles older than MAINTENANCE_DAYS_THRESHOLD
    2. If total articles still exceed MAINTENANCE_MAX_ARTICLES, delete oldest articles
  • Manual Trigger: Run maintenance anytime from admin panel or CLI

API Integration with React/TypeScript

The system provides a complete REST API for frontend integration:

// Example React component
import React, { useEffect, useState } from 'react';
import { Article } from './types';

const ArticleList: React.FC = () => {
  const [articles, setArticles] = useState<Article[]>([]);
  const [page, setPage] = useState(1);

  useEffect(() => {
    fetch(`/api/articles?page=${page}`)
      .then(res => res.json())
      .then(data => setArticles(data.data.articles));
  }, [page]);

  return (
    <div>
      {articles.map(article => (
        <ArticleCard key={article.id} article={article} />
      ))}
    </div>
  );
};

CLI Commands

The package includes a powerful CLI:

# Initialize database and create admin
ams-cli init-db

# Create admin user
ams-cli create-admin

# List all articles
ams-cli list-articles

# Delete article by ID
ams-cli delete-article 123

# Run maintenance manually
ams-cli run-maintenance

# Export all articles to JSON
ams-cli export-articles -o backup.json

Project Structure

article_management/
├── __init__.py          # Application factory
├── config.py            # Configuration classes
├── models.py            # Database models
├── seo_utils.py         # SEO utilities
├── html_parser.py       # HTML content parser
├── forms.py             # WTForms definitions
├── decorators.py        # Custom decorators
├── cli.py               # CLI commands
├── routes/
│   ├── __init__.py
│   ├── main.py          # Public routes
│   ├── admin.py         # Admin routes
│   ├── auth.py          # Authentication routes
│   └── api.py           # API endpoints
├── templates/           # Jinja2 templates
│   ├── base.html
│   ├── index.html
│   ├── article_detail.html
│   ├── auth/
│   └── admin/
├── static/
│   ├── css/style.css
│   └── js/main.js
└── wsgi.py              # WSGI entry point

Database Schema

Main Tables

  • users: User accounts with authentication
  • articles: Article content with SEO fields
  • comments: Threaded comments (integrated with rcomments)
  • likes: User likes/dislikes tracking
  • maintenance_settings: Maintenance configuration

Relationships

  • User → Comments (one-to-many)
  • User → Likes (one-to-many)
  • Article → Comments (one-to-many, cascade delete)
  • Article → Likes (one-to-many, cascade delete)
  • Comment → Replies (self-referential)

Deployment

Production Configuration

  1. Environment Setup:
export FLASK_ENV=production
export SECRET_KEY=your-very-secure-secret-key
export DATABASE_URL=postgresql://user:pass@host:5432/db
  1. Use a Production WSGI Server:
# Using Gunicorn
pip install gunicorn
gunicorn -w 4 "article_management.wsgi:app" -b 0.0.0.0:8000
  1. Set up Systemd service (Linux):
[Unit]
Description=Article Management System
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/path/to/app
Environment="PATH=/path/to/venv/bin"
EnvironmentFile=/path/to/.env
ExecStart=/path/to/venv/bin/gunicorn -w 4 "article_management.wsgi:app" -b 127.0.0.1:8000

[Install]
WantedBy=multi-user.target
  1. Nginx Configuration:
server {
    listen 80;
    server_name yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Database Migrations

# Initialize migrations
flask db init

# Create migration
flask db migrate -m "Description"

# Apply migration
flask db upgrade

Testing

Run tests with pytest:

pytest tests/

Security Features

  • Password hashing with werkzeug
  • CSRF protection with Flask-WTF
  • SQL injection prevention with SQLAlchemy
  • XSS protection in templates
  • Authentication required for admin routes
  • Role-based access control (admin/user)
  • Secure session management

Extending the Package

Custom Templates

Override templates by creating a templates/ directory and setting TEMPLATES_PATH in config.

Custom Static Files

Add custom CSS/JS by placing files in static/ directory.

Adding New Routes

Create a new blueprint in routes/ and register it in __init__.py.

Troubleshooting

Common Issues

  1. Database connection error:

    • Check PostgreSQL is running
    • Verify credentials in DATABASE_URL
    • Ensure database exists
  2. Template not found:

    • Check Flask can find the templates directory
    • Verify package installation with pip install -e .
  3. Static files not loading:

    • Ensure static/ folder exists
    • Check file permissions
  4. Migrations fail:

    • Ensure database user has proper privileges
    • Check Flask-Migrate is installed

License

MIT License - see LICENSE file for details

Changelog

v1.0.0

  • Initial release
  • Full CRUD operations for articles
  • SEO optimization with schema.org
  • HTML import with automatic parsing
  • Admin dashboard
  • User authentication
  • Comments system (rcomments integration)
  • Likes/dislikes
  • Maintenance automation
  • REST API for frontend integration
  • Responsive Bootstrap 5 UI
  • CLI tools

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

article_management_system-1.1.1.tar.gz (57.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

article_management_system-1.1.1-py3-none-any.whl (65.7 kB view details)

Uploaded Python 3

File details

Details for the file article_management_system-1.1.1.tar.gz.

File metadata

File hashes

Hashes for article_management_system-1.1.1.tar.gz
Algorithm Hash digest
SHA256 88a2cf659dae97ac33cfbd836e01e92be68695f63743a572aa51be08fe532164
MD5 0813be0643e726b54f37224d97195361
BLAKE2b-256 8dbe6d2e0b44fc66d1350e4ec5ca3cbe6726d864ecb817b21e3a35fa93d29ca4

See more details on using hashes here.

File details

Details for the file article_management_system-1.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for article_management_system-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1e50d8d233978a30184b9809e3a623507653a3c5ca6c690b16f9aeb1c50dcaf7
MD5 8a02900df7132baa3c03978bb0a7461d
BLAKE2b-256 5750deca9e4bcd5d4b578fd7c67fc72ae4d5733919a6e6d48cf1ac7ba0826f97

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page