A functional, low-maintenance, and fun CMS for cozy news sites and blogs. A small Python server, a SQLite file, and your stories.
- Paper-style Frontend: Beautiful newspaper-style design for your readers
- Full CMS Backend: Manage all your stories with an easy-to-use interface
- Block Editor: Write stories with a friendly Editor.js editor (headings, lists, quotes, images, tables, embeds and more)
- Dark & Light Modes: Toggle between themes with a single click
- Preview Functionality: See how stories look before publishing
- SQLite Database: Zero-configuration, file-based database
- Low Maintenance: Standard-library Python backend, no pip installs, no build step
# Navigate to the Scooper directory
cd /path/to/Scooper
# Set admin credentials (required - the server will not start without them)
export SCOOPER_ADMIN_USER=your_username
export SCOOPER_ADMIN_PASS=your_secure_password
# Run the server
python3 server.pyThe application will start on http://localhost:8000
- Paper Site:
http://localhost:8000/ - CMS Backend:
http://localhost:8000/cms
Scooper/
├── server.py # Main application server
├── editorjs_render.py # Renders Editor.js block content to HTML
├── demo_render.py # Template rendering demo (safe: never wipes the DB by default)
├── test_editorjs_render.py # Tests for the block renderer
├── test_template_engine.py # Tests for the template engine
├── db/ # SQLite database
│ └── scooper.db # Database file (created on first run)
├── static/
│ ├── css/
│ │ └── style.css # All styles (paper + CMS)
│ ├── js/
│ │ └── script.js # Client-side JavaScript
│ └── uploads/ # Uploaded images
└── templates/
├── paper/
│ ├── index.html # Paper homepage
│ └── story.html # Single story view
└── cms/
├── dashboard.html # CMS dashboard
├── stories.html # Stories list
├── create.html # Create new story (block editor)
├── edit.html # Edit story (block or classic editor)
└── settings.html # Site settings
- Clean, newspaper-style design
- Responsive layout for all devices
- Featured stories grid
- Category tags
- Author and date information
- Link to CMS for admins
- Dashboard: Overview with statistics
- Stories: List all stories with status indicators
- Create/Edit: Block editor for new stories; older HTML stories keep the classic editor
- Preview: See how stories look before publishing
- Delete: Remove stories with confirmation
- Settings: Configure site title, description, categories, and theme
- Light and dark modes
- Persists across sessions (stored in database)
- Also saved to browser localStorage
- Smooth transitions between themes
Edit the configuration at the top of server.py:
HOST = "localhost" # Change to "0.0.0.0" for external access
PORT = 8000 # Change to any available portRequired: You must set environment variables for CMS authentication. The server will fail to start without them.
# Linux/macOS
export SCOOPER_ADMIN_USER=your_username
export SCOOPER_ADMIN_PASS=your_secure_password
python3 server.py
# Or as a one-liner:
SCOOPER_ADMIN_USER=your_username SCOOPER_ADMIN_PASS=your_secure_password python3 server.py
# Windows (Command Prompt)
set SCOOPER_ADMIN_USER=your_username
set SCOOPER_ADMIN_PASS=your_secure_password
python server.py
# Windows (PowerShell)
$env:SCOOPER_ADMIN_USER="your_username"
$env:SCOOPER_ADMIN_PASS="your_secure_password"
python server.py
⚠️ Security Note: Never use default credentials like "admin/admin". Always set strong, unique credentials via these environment variables.
Manage categories from the CMS: open Settings and use the category section to add, rename, or delete them. Stories keep their category if it is later removed.
Scooper uses SQLite, which creates a database file automatically in the db/ directory. No setup required!
The database includes:
storiestable: All news articlessettingstable: Site configuration
Important: Regular backups are essential for data protection. Scooper provides comprehensive backup solutions for both database and media assets.
Create manual backups:
# Database backup
python3 scripts/backup_db.py backup
# Media assets backup (uploads directory)
python3 scripts/backup_media.py backup
# Full backup (database + media)
python3 scripts/backup_all.pyBackups are stored in the backups/ directory:
- Database:
backups/scooper_backup_YYYYMMDD_HHMMSS.db - Media:
backups/media_backup_YYYYMMDD_HHMMSS.tar.gz
Set up automatic backups by adding to crontab:
# Edit crontab
crontab -e
# Add daily backup at 2:00 AM
0 2 * * * /usr/bin/python3 /path/to/scooper/scripts/backup_all.py >> /var/log/scooper_backup.log 2>&1For offsite backups, configure rclone:
# Install rclone
sudo apt install rclone
# Configure remote storage
rclone config
# Enable remote backup in Scooper
python3 scripts/backup_media.py config-set remote_enabled true
python3 scripts/backup_media.py config-set rclone_remote myremote
python3 scripts/backup_media.py config-set rclone_path scooper_backupsSee BACKUP_SETUP.md for complete backup documentation.
http.server (Python's built-in server) in production!
It is not designed for production use and may be vulnerable to DoS attacks.
-
Install Caddy (follow instructions at https://caddyserver.com/docs/install)
-
Configure Caddyfile (already provided):
# For production, replace 'localhost' with your domain in Caddyfile # Then start Caddy: caddy run
-
Run Scooper CMS:
# Make server accessible to Caddy (bind to 0.0.0.0) python3 server.py -
Access your site:
- Production:
https://yourdomain.com(HTTPS automatically enabled) - CMS:
https://yourdomain.com/cms(requires authentication)
- Production:
-
Install Nginx:
# Ubuntu/Debian sudo apt install nginx -
Configure Nginx (create
/etc/nginx/sites-available/scooper):server { listen 80; server_name yourdomain.com; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name yourdomain.com; ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem; location / { proxy_pass http://localhost:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
-
Enable SSL with Let's Encrypt (Certbot):
sudo apt install certbot python3-certbot-nginx sudo certbot --nginx -d yourdomain.com
- Python 3.6+
- Nothing to install with pip - the backend runs entirely on the Python standard library
- Internet access on first visit: a few frontend libraries load from a CDN (see below)
Scooper aims to be low-maintenance, not zero-dependency. Here is the complete list:
- Python standard library only - no pip packages, no build step
- Editor.js and its tools (Apache-2.0) - the block editor used when creating and editing stories
- Quill 1.3.7 (MIT) - legacy editor, only used when editing stories written before the block editor
- Google Fonts - Playfair Display and Nunito
The story editor degrades gracefully: if the CDN is unreachable, the form falls back to a plain textarea.
- Chrome/Edge (latest)
- Firefox (latest)
- Safari (latest)
- Works on mobile devices
Edit static/css/style.css to customize the appearance. The file uses CSS custom properties (variables) for easy theming.
Edit files in the templates/ directory to change the HTML structure.
Edit static/js/script.js to add custom client-side functionality.
Ctrl/Cmd + S: Save form (when editing a story)
- First Run: Sample stories are automatically created on first run
- Preview: Click the eye icon in the stories list to preview before publishing
- Drafts: Uncheck "Publish immediately" to save as draft
- Block Editor: Click the + button (or press Tab in an empty block) to insert headings, lists, quotes, images, tables and more
- Template Demo: Run
python3 demo_render.pyto render the paper templates with sample data (add--wipeto reset the database to demo content - it asks twice)
Scooper CMS is free to use for any purpose and is licensed with the MIT License.
- Fonts: Google Fonts (Playfair Display, Nunito)
- Editor: Editor.js (Apache-2.0)
- Legacy editor: Quill (MIT)
- Icons: Unicode emoji characters
- Mascot: Scoop the cat
