Files
sunday/README.md
2025-11-14 15:10:50 +10:00

279 lines
7.3 KiB
Markdown

# Sunday Comics - Webcomic Flask App
A Flask-based webcomic website with server-side rendering using Jinja2 templates.
## Features
- Comic viewer with navigation (First, Previous, Next, Latest)
- Client-side navigation using JSON API (no page reloads)
- Archive page with thumbnail grid
- RSS feed support
- JSON API for programmatic access
- Open Graph and Twitter Card metadata for social sharing
- Responsive design
- Server-side rendering with Jinja2
- Clean, comic-focused layout
## Project Structure
```
sunday/
├── app.py # Main Flask application
├── comics_data.py # Comic data (edit this to add comics)
├── 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
├── templates/ # Jinja2 templates
│ ├── base.html # Base template with navigation
│ ├── index.html # Latest comic page
│ ├── comic.html # Individual comic viewer
│ ├── archive.html # Archive grid
│ ├── about.html # About page
│ └── 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
└── 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
```
## 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)
'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)
}
```
### 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. 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`
## 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 "Sunday Comics" references in `templates/base.html`
- Update site title and footer text
### 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 `templates/about.html` to add your bio and comic information
## 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
[Add your license here]