MetronInfo V1.1
A quick follow-up to the v1.0 announcement from two years ago: MetronInfo v1.1 is out, adding two new optional elements that came out of feedback since the initial release.
A quick follow-up to the v1.0 announcement from two years ago: MetronInfo v1.1 is out, adding two new optional elements that came out of feedback since the initial release.
During February the Metron Project added the following to its database:
Thanks to everyone that contributed!
Over the last 6 months, API usage has seen a significant increase — which is great! However, we are now at a point where our current server capacity is being strained.
Jonas Stendahl and I have landed some optimizations in the site's code, but they only go so far in relieving the pressure.
That leaves us with two options:
Option #1 is clearly preferable, but we currently don't receive enough donations to cover the extra cost. That means we will likely need to reduce the daily rate-limit in the very near future, and we'll post an announcement here when that happens.
If you have other ideas or suggestions, please reach out!
Several changes were made to improve API and database query performance.
select_related and prefetch_related.order_by() to SeriesViewSet and the publisher series-list action to resolve a UnorderedObjectListWarning that could surface during pagination.ETag and Last-Modified headers. Clients can send If-None-Match or If-Modified-Since headers to avoid re-downloading unchanged data, saving bandwidth. (jyggen)read_dates data, giving API consumers access to reading history information directly from the list view.The following changes made to Mokkari, the Python wrapper for the Metron API, over the past month:
if_modified_since parameter to detail endpointsAll the detail methods (arc, character, creator, imprint, issue, publisher, series, team, universe, reading_list, and collection) now accept an optional if_modified_since datetime parameter. When provided, the request includes an If-Modified-Since HTTP header (formatted per RFC 7231) and returns None on a 304 Not Modified response — useful for efficiently detecting whether a resource has changed since you last fetched it. Naive datetimes are treated as UTC, and non-UTC datetimes are automatically converted before the header is sent.
CollectionList schemaThe collection schemas have been updated to match the latest Metron API:
ReadDate model was added with id, read_date, and created_on fields.read_dates and read_count fields were added to CollectionList and CollectionRead.date_read field type in CollectionRead was changed from date to datetime to align with the API's date-time format.The rate-limiting implementation was updated for the breaking changes in pyrate-limiter 4.0:
BucketFullException and LimiterDelayException imports.Limiter construction._check_rate_limit() to use the boolean return value of try_acquire(blocking=False) instead of catching exceptions.Here's a roundup of changes shipped to Desaad over the past month.
The import_reading_status management command was upgraded: it now imports reading history dates from Metron, not just reading status. A new
ReadDate model was added to store the actual date an issue was read, and the UserStatsView was updated to use these dates for reading activity stats. Previously, stats reflected the import timestamp rather than when issues were actually read.
The comic importer was tightened up to require an external ID when creating characters, teams, universes, arcs, locations, genres, and creators. Previously, the importer would fall back to name-based lookups and create records without a verified external ID, leading to potential unverified duplicates. This change simplifies the importer significantly and ensures all entities can be reliably matched against a metadata source.
The comic reader's Prev Issue, Next Issue, and Close buttons now require a double-tap to activate. On the first tap, the button turns yellow and prompts "Tap again"; a second tap within 2 seconds proceeds with navigation. Otherwise, the button resets. This prevents accidental navigation away from your current reading position.
DB_* variables were also documented in the README.A huge thank you to everyone who has contributed to our Open Collective! Your support makes a real difference in keeping the Metron Project running and growing.
Funds from Open Collective go directly toward:
All expenses are transparent and publicly viewable on our Open Collective page, so you can see exactly where every dollar goes.
If you'd like to help keep the lights on and support continued development, contributions of any size are appreciated and help ensure Metron remains a free resource for the comic book community.
Anyway, that's everything for this month! Take care.
During January the Metron Project added the following to its database:
Thanks to everyone that contributed!
Scrobble API Support
A new /scrobble endpoint allows users to quickly mark issues as read via the API with optional rating and timestamp. This enables integration with third-party reading apps and automated tracking workflows. The date_read field was migrated from a date to datetime for more precise tracking.
Reading History
Users can now view their reading history in a timeline layout with daily grouping. Recent reading activity also appears on user profile pages.
Multiple Read Dates
Collection items now support tracking multiple read dates, since comic issues are often re-read over time. The UI includes HTMX-powered controls for adding and removing read dates directly from the detail page.
Community View
User profiles now use username-based URLs (/accounts/username/) instead of numeric IDs. A new user list view with search functionality was added, making it easier to find and view other community members.
HTMX Migration
Significant portions of the frontend JavaScript have been replaced with HTMX:
Auto-Dismissing Notifications
Non-error notifications now automatically disappear after 5 seconds. Error messages remain visible until manually dismissed.
Issue Autocomplete Search
The issue autocomplete now supports more flexible searching:
Email Compatibility for Account Activation
Updated how Metron sends account activation emails to ensure they display correctly across all major email clients.
The changes include:
<head> sectionThese updates should ensure new users have a smooth onboarding experience, regardless of whether they use Gmail, Outlook, Apple Mail, or any other email client.
The following changes were made to Desaad.
Issue scrobbling was added this month, and more information on it can be found in this blog post.
The application has migrated from SQLite to PostgreSQL. This followed an initial attempt to improve SQLite concurrency with WAL mode and retry logic, but PostgreSQL proved to be a better fit for handling concurrent operations during comic imports while the web server is running.
The comic reader received several updates:
After testing both approaches, the reader reverted to using base64 image data instead of image URLs, as this provided a better reading experience.
The app now uses Django 6.0's Tasks framework with django-tasks[rq] for several operations:
A new import_reading_status management command allows users to sync their reading history from their Metron collection. This imports completion status and ratings for issues that match by Metron ID. Currently, it only imports the read status, but in the near future it will add the dates the issues were read on also.
Replaced JavaScript with HTMX in several places:
A huge thank you to everyone who has contributed to our Open Collective! Your support makes a real difference in keeping the Metron Project running and growing.
Funds from Open Collective go directly toward:
All expenses are transparent and publicly viewable on our Open Collective page, so you can see exactly where every dollar goes.
If you'd like to help keep the lights on and support continued development, contributions of any size are appreciated and help ensure Metron remains a free resource for the comic book community.
Anyway, that's everything for this month! Take care.
We've added a new scrobble endpoint to Metron that makes tracking your comic reading progress more convenient.
Scrobbling is a quick way to mark an issue as read via the API. The term comes from music services like Last.fm, where it refers to automatically tracking what you're listening to. For Metron, it means you can instantly log that you've finished reading a comic issue without navigating through the web interface.
The new /api/collection/scrobble/ endpoint accepts a simple POST request with an issue ID. When you scrobble an issue, Metron will:
If the issue doesn't exist in your collection yet, scrobbling creates a new collection item with reasonable defaults (digital format, quantity of 1). If it's already in your collection, the endpoint just updates the read status and timestamp.
The web interface works fine for managing your collection, but marking issues as read can feel cumbersome when you're actively reading. You have to navigate to the right page, find the issue, click edit, check the box, and save. That's several steps just to record something simple.
Scrobbling reduces this to a single API call. This opens up possibilities for:
To support more precise tracking, we migrated the date_read field from DateField to DateTimeField. This means you can now track exactly when you finished reading an issue, not just which day. All existing data was preserved during the migration.
Along with scrobbling, we added a reading history view that displays your recently-read comics in a timeline format. You can see:
The full reading history is available at /collection/history/, and your user profile now shows your 10 most recent reads.
To scrobble an issue, make a POST request to /api/collection/scrobble/:
{
"issue_id": 12345,
"date_read": "2026-01-08T14:30:00Z",
"rating": 4
}
The date_read and rating fields are optional. If you omit date_read, it defaults to the current timestamp.
Authentication is required (Basic Auth or session), and the endpoint respects collection privacy—you can only scrobble to your own collection.
The scrobble endpoint provides a foundation for better reading tracking. We'd like to see what tools the community builds with it. If you create a browser extension, mobile app, or other integration, let us know.
For complete API documentation, see the User Collection Documentation.
During December the Metron Project added the following to its database:
Thanks to everyone that contributed!
This month I added a User Collections system that lets you track your personal comic book collection. You can manage your collection by adding or removing issues, mark things as read, and track comic condition using the CGC grading scale (0.5 to 10.0). The grading system supports professional grading companies like CGC, CBCS, and PGX, as well as user-assessed grades for raw comics.
There's also a star rating system (1-5 stars) for rating issues in your collection, format tracking for print and digital copies, and bulk operations to add entire series runs at once. If you're trying to complete runs, there's a missing issues tracker that shows you which issues you need and displays completion percentages for each series.
The feature includes collection statistics with visual charts, advanced filtering options to search by series, publisher, format, read status, grade, and more. There are also read-only API endpoints for accessing your collection data and statistics, along with documentation to help you get started.
Reading lists got some updates this month. You can now tag issues as Prologue, Core Issue, Tie-In, or Epilogue, with inline editing and visual badges to make it easier to see what's what. I also added a 5-star rating system for public reading lists, so you can see average ratings and filter lists by minimum rating.
There's also story arc integration that lets you add all issues from a story arc to a reading list in one go, which should save some time. I created a "reading list editor" group for managing Metron's curated lists - this allows trusted users to help curate without needing full staff privileges. If you're interested in being part of this group, just let me know.
The reading list API now supports browsing and retrieving lists with paginated results (50 items per page) and filtering options.
I spent some time improving the search functionality across the site. Series lists now support multi-word search with filters for type, publisher, imprint, year range, status, and volume. Issue lists have quick search with advanced filters for series info, dates, and IDs. Reading lists can be searched by name, creator, attribution source, and privacy status. User collections have quick search across series names and notes with multi-field filtering.
All the search interfaces now have collapsible advanced filter sections, preserve your filter state, show active filter indicators, and have better empty states. I tried to keep the UI patterns consistent across all of them.
Fixed a bug where WeekList, NextWeekList, and FutureList views were using class-level date calculations evaluated at import time. This meant the views would always show the same week (from when the server started) instead of updating dynamically. I moved the date calculations to per-request methods and switched to precise date range queries to fix this.
Fixed a few mobile-specific issues this month: filter buttons now work properly on mobile devices, improved the home page responsiveness, fixed layout issues in home.html, and cleaned up button layouts across collection and reading list views.
Added a Reading List & Collections section to the home page, made the first information card full width, and improved the overall layout for better visual hierarchy. I also spent time optimizing database queries - reading list detail views went from around 20 queries down to 4-6 by using better prefetching and annotation strategies. Collection detail views now show cover images and descriptions with lazy loading.
Improved permission checks across reading list operations.
Upgraded to Django 5.2.9 and added documentation for User Collections and Reading Lists, including user guides, technical documentation for developers, and API documentation. I also refactored and simplified some views with better inheritance patterns.
Now that User Collections is up and running and Reading Lists have been improved, the plan is to refine these features based on user feedback and explore additional integration opportunities.
Desaad is a self-hosted, web-based comic book library manager and reader built with Django that I've been working on over the past week or so. I created it to test and plan features for Metron that might be useful for other comic servers.
Desaad imports CBZ, CBR, and PDF comic archives and automatically pulls metadata from MetronInfo.xml files - things like series information, publishers, creators, characters, teams, universes, and story arcs. I'm not planning to add ComicInfo.xml support, since there are a lot of comic servers that already do.
It uses Darkseid for handling comic archives and extracting metadata.
The web reader uses HTMX and automatically saves your reading position and progress, so you can pick up where you left off.
You can import reading lists from Metron using the API. The feature automatically tracks which issues are in your library and shows you which ones you're missing.
You can access your comic library from mobile devices and e-readers using OPDS-compatible apps like Chunky Comic Reader (iOS), Panels (iOS), or Challenger Comics Viewer (Android).
I tried testing it with the Challenger app, but their OPDS support doesn't seem to work and is still marked as Beta. If anyone wants to test with Chunky or Panels, I'd appreciate hearing how it goes.
There's an import management command that you can run manually or set up to watch a directory for new comics.
I haven't optimized it much yet - the most expensive part is cover extraction, which I'll probably move to a background task at some point. I deployed it on a spare GMKtec NucBox G3 I had, and it took about 3 hours to import around 65,000 comics. Once I move cover extraction to a background task, I should be able to get that down to 1-2 hours.
Desaad is built on Django 6.0 with SQLite for simplicity (though I'll probably switch to PostgreSQL at some point since SQLite has some performance limitations and missing features). The frontend uses the Bulma CSS framework with HTMX, and comic processing is handled by the Darkseid library. It's container-ready with Podman support and systemd integration.
It requires Python 3.13+ and uses the uv package manager for dependency management.
A few things to keep in mind about Desaad:
Single Metadata Source: It assumes all your comics use metadata from a single source (Metron, Comic Vine, etc.). Mixed metadata sources aren't supported.
MetronInfo.xml Format: Only supports the MetronInfo.xml metadata specification. Your comics need metadata written by software that implements this spec.
Under Active Development: The project is still under construction and not ready for production use. Features and APIs will change.
Desaad might be a good fit if you're a developer or tester who prefers browser-based reading and wants to see possible new features like scrobbling. It works best if your collection uses metadata from a single source (Metron, Comic Vine, or Grand Comics Database). If your collection has mixed metadata from multiple sources, Desaad probably isn't the right tool for you.
Setting up Desaad is pretty straightforward:
# Clone the repository
git clone https://codeberg.org/bpepple/desaad.git
cd desaad
# Configure environment
cp .env.example .env
# Edit .env with your settings
# Install dependencies and setup
uv sync
uv run python manage.py migrate
uv run python manage.py createsuperuser
uv run python manage.py collectstatic
# Run the development server
uv run python manage.py runserver
For production deployments, there are Podman compose configurations with systemd service integration.
If you're using Fedora Linux, the included Podman configuration should make deployment simple. It should work on other systems running Podman too, but I haven't tested that yet. To get started:
# Build and start
podman-compose up -d
# Create admin user
podman-compose exec web python manage.py createsuperuser
# Import comics
podman-compose exec web python manage.py import_comics
The application will be available at http://localhost:9000.
There's more information in the project's README.md, including how to create systemd service files.
A huge thank you to everyone who has contributed to our Open Collective! Your support makes a real difference in keeping the Metron Project running and growing.
Funds from Open Collective go directly toward:
All expenses are transparent and publicly viewable on our Open Collective page, so you can see exactly where every dollar goes.
If you'd like to help keep the lights on and support continued development, contributions of any size are appreciated and help ensure Metron remains a free resource for the comic book community.
Anyway, that's everything for this month! Take care.
I've spent the last week or so, implementing User Collections, a feature for Metron that lets you catalog, organize, and track your personal comic book collection.
User Collections is a comic book collection management system.
Track every aspect of your collection:
Adding your entire collection is fast and efficient:
Get insights into your collection:
Helps you complete your series runs:
Track your reading journey:
Your collection is completely private:
Navigate to /collection/add/ and search for any issue using the autocomplete feature. Fill in optional details like grade, purchase price, storage location, and click "Add to Collection."
Visit /collection/add-from-series/ to quickly add entire series runs:
The system automatically skips issues already in your collection, making it perfect for cataloging longboxes or digital libraries.
The Missing Issues feature (/collection/missing/) identifies gaps in your series runs:
Find exactly what you're looking for with extensive filtering options:
Built on Django with:
/api/collection/For Completionists: Use Missing Issues to systematically fill gaps in your series runs. Color-coded progress bars show which series you're close to completing.
For Investors: Track purchase prices and grades for valuable books. Monitor total collection value and maintain detailed records for insurance.
For Readers: Mark issues as read, rate them, and track your progress. Filter to find unread comics in your collection.
For Organizers: Use storage locations to keep track of where comics are physically stored. Perfect for managing multiple longboxes or storage units.
A new release of Mokkari will be made this week with support for the user collections API endpoints.
More Import Options: When I get some time, I'll look at adding support for importing existing collections. If you track your collection elsewhere I'd be interest what export options you have, so please contact me.
Wish List: A logical addition would be to have the option for make a wish list of issues to purchase.
Pull List: Another closely related feature that could be useful.
Comic Value: It would be interesting to be able to provided estimated market values for issues.
During November the Metron Project added the following to its database:
Thanks to everyone that contributed!
So... the last post I made introducing Reading List, unfortunately caused a bit of drama, since I forgot to attribute that the 13 initial reading lists were created from cbl files from the CBL-ReadingLists group. I'm sorry for this oversight and it wasn't my intention to give the impression they were created by me. I've since made a note on those reading lists attributing them to this group, and removed the import CLB functionality from the site.
Due to the aforementioned drama, I've had to call a bit of an audible in regard to the maintaining of the reading lists owned by the Metron user. I'm planning to work on adding support for non-admin users to edit these lists over the Holiday break and if you have an interest in helping to maintain them, please contact me.
One side-effect of my mistake is that it spurred on one of our community members to write a tool to retrieve the data directly from the reading lists source and check them against the site, and then produce a json file or if issues are missing generate a report that can be acted upon. Currently, I've got a management command to import these json files, but maybe I'll look at adding POST support to the API in the future.
Down the road, I'll look at adding arc-based bulk additions, other import options, and maybe an associated reading list fields.
I've added the option to add a series to a reading list, which should be easier than just adding individual issues.
I've spent the last week or so working on the Reading List API, and it's finally been pushed to production. There is fairly detailed API documentation on the wiki, and there is also the Swagger API Documents.
I was originally planning to write a simple tool to generate reading lists from the API, but have held off due to:
A new version of Mokkari has been released that adds support for the new Reading List API, and also reworked the rate limiting code so that it produces more feedback to the user. If you have written an application that uses Mokkari, you'll want to modify your API calls to Metron to sleep when receiving RateLimitError. For example:
>>> import time
>>> from mokkari.exceptions import RateLimitError
>>> session = Session("username", "password")
>>> def fetch_with_rate_limit_handling(issue_id):
... while True:
... try:
... return session.issue(issue_id)
... except RateLimitError as e:
... if "per minute" in str(e):
... # Minute limit - automatically wait and retry
... print(f"{e}")
... print(f"Waiting {format_time(e.retry_after)}...")
... time.sleep(e.retry_after)
... continue
... elif "per day" in str(e):
... # Daily limit - ask user whether to wait or quit
... response = input(f"Wait {format_time(e.retry_after)}? (y/n): ")
... if response.lower() == 'y':
... time.sleep(e.retry_after)
... continue
... else:
... raise
... else:
... raise
>>> issue = fetch_with_rate_limit_handling(1)
A couple of releases of Metron-Tagger were made since my last blog post. The big change was support for writing/reading metadata was added, but implemented differently than other tagging software which have overloaded the PDF metadata. I decided to treat PDFs, like we do with CBZ, by embedding the metadata.
After discussing this with AJ, he has also made a release of Comicbox supporting this method of writing comic metadata to a PDF.
The latest release has also improved the rate limiting, so that when the daily limit is exceeded, the user is asked whether they want to wait the reported number of minutes or quit processing the remaining files.
The site has been dealing with AiBots and scrapers quite a bit lately, and I'm giving serious thought to moving the site DNS over to Cloudflare to take advantage of the bot protection. I'm still working on what the migration plan would entail (name server changes, SSL certs, nginx, etc) and will make a decision once that's finished. If we do make the switch, the site will most likely be down for a while (assuming everything goes as planned), and I will put a notice on the site beforehand.
If you would like to help keep the lights on at the project, we have an account at Open Collective to defray the servers costs and help with increasing future server capacity.
Anyway, I think that's everything for this month! Take care.
During October the Metron Project added the following to its database:
Thanks to everyone that contributed!
I spent most of the month working on improvements to the site.
One of the most substantial additions to Metron is the integration of django-wiki (#403), replacing the previous flatpages system. This enhancement includes:
I've copied over the information from the old flat pages, but work still needs to be done on adding information that is of use to our users.
A fairly comprehensive performance overhaul (#412) dramatically improved page load times across all detail views:
prefetch_related() and select_related() to reduce database queriesLazyLoadMixin to eliminate code duplicationThe project now includes comprehensive edit history tracking using django-simple-history (#392) compared to our fairly hacky prior implementation:
Added a convenient feature to duplicate issue credits (#411), streamlining the workflow when creating issues with similar creative teams.
Extended the variant model to support price information (#391), including price and currency fields.
Migrated the Issue price field to use proper MoneyField (#390) using a multi-step database migrations:
Added functionality to sync characters, teams, and story titles to collections (#372, #373) from the issues being reprinted which should make it a bit easier to add collected editions.
A bunch of refactoring was done to improve code maintainability:
Optimized database querysets across all major views (#408) using select_related() and prefetch_related() to reduce N+1 query problems.
Added comprehensive test coverage:
Significant template improvements focused on consistency and usability:
I've started to think about what I'd like to work on next year, and the big item is to reduce the project reliance on me. In particular, I want to address:
Over the past six years, I've covered the hosting costs and related expenses (domain registration, email services, etc.). Recently, I've started drawing from the project's OpenCollective funds, which currently provide approximately 11 months of runway at our current capacity.
The Goal: Build a sustainable funding base through many small contributions ($2-$5/month) rather than relying on a few large donors. This distributes the financial responsibility and ensures the project's long-term stability.
How You Can Help:
If you have suggestions or feedback, please reach out!
As the project has grown, so has the need to evolve from a single-person decision-making model to a more collaborative governance structure. While centralized decision-making worked well in the early days, enabling quick iterations and changes, but as the project has matured it make sense to add more leadership.
Why Change: Distributing governance responsibilities will:
Next Steps: I'm researching governance models from similar projects, particularly the Grand Comics Database (GCD), to understand what structures work well for community-driven comic databases. My experience with Fedora Project governance provides a foundation, though Metron likely needs a different, more streamlined approach given our scope and community size.
I'll be starting a discussion thread on our GitHub Discussions page soon. If you're interested in helping shape Metron's governance structure, please join the conversation or reach out directly.
If you would like to help keep the lights on at the project, we have an account at Open Collective to defray the servers costs and help with increasing future server capacity.
Anyway, I think that everything for this month! Take care.
During September the Metron Project added the following to its database:
Thanks to everyone that contributed!
A new version of Metron-Tagger was released that added the ability to skip issues that have multiple matches (--skip-multiple) but can't be matched based its cover hash.
Back in May the decision was made to temporarily disable new collections (Trade Paperback, Omnibus, and Hard Covers) until better documentation was written since their handling was a source of confusion for users due to our lack of documentation.
Thankfully, anon_hacker47 (from the Matrix General Chat Room) spent time writing new documentation (located at the bottom of the page under the Collected Editions heading), which should help in most cases. Unfortunately, the comic industry isn't known for it's consistency, so there may be cases which the guidelines don't cover and in those cases it's best to ask either in the Matrix chat room or in the Github Discussions before adding a collected edition.
So, with that the documentation completed I've enabled support for collected editions on the site. In addition, I spent some time implementing a helper function which will add resource data (character & teams) to a collection provided that it has reprints associated with it. There are some caveats, tho:
The Sync button, which is only active if it's a valid series type and doesn't contain any characters or teams, will be used to run this functionality. After it's ran, it will provide notification on what was or wasn't not added to the collection.

If you have suggestions on any improvements to the guidelines, don't hesitate to reach out on Matrix.
If you would like to help keep the lights on at the project, we have an account at Open Collective to defray the servers costs and help with increasing future server capacity.
Anyway, that's all I got for this month. Take care!
During August the Metron Project added the following to its database:
Thanks to everyone that contributed!
Due to some API usage problems support for Metron was removed from ComicTagger. This was primarily done since ComicTagger was designed with Comic Vine's API in mind and Metron's API differs enough that ComicTagger was using 2-14x the number of API requests compared to other clients for the same data.
For example, someone tagging their Captain America series would be using around 4,616 API calls with ComicTagger compared to about 355 API calls if they had used Metron-Tagger. Due to trying to keep up with this additional load, we've had to upgrade our server specs twice this summer and came to the conclusion this wasn't sustainable in the long term.
So, after September 12th you will be unable to useComic Tagger to tag your comics,but if you still wish to use Metron for tagging, you can use Metron-Tagger or Perdoo. If you have any questions or concerns don't hesitate to reach out on Matrix.
If you would like to help keep the lights on at the project, we have an account at Open Collective to defray the servers costs and help with increasing future server capacity.
Anyway, that's all I got for this month. Take care!