# Feature library ("What's here") Airbnb-amenities pattern: a **curated library** of features, each with a fixed icon + label + slug. Operators pick **up to 15** for their attraction. Free-text is not allowed — it keeps icons consistent, data filterable, and listings honest. ## Display - **Detail page:** a tile grid in the weather-card style (icon above, label below). First **10** show; the rest behind a "+ N more" expander tile. - **Cards/search:** only the 2–3 most decision-critical (buggy, indoor, free) appear on cards; the full set lives on the detail page. - **Operator picker:** grouped by category, tap to toggle, live "12 of 15 chosen" counter; at 15 the picker refuses until one is removed (choosing is prioritising). See `edit.html` for the working design. ## The library (v1 · 44 features) ### Facilities | Icon | Label | Slug | Filter? | |---|---|---|---| | ☕ | Café | `cafe` | | | 🧺 | Picnic area | `picnic` | | | 🚻 | Toilets | `toilets` | | | 🚼 | Baby changing | `baby-changing` | ✅ core | | 🅿️ | Parking | `parking` | ✅ core | | 🎁 | Gift shop | `gift-shop` | | | 🍦 | Snack kiosk | `snacks` | | | 🔄 | Free re-entry | `free-reentry` | | ### Access | Icon | Label | Slug | Filter? | |---|---|---|---| | 👶 | Buggy-friendly | `buggy` | ✅ core | | ♿ | Wheelchair accessible | `wheelchair` | v1.5 | | 🛗 | Step-free | `step-free` | v1.5 | | 🦻 | Hearing loop | `hearing-loop` | | | 🐕‍🦺 | Assistance dogs | `assistance-dogs` | | | 🚌 | Near public transport | `public-transport` | | ### Family | Icon | Label | Slug | Filter? | |---|---|---|---| | 🎉 | Party room | `party-room` | ✅ parties | | 🧸 | Toddler area | `toddler-area` | | | 🍼 | Feeding room | `feeding-room` | | | 👶 | Pram storage | `pram-storage` | | | 🪑 | High chairs | `high-chairs` | | | 🚸 | Fenced & secure | `fenced` | | ### Activities | Icon | Label | Slug | Filter? | |---|---|---|---| | 🛝 | Soft play | `soft-play` | | | 🏠 | Indoor play barn | `indoor-play` | | | 💦 | Splash zone | `splash-zone` | | | 🐐 | Animal feeding | `animal-feeding` | | | 🚜 | Tractor rides | `tractor-rides` | | | 🥾 | Walking trails | `trails` | | | 🎨 | Craft sessions | `crafts` | | | ⛏️ | Den building | `den-building` | | ### Practical | Icon | Label | Slug | Filter? | |---|---|---|---| | 📶 | Free wifi | `wifi` | | | 🐶 | Dogs welcome | `dogs` | v1.5 | | 💳 | Card / contactless | `contactless` | | | ☔ | Wet-weather cover | `wet-weather` | | | 🌳 | Shade | `shade` | | | 🔌 | EV charging | `ev-charging` | | ### SEND / additional needs | Icon | Label | Slug | Filter? | |---|---|---|---| | 🤫 | Quiet room | `quiet-room` | v2 ⭐ | | 🌈 | Sensory sessions | `sensory` | v2 ⭐ | | 🚻 | Changing Places | `changing-places` | v2 ⭐ | | 🎧 | Quiet hours | `quiet-hours` | v2 ⭐ | | 📋 | Visual guide | `visual-guide` | | ## Rules - **Cap: 15 per attraction**; detail page shows 10 + "+ N more" expander. - Library is **versioned and curated** — operators request additions, they don't self-serve (prevents icon drift + junk). - "Filter?" column: ✅ core = one of the 10 primary filters today (backed by the existing boolean columns); v1.5/v2 = promoted into "More filters" as data coverage grows. **SEND features are the planned differentiator** (Maya persona) — surface them prominently once coverage justifies it. ## Data model - `attraction.features` = array of slugs (≤15), validated against the library. - The 6 existing boolean columns (indoor/outdoor/buggy/baby-changing/parking/ free) stay as first-class filter columns; their matching library slugs are auto-synced both ways so filters and tiles never disagree. - **Import contract:** `features` column = pipe-separated slugs, e.g. `cafe|picnic|toilets|party-room|animal-feeding`. Unknown slugs are flagged for curation, not silently dropped. See `docs/product/import-contract.md`.