Panels is a simple Rust based web server for delivering the Sunday Funnies anytime, anywhere. It provides over 400 comics; select your favorites, and get random strips immediately. Panels also has a recommendation engine to help you discover new comics based on your preferences.
Note
Panels is a personal project and is not affiliated with any comic publishers. All comics are sourced from publicly available data and are intended for personal use and enjoyment. All comics are property of their respective creators and publishers.
- Rust stable toolchain
cargo
cargo runServer starts on http://localhost:3000 by default.
curl http://localhost:3000/api/healthExpected response:
{"status":"ok"}Panels uses CLI flags and environment variables:
| Flag | Env | Default | Description |
|---|---|---|---|
--port |
PANELS_PORT |
3000 |
HTTP server port |
--data-dir |
PANELS_DATA_DIR |
data |
Path containing comics.json, tags.json, and badges/ |
--strip-cache-max |
PANELS_STRIP_CACHE_MAX |
500 |
Max strip cache entries |
--strip-cache-ttl |
PANELS_STRIP_CACHE_TTL |
1800 |
Strip cache TTL in seconds |
Example:
PANELS_PORT=4000 PANELS_DATA_DIR=./data cargo runBasic liveness endpoint.
Returns comics with tag metadata.
Query params:
search(optional): matchestitleorendpointtag(optional): exact tag filter (case-insensitive)
Example:
curl "http://localhost:3000/api/comics?search=garfield&tag=humor"Returns scored recommendations from selected comic endpoints.
Query params:
selected(required for non-empty results): comma-separated endpointslimit(optional): max results, default10
Example:
curl "http://localhost:3000/api/recommendations?selected=garfield,peanuts&limit=8"Returns one strip as JSON.
{date} supports:
YYYY-MM-DDlatestrandom
Examples:
curl "http://localhost:3000/api/comics/garfield/latest"
curl "http://localhost:3000/api/comics/garfield/random"
curl "http://localhost:3000/api/comics/garfield/2025-02-14"Proxies the strip image bytes and content type.
Caching behavior:
date=random:Cache-Control: no-store- any non-random request:
Cache-Control: public, max-age=86400, s-maxage=604800
Example:
curl -I "http://localhost:3000/api/comics/garfield/random/image"Run the usual checks:
cargo fmt
cargo clippy --all-targets -- -D warnings
cargo testCI (.github/workflows/ci.yml) runs:
cargo check --all-targetscargo test --all-targets
Tests workflow (.github/workflows/tests.yml) runs:
cargo test --all-targets
Contributions are welcome. Feel free to open an issue or submit a pull request. Let me know if a comic you love is missing or if you have ideas for new features!
When reporting an issue, please include:
- A clear description of the problem.
- Steps to reproduce the issue.
- Expected vs actual behavior.
- Any relevant logs or error messages.
- Fork the repo and create a feature branch.
- Make focused changes with clear commit messages.
- Run the local quality checks.
- Open the PR with context and testing notes.
cargo fmt
cargo clippy --all-targets -- -D warnings
cargo test- Scope is limited to one feature or fix.
- API behavior changes are documented in
README.md. - New behavior is covered by tests in
tests/or module tests. - Clippy and tests pass locally.
MIT. See LICENSE.