Gallery Layout

The gallery layout displays list action data as a grid of cards with images. It's ideal for visual content like product catalogs, media libraries, or any data where images help users quickly identify records.

When to use gallery

Use gallery layout when:

  • Records have associated images (product photos, thumbnails, avatars)
  • Visual recognition is faster than reading text
  • You're building a catalog or browsing interface
  • Users need to scan many items quickly

Configuration

Configure the gallery layout in your tool's JSON configuration file:

tools/list-products.json
{
  "id": "list-products",
  "action_name": "listProducts",
  "display_layout": {
    "config": {
      "type": "GALLERY",
      "galleryConfig": {
        "title": {
          "template": "{{$.name}}"
        },
        "description": {
          "template": "{{$.sku}}"
        },
        "image": {
          "fileField": {
            "path": "$.thumbnail"
          },
          "alt": {
            "template": "{{$.name}}"
          }
        }
      }
    }
  }
}

Gallery config options

FieldTypeRequiredDescription
titleStringTemplateYesPrimary text shown on each card
descriptionStringTemplateNoSecondary text shown below the title
imageImageYesImage configuration for each card

Image configuration

The image object configures which field contains the image and how it's displayed:

FieldTypeRequiredDescription
fileFieldJsonPathYesPath to the file field containing the image
altStringTemplateNoAlt text for accessibility

The fileField must reference a File type field in your model that contains image data.

Example: Product catalog

Here's a complete example showing a product catalog with gallery layout.

Schema

schema.keel
model Product {
  fields {
    sku Text @unique
    name Text
    description Text?
    price Decimal
    thumbnail File?
    category Category
  }
 
  actions {
    list listProducts(category.id?)
  }
}
 
model Category {
  fields {
    name Text
    products Product[]
  }
}

Tool configuration

tools/list-products.json
{
  "id": "list-products",
  "action_name": "listProducts",
  "name": "Product Catalog",
  "display_layout": {
    "config": {
      "type": "GALLERY",
      "galleryConfig": {
        "title": {
          "template": "{{$.name}}"
        },
        "description": {
          "template": "{{$.sku}} - ${{$.price}}"
        },
        "image": {
          "fileField": {
            "path": "$.thumbnail"
          },
          "alt": {
            "template": "Photo of {{$.name}}"
          }
        }
      }
    }
  },
  "get_entry_action": {
    "tool_id": "get-product"
  },
  "create_entry_action": {
    "tool_id": "create-product",
    "title": "Add Product"
  }
}

This configuration:

  • Displays each product as a card with its thumbnail image
  • Shows the product name as the card title
  • Shows the SKU and price as the description
  • Links to the product detail view when clicking a card
  • Adds a button to create new products

String templates

The title, description, and alt fields support string templates. Use {{$.fieldPath}} syntax to insert field values:

{
  "title": {
    "template": "{{$.name}}"
  },
  "description": {
    "template": "{{$.category.name}} - {{$.sku}}"
  }
}

Templates can reference nested fields using dot notation. The template is resolved at runtime using each record's data.

Combining with other features

Gallery layout works with other tool configuration features:

Filtering

Add filter configuration to let users search the gallery:

{
  "display_layout": {
    "config": {
      "type": "GALLERY",
      "galleryConfig": { ... }
    }
  },
  "filter_config": {
    "quick_search_field": "$.where.name.contains"
  }
}

Entry actions

Configure what happens when users click a card or want to create new records:

{
  "get_entry_action": {
    "tool_id": "get-product"
  },
  "create_entry_action": {
    "tool_id": "create-product",
    "title": "Add Product",
    "as_dialog": true
  }
}

Pagination

Control how many cards appear per page:

{
  "pagination": {
    "page_size": {
      "default_value": 24
    }
  }
}