Feature: Reusable Collection Overrides Editor with Shopify Collection Picker
Status: Planned
Context
UI component settings (collection page image, swatches, subcollections) are currently global — they apply to all collections. Merchants need per-collection control (e.g., hide the collection image on "Men's Innerwear" but show it on "Socks"). Danyil's PR #3019 added a basic inline collection overrides pattern for swatches with manual handle entry.
This plan extends that into a proper reusable modal-based editor with a Shopify collection picker, usable by any settings section.
Interim workaround: Collection overrides can be pushed manually via the settings API. The collectionOverrides array on any UI component follows the same resolveCollectionSetting() pattern from storefront_search/src/vue/collection-overrides.ts.
Example — disable collection image for specific collections via API:
# Fetch current settings
curl -s -H "Authorization: Bearer {key}" \
"https://admin.ecom.marqo.ai/api/v1/storefront/shops/{domain}/settings" > settings.json
# Edit collection_page_config.value.collectionOverrides in settings.json:
# {
# "collectionOverrides": [
# { "collections": ["mens-innerwear"], "showImage": false },
# { "collections": ["socks", "hats"], "showDescription": false }
# ]
# }
# Push updated settings
curl -s -X POST -H "Authorization: Bearer {key}" -H "Content-Type: application/json" \
-d @settings.json "https://admin.ecom.marqo.ai/api/v1/storefront/shops/{domain}/settings"
The storefront widget reads these via resolveCollectionSetting() — first matching rule wins, unmatched collections use global defaults.
Admin UI Design
UX: Modal with Shopify collection picker
Each settings section that supports overrides has a "Collection Overrides (N)" button that opens a modal:
List page:
┌─ Collection Overrides ─────────────┐
│ │
│ ┌ Men's Innerwear ──────── [✎] ┐ │
│ │ showImage: false │ │
│ └───────────────────────────────┘ │
│ ┌ Socks ────────────────── [✎] ┐ │
│ │ showDescription: false │ │
│ └───────────────────────────────┘ │
│ │
│ [+ Add Override] [Done] │
└────────────────────────────────────┘
Add/Edit page:
┌─ Add Collection Override ──────────┐
│ │
│ Collection: │
│ ┌──────────────────────────────┐ │
│ │ 🔍 Search collections... │ │
│ ├──────────────────────────────┤ │
│ │ Men's Shirts & Polos │ │
│ │ Men's Innerwear │ │
│ │ Socks │ │
│ └──────────────────────────────┘ │
│ │
│ Show Image: [toggle] │
│ Show Description: [toggle] │
│ │
│ [Cancel] [Save] │
└────────────────────────────────────┘
Reusable Component: CollectionOverrideEditor
A headless modal component that any settings section can embed:
interface CollectionOverrideEditorProps<T extends Record<string, unknown>> {
overrides: Array<{ id: string; collections: string[] } & T>;
onUpdate: (overrides: Array<{ id: string; collections: string[] } & T>) => void;
renderFields: (override: T, onChange: (updates: Partial<T>) => void) => React.ReactNode;
newOverrideDefaults: T;
label?: string;
}
Parent component provides override-specific fields as a render prop. The shared component handles collection picking, CRUD, and modal navigation.
Implementation
Backend
New endpoint: GET /api/v1/storefront/shops/{domain}/collections
- Authenticates via API key
- Queries Shopify Admin API with existing
LIST_COLLECTIONSGraphQL query - Returns
{ collections: [{ handle, title }] }
GraphQL query already exists: admin_server/graphql/queries/collection_queries.py:LIST_COLLECTIONS
Admin UI
| File | Change |
|---|---|
admin_server/routes/storefront_routes.py | New collections list endpoint |
storefront_admin/app/lib/api-client.ts | Add listCollections() method |
storefront_admin/app/components/ui/collection-override-editor.tsx | Reusable modal editor (NEW) |
storefront_admin/app/components/settings/collection-page-section.tsx | First consumer |
storefront_admin/app/lib/types.ts | Add CollectionPageOverrideRule |
storefront_admin/app/lib/settings-converter.ts | Collection page overrides conversion |
Storefront Widget
Uses existing resolveCollectionSetting() from collection-overrides.ts (Danyil's PR #3019). Each render function that reads component settings calls resolveCollectionSetting() to check for per-collection overrides.
Future consumers
Once the shared editor is built, migrate:
- Swatch overrides (currently inline in
product-display-section.tsx) - Subcollection settings per parent collection
- Any future component that needs per-collection behavior