Files
sunday/README.md

492 lines
18 KiB
Markdown

# Sunday Comics - Webcomic Flask App
A Flask-based webcomic website with server-side rendering using Jinja2 templates.
## What is This?
**Sunday Comics** is a simple, ready-to-use website for publishing your webcomic online. If you're an artist or comic creator who wants to share your work on the web without dealing with complex platforms or databases, this is for you.
**What you get:**
- A clean, professional website to display your comics
- Easy navigation for readers (first, previous, next, latest buttons)
- An archive page where readers can browse all your comics
- RSS feed so readers can subscribe to updates
- Mobile-friendly design that works on phones and tablets
- No database required - just upload images and edit a simple text file
**Perfect for:**
- Independent comic artists starting their first webcomic
- Artists who want full control over their comic's presentation
- Creators who prefer simple file-based management over databases
- Anyone looking for a lightweight, customizable comic platform
**How it works:**
You add your comics by uploading image files and adding basic information (title, date, description) to a configuration file. The website handles everything else - displaying comics with navigation, creating an archive, generating an RSS feed, and making your comics shareable on social media.
No coding knowledge required for basic use - just follow the instructions below to add comics and customize your site's appearance.
## How Does This Compare to Rarebit?
[Rarebit](https://rarebit.neocities.org/) is an excellent static webcomic template that inspired this project. Sunday Comics offers a different approach with its own strengths:
**Sunday Comics:**
- Server-side application (Flask/Python) that runs on a web server
- Comics stored in a Python file - edit text to add comics
- Includes an RSS feed generator and helper scripts
- API endpoints for programmatic access
- Markdown support for rich-formatted content
- More flexibility for custom features and integrations
- Requires Python installation and basic server setup
**Rarebit:**
- Purely static HTML/CSS/JavaScript files
- Comics are inferred from static images upload - edit a JS to customize
- Can be hosted for free on GitHub Pages, Neocities, etc.
- No server or programming language required
- Simpler deployment - just upload files
**Which should you choose?**
- Choose **Rarebit** if you want the simplest possible setup and free hosting
- Choose **Sunday Comics** if you want server-side features, plan to add custom functionality, or prefer working with Python
- Both are great options - it depends on your technical comfort level and hosting preferences
Sunday Comics is meant as another option in the webcomic toolkit, not a replacement for Rarebit. Many creators might even use both for different projects!
## Simple Hosting Options
Don't have a server? No problem! Here are beginner-friendly options to get your comic online:
### PythonAnywhere (Recommended for Beginners)
**Best for:** First-time deployments, testing your comic site
- **Free tier available** (with pythonanywhere.com subdomain)
- **No credit card required** for free tier
- **Setup:** Upload your files through their web interface, configure a few settings
- **Great beginner tutorials** available on their site
- Visit: [pythonanywhere.com](https://www.pythonanywhere.com)
### Render
**Best for:** Automatic deployments from GitHub
- **Free tier available** (site sleeps after inactivity)
- **Setup:** Connect your GitHub repository, Render deploys automatically
- **No server management needed** - just push code to GitHub
- Custom domain support on free tier
- Visit: [render.com](https://render.com)
### Railway
**Best for:** Quick deployment with modern interface
- **Free trial credits** included ($5/month after)
- **Setup:** Connect GitHub, deploy with one click
- **Automatic deployments** when you update your code
- Simple dashboard to monitor your site
- Visit: [railway.app](https://railway.app)
### DigitalOcean App Platform
**Best for:** Scaling as your audience grows
- **$5/month** for basic tier (no free tier)
- **Very reliable** for growing comics with traffic
- **Automatic scaling** handles traffic spikes
- One-click deploy from GitHub
- Visit: [digitalocean.com/products/app-platform](https://www.digitalocean.com/products/app-platform)
### What You'll Need:
1. Your comic files and images
2. A GitHub account (free) for most modern hosting platforms
3. Basic familiarity with uploading files or pushing to GitHub
**Complete beginner?** Start with **PythonAnywhere** - it has the gentlest learning curve and requires no GitHub knowledge. You can always migrate to other platforms later as you get more comfortable.
## Features
- Comic viewer with navigation (First, Previous, Next, Latest)
- Client-side navigation using JSON API (no page reloads)
- Keyboard navigation support (arrow keys, Home/End)
- Archive page with thumbnail grid
- RSS feed support
- Markdown support for author notes and about page
- Optional icon-based navigation (comic navigation, header, and social links)
- Configurable logo and header/footer images
- Mobile-responsive with optional mobile-specific comic images
- Full-width and plain (headerless) display modes
- JSON API for programmatic access
- Open Graph and Twitter Card metadata for social sharing
- Server-side rendering with Jinja2
## Project Structure
```
sunday/
├── app.py # Main Flask application
├── comics_data.py # Comic data and configuration
├── requirements.txt # Python dependencies
├── Dockerfile # Production Docker image
├── docker-compose.yml # Docker Compose configuration
├── .dockerignore # Docker build exclusions
├── scripts/ # Utility scripts
│ ├── add_comic.py # Script to add new comic entries
│ └── generate_rss.py # Script to generate RSS feed
├── content/ # Markdown content
│ ├── about.md # About page content
│ └── author_notes/ # Author notes for comics (by date)
├── templates/ # Jinja2 templates
│ ├── base.html # Base template with navigation
│ ├── index.html # Latest comic page
│ ├── comic.html # Individual comic viewer
│ ├── archive.html # Archive grid
│ ├── page.html # Generic markdown page template
│ └── 404.html # Error page
└── static/ # Static files
├── css/
│ └── style.css # Main stylesheet
├── js/
│ └── comic-nav.js # Client-side navigation
├── images/ # Image directory
│ ├── comics/ # Comic images
│ ├── thumbs/ # Thumbnail images for archive
│ └── icons/ # Navigation and social icons (optional)
└── feed.rss # RSS feed (generated)
```
## Setup
1. Install dependencies:
```bash
pip install -r requirements.txt
```
2. Run the application:
```bash
python app.py
```
3. Visit http://127.0.0.1:3000 in your browser
## Environment Variables
The app can be configured via environment variables:
- `SECRET_KEY` - Flask secret key (defaults to 'your-secret-key')
- `PORT` - Port to run on (defaults to 3000)
- `DEBUG` - Enable debug mode (defaults to False)
**Development:**
```bash
export DEBUG=True
python app.py
```
**Production:**
```bash
export SECRET_KEY="your-secure-random-secret-key"
export PORT=3000
python app.py
```
## Configuration
The `comics_data.py` file contains both comic data and global configuration options:
### Global Settings
```python
COMIC_NAME = 'Sunday Comics' # Your comic/website name
SITE_URL = 'http://localhost:3000' # Your domain (update for production)
FULL_WIDTH_DEFAULT = False # Make all comics full-width by default
PLAIN_DEFAULT = False # Hide header/remove borders by default
LOGO_IMAGE = 'logo.png' # Path to logo (relative to static/images/)
LOGO_MODE = 'beside' # 'beside' or 'replace' title with logo
HEADER_IMAGE = None # Optional header image path
FOOTER_IMAGE = None # Optional footer image path
COMPACT_FOOTER = False # Display footer in compact mode
ARCHIVE_FULL_WIDTH = True # Full-width archive with 4 columns
USE_COMIC_NAV_ICONS = True # Use icons for comic navigation buttons
USE_HEADER_NAV_ICONS = True # Show icons in main header navigation
USE_FOOTER_SOCIAL_ICONS = True # Use icons for social links
SOCIAL_INSTAGRAM = None # Instagram URL (or None)
SOCIAL_YOUTUBE = None # YouTube URL (or None)
SOCIAL_EMAIL = None # Email mailto link (or None)
API_SPEC_LINK = None # API documentation link (or None)
```
## Adding Comics
Comics are stored in the `COMICS` list in `comics_data.py`. Each comic entry:
```python
{
'number': 1, # Comic number (required, sequential)
'filename': 'comic-001.png', # Image filename (required)
'mobile_filename': 'comic-001-mobile.png', # Optional mobile version
'date': '2025-01-01', # Publication date (required)
'alt_text': 'Alt text for comic', # Accessibility text (required)
'title': 'Comic Title', # Title (optional, shows #X if absent)
'author_note': 'Optional note', # Author note (optional, plain text)
'author_note_md': '2025-01-01.md', # Optional markdown file for author note
'full_width': True, # Optional: override FULL_WIDTH_DEFAULT
'plain': True # Optional: override PLAIN_DEFAULT
}
```
### Adding a New Comic
**Option 1: Use the script (recommended)**
```bash
# Add comic entry only
python scripts/add_comic.py
# Add comic entry AND create markdown file for author notes
python scripts/add_comic.py -m
```
This will automatically add a new entry with defaults. The `-m` flag creates a markdown file in `content/author_notes/{date}.md` with a template and adds the `author_note_md` field to the comic entry. Then edit `comics_data.py` to customize.
**Option 2: Manual**
1. Save your comic image in `static/images/comics/` (e.g., `comic-001.png`)
2. Optionally, create a thumbnail in `static/images/thumbs/` with the same filename
3. Add the comic entry to the `COMICS` list in `comics_data.py`
### Generating RSS Feed
After adding comics, regenerate the RSS feed:
```bash
python scripts/generate_rss.py
```
This creates/updates `static/feed.rss`
### Markdown Support
**Author Notes:**
Add the `author_note_md` field to your comic entry in `comics_data.py` to use markdown-formatted author notes. The field can be:
- Just a filename (e.g., `"2025-01-01.md"`) - looked up in `content/author_notes/`
- A path relative to `content/` (e.g., `"special/intro.md"`)
Markdown author notes take precedence over the plain text `author_note` field and render as HTML.
Example:
```python
# In comics_data.py
{
'number': 1,
'filename': 'comic-001.png',
'date': '2025-01-01',
'alt_text': 'First comic',
'author_note_md': '2025-01-01.md' # References content/author_notes/2025-01-01.md
}
```
```bash
# Create the markdown file
echo "# My First Comic\n\nThis is **bold** text!" > content/author_notes/2025-01-01.md
```
**About Page:**
The `/about` route renders `content/about.md` as HTML. Edit this file to customize your about page with markdown formatting.
**Note:** Client-side navigation displays author notes as plain text. Markdown author notes only render properly on initial page load (server-side rendering). For full markdown rendering, users need to refresh the page or navigate directly to the comic URL.
## Production Deployment
For production, you should **NOT** use Flask's built-in development server. Choose one of the following deployment methods:
### Option 1: Docker (Recommended)
**1. Generate a secure secret key:**
```bash
python -c "import secrets; print(secrets.token_hex(32))"
```
**2. Create a `.env` file:**
```bash
SECRET_KEY=your-generated-secret-key-here
```
**3. Build and run with Docker Compose:**
```bash
docker-compose up -d
```
**Or build and run manually:**
```bash
# Build the image
docker build -t sunday-comics .
# Run the container
docker run -d \
-p 3000:3000 \
-e SECRET_KEY="your-secret-key" \
-v $(pwd)/comics_data.py:/app/comics_data.py:ro \
-v $(pwd)/static/images:/app/static/images:ro \
--name sunday-comics \
sunday-comics
```
**View logs:**
```bash
docker-compose logs -f
```
### Option 2: Manual Deployment with Gunicorn
**1. Generate a Secure Secret Key**
```bash
python -c "import secrets; print(secrets.token_hex(32))"
```
**2. Set Environment Variables**
```bash
export SECRET_KEY="generated-secret-key-from-above"
export DEBUG=False
export PORT=3000
```
**3. Use a Production WSGI Server**
**Install Gunicorn:**
```bash
pip install gunicorn
```
**Run with Gunicorn:**
```bash
gunicorn app:app --bind 0.0.0.0:3000 --workers 4
```
### Using a Reverse Proxy (Recommended)
Set up Nginx or another reverse proxy in front of your app for:
- HTTPS/SSL termination
- Static file serving
- Load balancing
- Better security
### Additional Production Considerations
- Use a process manager (systemd, supervisor) for non-Docker deployments
- Set appropriate file permissions
- Enable HTTPS with Let's Encrypt
- Consider using a CDN for static assets
- Monitor logs and performance
- Set up automated backups of `comics_data.py`
## Upgrading to a Database
For larger comic archives, consider replacing the `COMICS` list with a database:
- SQLite for simple setups
- PostgreSQL/MySQL for production
- Use Flask-SQLAlchemy for ORM support
## Customization
### Branding
- Update `COMIC_NAME` in `comics_data.py` to change your comic's name
- Update `SITE_URL` in `comics_data.py` for production deployment
- Customize logo by setting `LOGO_IMAGE` and `LOGO_MODE`
### Styling
- Modify `static/css/style.css` to change colors, fonts, and layout
- Current color scheme uses blue (#3498db) and dark blue-gray (#2c3e50)
### About Page
- Edit `content/about.md` to add your bio and comic information (supports markdown)
### Icon Navigation
To use icon navigation:
1. Set `USE_COMIC_NAV_ICONS = True` in `comics_data.py`
2. Add icons to `static/images/icons/`:
- Comic navigation: `first.png`, `previous.png`, `next.png`, `latest.png`
- Header navigation: `alert.png`, `archive.png`, `info.png`
- Social links: `instagram.png`, `youtube.png`, `mail.png`
### Social Links
Configure social media links in `comics_data.py`:
```python
SOCIAL_INSTAGRAM = 'https://instagram.com/yourhandle'
SOCIAL_YOUTUBE = 'https://youtube.com/@yourchannel'
SOCIAL_EMAIL = 'mailto:your@email.com'
```
## Navigation
Sunday Comics provides multiple ways for readers to navigate through your comic:
### Mouse/Touch Navigation
- **Navigation buttons**: First, Previous, Next, Latest buttons (text or icon-based)
- **Click-through**: Click on the comic image to advance to the next comic
- **Archive grid**: Click any thumbnail to jump directly to that comic
### Keyboard Navigation
When viewing a comic, readers can use keyboard shortcuts for quick navigation:
- **Left Arrow** (`←`) - Go to previous comic
- **Right Arrow** (`→`) - Go to next comic
- **Home** - Jump to first comic
- **End** - Jump to latest comic
Keyboard shortcuts respect navigation boundaries (won't navigate before the first comic or past the latest) and don't interfere with typing in input fields.
## Pages
- `/` - Shows the latest comic
- `/comic/<id>` - View a specific comic by number
- `/archive` - Browse all comics in a grid
- `/about` - About the comic and author
- `/static/feed.rss` - RSS feed
## API Endpoints
The app exposes a JSON API for programmatic access:
- **GET `/api/comics`** - Returns all comics as a JSON array
```json
[
{
"number": 1,
"title": "First Comic",
"filename": "comic-001.png",
"date": "2025-01-01",
"alt_text": "The very first comic",
"author_note": "This is where your comic journey begins!"
}
]
```
- **GET `/api/comics/<id>`** - Returns a specific comic as JSON
```json
{
"number": 1,
"title": "First Comic",
"filename": "comic-001.png",
"date": "2025-01-01",
"alt_text": "The very first comic",
"author_note": "This is where your comic journey begins!"
}
```
Returns 404 with `{"error": "Comic not found"}` if the comic doesn't exist.
## Credits
- Inspired by [Rarebit](https://rarebit.neocities.org/)
- Favicon generated using [favicon.io](https://favicon.io)
- Example comics sourced from Boots and Her Buddies comic strip at [Comic Book Plus](https://comicbookplus.com/?cid=2561)
## License & Content Ownership
This software is licensed under the **MIT License** - see the [LICENSE](LICENSE) file for details.
### Your Comics Are Yours
The Sunday Comics software is open source and free to use, but **any comics, artwork, and content you create and publish using this platform remain your intellectual property**. The software license does not grant any rights to your creative work.
Think of it like using a camera: the camera might be shared, but the photos you take with it are yours. Sunday Comics is the camera, your comics are the photos.
### What This Means
- ✅ You can use Sunday Comics for free, forever
- ✅ You can modify the code however you want
- ✅ You can use it for commercial projects
- ✅ Your comics and artwork remain 100% yours
- ✅ No attribution required (but always appreciated!)
- ✅ No revenue sharing or licensing fees