Files
ComicOPDS/docs/smartlists.md
T

5.8 KiB

🧠 Smart Lists

Access through /search

Smart Lists allow you to create saved search filters that appear as "virtual folders" in your OPDS feed.

Creating Smart Lists

Simple Filters

Add filters using the web interface:

  • series=Batman
  • year=2024
  • publisher=DC Comics

Advanced Filters

Create complex queries with multiple conditions:

series contains 'Scrooge McDuck'
volume equals 1953
number >= 285
number <= 297

JSON Configuration Example

For advanced users, Smart Lists are stored in /data/smartlist.json:

 {
    "name": "Maul + Vader (1-5)",
    "slug": "maul-vader-1-5",
    "groups": [
      {
        "rules": [
          {
            "not": false,
            "field": "series",
            "op": "contains",
            "value": "Maul"
          },
          {
            "not": false,
            "field": "number",
            "op": "<=",
            "value": "5"
          },
          {
            "not": false,
            "field": "format",
            "op": "equals",
            "value": "Limited Series"
          }
        ]
      },
      {
        "rules": [
          {
            "not": false,
            "field": "series",
            "op": "contains",
            "value": "Vader"
          },
          {
            "not": false,
            "field": "number",
            "op": "<=",
            "value": "5"
          },
          {
            "not": false,
            "field": "format",
            "op": "equals",
            "value": "Main Series"
          }
        ]
      }
    ],
    "sort": "series_number",
    "limit": 0,
    "distinct_by": "",
    "distinct_mode": "oldest"
  }

Maul + Vader (1-5):

  • Group 1:
    • series contains "Maul"
    • number <= 5
    • format = "Limited Series"
  • Group 2:
    • series contains "Vader"
    • number <= 5
    • format = "Main Series"
  • Sort:
    • series_number
    • limit: 0
    • Distinct: no

Supported Operations

  • equals, contains, startswith, endswith
  • =, !=, >=, <=, >, < (for numeric fields)
  • not modifier for any operation

"Distinct by series and volume (latest)"

When that option is enabled, a smart list will return at most one comic per series and volume. For each series, it picks the latest issue, using this tie-break:

  1. Newer year (cast to integer)
  2. If year ties: higher number (cast to integer)
  3. If number ties: newer file mtime (last modified time)

So you get a de-duplicated "what's the newest issue for each series?" view.

Use Cases:

  • A clean "latest per series" shelf (e.g., to see what's new without 300 issues of Batman).
  • Weekly pulls / backlog triage: combine with filters like publisher=Image or year >= 2020.

Important details / edge cases

  • Numeric casting: blank or non-numeric year/number are treated as NULL → effectively 0, so those won't beat entries with proper numbers (eg. 16A).

Example use

  • "Latest Image series":
    • Rules: publisher = "Image Comics", year >= 2018
    • Distinct by series: on

→ One newest issue per Image series since 2018.

Dynamic Smart Lists (Auto-Grouping)

Dynamic Smart Lists automatically create sub-folders based on distinct values in a metadata field. Instead of manually creating one smart list per writer, publisher, or series, you can create a single dynamic smart list that generates them automatically.

How It Works

When you set the Group By field to a metadata field (e.g., writer, publisher, format):

  1. The smart list becomes a navigation folder showing all distinct values for that field
  2. Each value appears as a sub-folder with a count (e.g., "Brian K. Vaughan (47)")
  3. Clicking a sub-folder shows all comics matching both:
    • Your smart list filters (if any)
    • That specific field value

Example: Browse by Writer

Create a smart list named "All Writers":

  • Group By: writer
  • Rules: (optional) Add filters to narrow down, e.g., year >= 2020
  • Sort: series_number or issued_desc

Result: You get a folder structure like:

All Writers/
  ├── Brian K. Vaughan (47)
  ├── Ed Brubaker (92)
  ├── Grant Morrison (156)
  ├── Jeff Lemire (73)
  └── ...

Example: Browse Trade Paperbacks by Series

Create "TPB by Series":

  • Group By: series
  • Rules: format equals "TPB"
  • Sort: series_number

Result: Only TPBs, organized by series name.

Supported Group By Fields

  • writer - Group by writer/author
  • publisher - Group by publisher
  • series - Group by series name
  • format - Group by format (TPB, Hardcover, etc.)
  • year - Group by publication year
  • tags - Group by tags
  • characters - Group by character appearances
  • teams - Group by team appearances
  • genre - Group by genre

Combining with Regular Filters

Dynamic smart lists work with all regular smart list features:

  • Filters: Pre-filter comics before grouping (e.g., only 2020+ or only Image Comics)
  • Distinct: De-duplicate by series+volume
  • Limit: Cap results per sub-folder
  • Sort: Control ordering within each group

JSON Configuration Example

{
  "name": "Recent Comics by Writer",
  "slug": "recent-by-writer",
  "group_by": "writer",
  "groups": [
    {
      "rules": [
        {
          "not": false,
          "field": "year",
          "op": ">=",
          "value": "2020"
        }
      ]
    }
  ],
  "sort": "issued_desc",
  "limit": 0,
  "distinct_by": "",
  "distinct_mode": "latest"
}

This creates a dynamic list showing all writers who published comics since 2020, with each writer's comics sorted by newest first.

Screenshot