Grid URL Parameters
The /embed/grid endpoint renders an EventsGrid component that displays places or events in a filterable grid layout.
Base URL
/embed/grid?slug=<boundary-slug>
Required Parameters
| Parameter | Type | Description |
|---|---|---|
slug OR boundary | string | Location boundary slug (e.g., "austin", "sf", "denver") |
list | string | Alternative: List slug that provides configuration from Lists API |
Note: Either slug/boundary OR list must be provided. When using list, if the list has an associated organization, that organization's boundary will be used automatically.
Content & Data Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
type | string | "places" | Content type: "places" or "events" |
vibes | string | - | Comma-separated vibe filters (e.g., "chill,artsy") |
categories | string | - | Comma-separated category filters |
tags | string | - | Comma-separated tag filters |
editorial_categories | string | - | Editorial category filters (always applied server-side). Aliases: editorial_category, editorialCategory. |
featured | boolean | false | When true, only show featured places/events |
dist / radius | number | - | Radius in meters for proximity (geo-distance) search. Requires latitude + longitude to take effect. |
latitude / lat | number | - | Center latitude for proximity search. Only used when longitude and dist/radius are also set. |
longitude / lng | number | - | Center longitude for proximity search. Only used when latitude and dist/radius are also set. |
search / searchTerm | string | - | Initial search term |
hideNoImageItems | boolean | false | Hide items without images |
tiers | string | - | Filter by membership tier slugs. Comma-separated (e.g., "basic,premium"). Use "non-member" for items with no tier. |
ordering / sort | string | "-score_combined" | Sort order for results (see below) |
Sort Order (ordering / sort)
Controls how places are sorted in the grid.
| Value | Description |
|---|---|
name | Alphabetical by place name (A-Z) |
-score_combined | Default. By relevance/popularity score (highest first) |
-vibe_count | By number of vibes (most vibes first) |
View Parameters
The grid embed renders the shared Combo controller (ADR-0004). Calendar joins Grid as a peer View; the Map View is disabled on this endpoint. The View toggle auto-hides when only one view is available (so Places, which is grid-only, never shows a toggle).
| Parameter | Type | Default | Description |
|---|---|---|---|
views | string (CSV, ordered) | grid,calendar (events) / grid (places) | Ordered list of Available views. Order = toggle order; presence = enabled. Tokens: grid, calendar, map. map is ignored on the grid endpoint and calendar is always stripped for Places (Events-only). Duplicates are de-duped; an empty/all-stripped result falls back to grid. Legacy list token is accepted and mapped to grid. Example: views=calendar,grid. |
defaultView | string | first entry of views | Starting view. Must be one of the (guarded) Available views, else falls back to the first entry. Values: grid, calendar (map n/a here). |
initialView | string | — | Deprecated alias for defaultView; honoured only when defaultView is absent. Now also accepts calendar. Legacy list → grid. |
calendarMonths | number (1–12) | theme calendar.monthsToShow → 1 | Number of months the Calendar View renders at once. |
calendarCardStyle | string | theme calendar.cardStyle → compact | Calendar event card style: compact (default — small thumbnail + accent time + one-line title, no date badge) or card (full ui-components Card). |
calendarMaxPerDay | number | theme calendar.maxEventsPerDay → 4 | Max events shown per day cell before a "+N more" link. When omitted, resolves from the active theme's calendar.maxEventsPerDay. |
Calendar View behaviour (ADR-0005): In Calendar View the global date filter is bypassed and its date-range chip is hidden — the calendar's own month navigation is the date control. Taxonomy / vibe / category / search filters still apply. The date-filter value is preserved and re-applies when switching back to Grid.
Examples:
# Events grid that opens on the calendar, showing two months
/embed/grid?slug=austin&type=events&defaultView=calendar&calendarMonths=2
# Grid-only events (no calendar toggle)
/embed/grid?slug=austin&type=events&views=grid
# Calendar-first with full-size cards
/embed/grid?slug=austin&type=events&views=calendar,grid&calendarCardStyle=card
Filter Behavior Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
strictFilter | boolean | false | When true, taxonomy filters are applied server-side (AND logic). When false, filters are client-side (OR logic). |
onlyShowPassedTaxonomies | boolean | false | When true, filter chips only show values passed via URL (plus subcategories for hierarchical taxonomies). |
filterBehavior | string | "trapped" | Only applies when strictFilter=true. Controls how users can navigate taxonomy filters: |
Filter Behavior Options:
"trapped"- User is locked within the passed taxonomy values and their children"selected"- Passed filter values are pre-selected, but user can deselect and explore other options"open"- All taxonomies shown, passed values are not pre-selected
Grid Display Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
gridColumns | number | 3 | Number of columns in the grid |
shownAtStart | number | 99 | Number of items shown initially (before "Load More") |
showContentModeToggle | boolean | true (events) / false (places) | Show Events/Venues toggle. Users can switch between viewing events and venues with event counts. Defaults to true when type=events. |
Filter UI Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
showSearchFilter | boolean | true | Show the search input |
showVibeFilter | boolean | true | Show the vibes filter |
showCategoryFilter | boolean | auto | Show the category filter (auto-enabled for places) |
showTagFilter | boolean | true | Show the tags filter |
showAllTags | boolean | false | When true, force the tag filter row on and bypass any tagsToInclude/tagsToExclude restrictions (from both URL and theme), showing every tag. Theme equivalent: theme.filters.showAllTags. |
tagsToInclude | string | theme | Comma-separated allowlist of tag slugs/names — only these tags appear in the tag filter. Falls back to theme.filters.tagsToInclude. Ignored when showAllTags=true. |
tagsToExclude | string | theme | Comma-separated blocklist of tag slugs/names to hide from the tag filter. Falls back to theme.filters.tagsToExclude. Ignored when showAllTags=true. |
showTierFilter | boolean | false | Show membership-tier filter chips (filter items by membership tier). |
showItemCountOnFilters | boolean | true | Show item counts on filter chips |
visibleCats | number | - | Max categories to show before "Show More" pill (undefined = show all) |
visibleVibes | number | - | Max vibes to show before "Show More" pill (undefined = show all) |
visibleTags | number | - | Max tags to show before "Show More" pill (undefined = show all) |
filterViewMode | string | "horizontal" | Filter layout: "horizontal" or "tabbed" |
filterSelectionMode | string | "auto" | Selection mode: "single", "multiple", or "auto" |
multiSelectTaxonomies | array | [] | Taxonomy slugs that allow multi-select (e.g., ["vibes","tags"]) |
taxonomySortOrder | string | "count" | Sort order for taxonomy chips (see below) |
loginButtonSize | number | 32 | Avatar size (px) of the login/account button shown in the filters bar. |
Taxonomy Sort Order (taxonomySortOrder)
Controls how filter chips are sorted. Default is count (most items first).
Format: "taxonomy:order,taxonomy:order"
Values:
| Value | Description |
|---|---|
count | Default. Sort by item count (most items first), then alphabetically |
alpha | Alphabetical sorting (theme order → color → A-Z) |
Example: taxonomySortOrder=vibes:alpha,categories:alpha,tags:alpha for all alphabetical.
Date Filter Parameters (Events Only)
| Parameter | Type | Default | Description |
|---|---|---|---|
showDateRangeSelector | boolean | true | Show date range selector (only for type=events) |
dateFilterOptions | array | ["upcoming","today","weekend","next_week","month"] | Available date filter options |
groupRecurringEvents | boolean | false | Group recurring events to show only next occurrence |
showRecurrenceBadge | boolean | false | Show the recurrence label pill (e.g. "Weekly Wed - Sun") on event cards |
hideRangedEvents | boolean | false | Hide "ranged" events — those with a duration longer than 24 hours (e.g. multi-day festivals, ongoing exhibits). |
recurringBadgeLinkTo | string | "grid-filter" | Where recurring badge click navigates: "grid-filter" (filter in place) or "event-series-page" (navigate to series page) |
Date Boundary
Hard date limits that exclude events outside the range, regardless of user filter selections.
| Parameter | Type | Default | Description |
|---|---|---|---|
dateBoundaryStart | string | - | Events before this date are excluded. Accepts yyyy-MM-dd or relative offset. |
dateBoundaryEnd | string | - | Events after this date are excluded. Accepts yyyy-MM-dd or relative offset. |
Relative offset format: +Nd (days), +Nm (months), +Ny (years). Negative values work too (-7d = 7 days ago). The offset is computed fresh on each page load relative to the current date.
Examples:
# Only show events in the next 14 days
/embed/grid?slug=austin&type=events&dateBoundaryEnd=%2B14d
# Next 3 months of events
/embed/grid?slug=austin&type=events&dateBoundaryEnd=%2B3m
# Events between specific dates
/embed/grid?slug=austin&type=events&dateBoundaryStart=2026-06-01&dateBoundaryEnd=2026-09-01
Note: The + character must be URL-encoded as %2B in query strings.
Past Event Window
Controls how long after an event's end time it remains visible in the grid. Default behavior keeps every event visible for 90 minutes after it ends, so events with identical start/end times don't disappear the instant they begin.
| Parameter | Type | Default | Description |
|---|---|---|---|
pastWindow | integer (minutes) | 90 | Minutes after end_date that an event remains eligible. 0 cuts at end. 1440 shows for 1 day. 10080 shows for a week. Overridden by pastCutoff if both are set. |
pastCutoff | ISO 8601 datetime | – | Absolute floor — only events with end_date >= pastCutoff are shown, e.g. 2026-06-01T00:00:00. Site-local time. Overrides pastWindow when set. |
Examples:
# Show events for 6 hours after they end
/embed/grid?slug=austin&type=events&pastWindow=360
# Show all events from the past week onward
/embed/grid?slug=austin&type=events&pastWindow=10080
# Show every event ending on/after June 1, 2026
/embed/grid?slug=austin&type=events&pastCutoff=2026-06-01T00:00:00
Admin Display Settings (logged-in users only)
The Advanced panel exposed in the Filters bar to logged-in users surfaces display toggles that change what appears in the embed:
- Show unapproved — drops
is_approved=truefrom API queries - Show closed places — drops
is_closed=false(places only) - Hide items without images
- Min completeness score
These are admin-only and intentionally have no URL surface. The toggles
exist solely in the Advanced panel for logged-in users. User overrides are
persisted per-embed-instance in localStorage. Cascade for resolution:
user override (panel) > theme default > code default.
The persistence scope is keyed by a hash of
themeName + type + listId + cityId + boundary + embedInstance. Two
identically-configured iframes on the same host page share state by design;
pass embedInstance=foo (URL param) to force separation.
| Parameter | Type | Default | Description |
|---|---|---|---|
embedInstance | string | - | Optional opaque suffix used to give two otherwise-identical embeds independent admin-override scopes. |
hideNoImageItems | boolean | false | Pre-existing public param. Hide items that don't have images. Logged-in users can also override via the panel. |
Developer guide for adding a new admin display toggle:
web/src/hooks/useAdvancedDisplaySettings.ts.
Card Display Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
showVibesOnCards | boolean | true | Show vibes on cards |
showTagsOnCards | boolean | false | Show tags on cards |
showAddressOnCards | boolean | true | Show address on cards |
Deprecated: Use
subtitle2Source=address&subtitle2Position=below-titleinstead.
| subtitleSource | string | "none" | Source for card subtitle: "none", "category", "address", etc. |
| subtitleSources | string | - | Comma-separated list of sources to combine for the first subtitle when subtitleSource=custom. First-subtitle analog of subtitle2Sources — same token vocabulary, joined with •. |
| subtitlePosition | string | "above-title" | Subtitle position: "above-title" or "below-title" |
| subtitle2Source | string | content-type default | Data source for the second subtitle. Default: places="address", events="none". Options: "none", "category", "tag", "vibe", "address", "venue", "date" (date only, e.g. "Jun 15th"), "start_date_time" (date + time, e.g. "Jun 15th • 7:00 PM"), "price", "custom" (combine multiple — see subtitle2Sources) |
| subtitle2Sources | string | - | Comma-separated list of sources to combine when subtitle2Source=custom. Each token uses the same vocabulary as subtitle2Source (e.g. category, venue, start_date_time). Empty values are skipped; the rest are joined with •. Example: subtitle2Source=custom&subtitle2Sources=venue,start_date_time → "Great Hall • Jun 15th • 7:00 PM" |
| subtitle2Position | string | "below-title" | Position of the second subtitle: "above-title" or "below-title" |
| showRating | boolean | false | Show ratings on cards |
| showBookmark | boolean | false | Show bookmark button on cards |
| smartCrop | boolean | true | ImageKit AI smart crop (fo-auto). Set false for deterministic center crop |
| linkToExternalUrl | boolean | false | Open each card's source URL (event source, place website) in a new tab instead of the internal single-post page. Falls back to the internal permalink when no source URL is set. |
| showTierBadge | boolean | false | Show the membership-tier badge on cards (e.g. "Premium"). |
| usePillLayout | boolean | true | For multi-day events, render the date badge as a horizontal pill (date range). Set false for the stacked calendar-style badge. |
| ongoingEventShowNow | boolean | false | For ongoing events (started in the past, still running), show the start as "Now" instead of today's date. |
| timeBadges | string | - (off) | Comma-separated list of time-relative event badges to enable on cards (e.g. today,tonight,weekend). Off by default. Only the single highest-precedence matching badge renders per card. Falls back to theme.cards.timeBadges. See values below. |
Time Badges (timeBadges)
Opt-in, time-relative badges for event cards, computed from each event's start (and optional end) relative to "now". Pass a comma-separated list of types; unknown values are ignored. Only the single highest-precedence match renders per card.
| Value | Badge label | Matches when… |
|---|---|---|
ongoing | "Ongoing" | A multi-day event (≥ 24h span) is currently running |
happening-now | "Happening Now" | The event is currently live (start ≤ now ≤ end; requires an end date) |
tonight | "Tonight" | Starts today, at or after 5pm |
today | "Today" | Starts today |
tomorrow | "Tomorrow" | Starts tomorrow |
weekend | "This Weekend" | Starts during the upcoming Sat–Sun window |
this-week | "This Week" | Starts within today → next 7 days |
Precedence is highest-first in the order above — e.g. a 7pm event tonight shows "Tonight" rather than "Today" when both are enabled. Labels can be overridden per theme via theme.cards.timeBadges.
Example: timeBadges=happening-now,today,tonight,weekend
Updates Display
| Parameter | Type | Default | Description |
|---|---|---|---|
showUpdates | boolean | false | Enable updates display on cards |
updatesDisplayMode | string | "badge" | Display mode: "badge", "text", or "both" |
updatesFilterTypes | string | - | Comma-separated types: Update,Offer,Clue,Sponsor,Special |
Theme Parameter
| Parameter | Type | Default | Description |
|---|---|---|---|
theme / themeName | string | "default" | Theme slug for styling |
Sticky-Header Offset (scrollToTopOffset)
Applies to data-resize="true" embeds. When a visitor scrolls down the grid and clicks a card, the single place/event opens in place and load.js scrolls the host page back up so the item's title/hero is in view. If your host page has a sticky or fixed header, the embed's top edge lands underneath it and the title stays covered. Set scrollToTopOffset to your header's height (px) to leave that much gap above the embed after the scroll, so the title clears the header.
| Parameter | Type | Default | Description |
|---|---|---|---|
scrollToTopOffset | number | 0 | Extra pixels of gap left above the embed when it scrolls to the top after opening a single item. Set to your sticky header's height. Non-negative integers only; 0 rests the embed flush against the viewport top (the original behavior). |
Where it's read: Put scrollToTopOffset in the embed's URL params, alongside the others — it works on a proxied api.vibemap.com/list/<slug> short link too, because the embed reads it inside the iframe and forwards it to the loader over postMessage. The value is retained across the in-embed grid→single navigation, so you set it once on the grid embed and it also applies to the single/similar-item views opened from it. (For host-side configuration load.js also honors it on the <script>'s data-url query or a data-scroll-to-top-offset="100" attribute.)
/embed/grid?slug=austin&scrollToTopOffset=96
Example URLs
Basic Places Grid
/embed/grid?slug=austin&type=places
Events with Date Filters
/embed/grid?slug=dc&type=events&showDateRangeSelector=true
Grid with Custom Columns
/embed/grid?slug=la&gridColumns=4&shownAtStart=20
List-Based Grid
/embed/grid?list=my-curated-list&gridColumns=3
Filtered by Vibes (Client-Side)
/embed/grid?slug=sf&vibes=chill,artsy&showVibeFilter=true
Strict Filtering (Server-Side)
/embed/grid?slug=sf&strictFilter=true&categories=food&vibes=chill
Trapped Filter Behavior
/embed/grid?slug=austin&strictFilter=true&filterBehavior=trapped&categories=food
Custom Theme and Display Options
/embed/grid?slug=denver&theme=dark&showVibesOnCards=true&showAddressOnCards=true
Full Featured Example
/embed/grid?slug=nyc&type=events&gridColumns=3&shownAtStart=50&showVibesOnCards=true&showDateRangeSelector=true&filterViewMode=horizontal&theme=default
PostMessage Events
The embed communicates with the parent window via postMessage:
| Event Type | Description | Data |
|---|---|---|
"view-changed" | User switched View via the toggle | { embedId: "grid", view: "grid" | "calendar" } |
"filters-changed" | User changed a taxonomy/search filter | { embedId: "grid", data: <updates> } |
Note: Since converging onto the shared Combo controller, cards navigate via their permalink (a normal link) rather than emitting a
card-clickedpostMessage. Use a standard link/navigation handler in the parent if you need to intercept clicks.
Example Parent Window Handler
window.addEventListener("message", (event) => {
if (event.data.embedId === "grid") {
switch (event.data.type) {
case "view-changed":
console.log("View switched to:", event.data.view);
break;
case "filters-changed":
console.log("Filters changed:", event.data.data);
break;
}
}
});
Message Origin
Embed messages may arrive from either of these origins:
https://web.vibemap.com— when the embed is loaded directlyhttps://api.vibemap.com— when the embed is loaded via a Vibemap list link (/list/<slug>) or short link (/s/<slug>), which reverse-proxies the embed page through the API host
Parent-window listeners should filter by payload (event.data.embedId and event.data.type) rather than event.origin. The example handler above already follows this pattern.
If you must check event.origin, accept BOTH https://web.vibemap.com AND https://api.vibemap.com.
Embedding
Basic iframe Embed
<iframe
src="https://vibemap.com/embed/grid?slug=austin&type=places"
width="100%"
height="600"
frameborder="0"
style="border: none;"
></iframe>
Responsive Embed
<div style="position: relative; width: 100%; padding-bottom: 75%;">
<iframe
src="https://vibemap.com/embed/grid?slug=austin"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none;"
></iframe>
</div>