| config.json | ||
| generate_config.py | ||
| index.html | ||
| LICENSE | ||
| parts.csv | ||
| README.md | ||
Comic Simple Reader
A lightweight, static HTML comic reader. No build tools, no dependencies, no server-side code. Drop your images in folders, run one Python script, open a browser.
Licensed under the Apache License 2.0.
Features
- Landing page with chapter thumbnails
- Chapter-by-chapter reading with prev/next navigation
- Sidebar with quick-jump bookmarks ("parts") per chapter
- Go-to-page input
- Keyboard navigation (← →)
- Responsive — works on desktop and mobile
- Pure static HTML/CSS/JS — host anywhere
File structure
/
├── index.html # The entire reader (one file)
├── config.json # Chapter list — generated by the Python script
├── parts.csv # Navigation bookmarks — written by hand
├── generate_config.py # Script that builds config.json from your folders
├── LICENSE
├── README.md
└── chapters/
├── chapter-01/
│ ├── 001.jpg
│ ├── 002.jpg
│ └── ...
├── chapter-02/
│ └── ...
└── ...
Quick start
1. Add your images
Create one folder per chapter inside chapters/. Name folders so they sort correctly alphanumerically — for example chapter-01, chapter-02, etc. Name image files the same way: 001.jpg, 002.jpg, …
Supported formats: .jpg, .jpeg, .png, .gif, .webp
2. Generate config.json
python generate_config.py
This scans all folders inside chapters/, sorts them alphanumerically, and writes config.json. Run it again whenever you add or rename chapters or pages.
Edit the top of generate_config.py to set your comic title:
COMIC_TITLE = "My Comic"
3. Edit parts.csv (optional)
parts.csv defines the quick-navigation bookmarks shown in the sidebar. Each line is:
<chapter-folder>,<Part Name>,<local page number>
The chapter folder must match the folder name inside chapters/. The page number is local to that chapter (starts at 1). Lines starting with # are comments.
Example:
chapter-01,Prologue,1
chapter-01,The Cave,4
chapter-01,Escape,9
chapter-02,Arrival,1
chapter-02,The Storm,6
If parts.csv is missing or a chapter has no entries, the sidebar shows a placeholder message for that chapter.
4. Add a subtitle (optional)
Open config.json and add a subtitle field:
{
"title": "My Comic",
"subtitle": "A story in chapters",
"chapters": [ ... ]
}
5. Start a local server
Browsers block fetch() from file:// URLs for security reasons, so you need a local HTTP server to test:
python -m http.server 8000
Then open http://localhost:8000 in your browser. Press Ctrl+C to stop.
6. Deploy
Upload all files to any static hosting service:
- GitHub Pages — push to a repo, enable Pages in Settings
- Netlify / Vercel — drag and drop the folder
- Apache / Nginx — copy files to your web root
- Any CDN — works with S3, Cloudflare Pages, etc.
No server-side configuration needed.
config.json reference
Generated automatically by generate_config.py. You can also edit it by hand.
{
"title": "My Comic",
"subtitle": "Optional subtitle shown on the landing page",
"chapters": [
{
"name": "Chapter 1 – The Beginning",
"pages": [
"chapters/chapter-01/001.jpg",
"chapters/chapter-01/002.jpg"
]
}
]
}
| Field | Required | Description |
|---|---|---|
title |
yes | Comic title, shown on landing and in the browser tab |
subtitle |
no | Short subtitle shown under the title on the landing page |
chapters |
yes | Array of chapter objects |
chapters[].name |
yes | Display name for the chapter |
chapters[].pages |
yes | Ordered array of image paths relative to the root |
parts.csv reference
# This is a comment line — ignored
chapter-01,Prologue,1
chapter-01,The Cave,4
chapter-02,Arrival,1
| Column | Description |
|---|---|
| 1 | Folder name (must match a folder inside chapters/) |
| 2 | Display name for the part |
| 3 | Starting page number, local to the chapter (1-based) |
Customisation
All visual variables are CSS custom properties at the top of index.html:
:root {
--bg: #0f0f0f; /* page background */
--surface: #1a1a1a; /* nav, cards, sidebar */
--surface2: #242424; /* hover states, inputs */
--border: #333; /* borders */
--accent: #e8c84a; /* highlight colour */
--accent2: #b8973a; /* secondary highlight */
--text: #f0ece0; /* main text */
--muted: #888; /* secondary text */
}
Change --accent and --accent2 to match your comic's palette.
Browser support
Any modern browser (Chrome, Firefox, Safari, Edge). No polyfills needed. Does not work when opened directly as a file:// URL — use a local server (see step 5).
Contributing
Pull requests welcome. Please keep the project dependency-free and single-file for index.html.