Developer docs  /  Themes

Routes & data scopes

ThemeV2RouteResolver.Resolve is a pure function from path → template + data scope. Paths aretrimmed and lower-cased first. The full table:

  • ` (empty) orhome`Template: templates/home.fluidData scope: HomeNotes: Page title "Home".
  • spacesTemplate: templates/spaces.fluidData scope: SpaceListingNotes: Honours ?location=, ?category=, ?attributes=1,2,3.
  • spaces/{slug}Template: templates/space-detail.fluidData scope: SpaceDetailNotes: Slug is the space UId (GUID); a bare name is accepted as a legacy fallback (prefers the Vacant match, ties broken by Id).
  • units, units/{slug}Template: as spaces… — Data scope: as above — Notes: Legacy alias — V1 called spaces "units"; the slug is rewritten so old links and pasted embed URLs keep working.
  • locationsTemplate: templates/locations.fluidData scope: HomeNotes: Full locations index.
  • locations/{slug}Template: templates/location.fluidData scope: LocationDetailNotes: Slug matched against location name (case-insensitive, spaces↔hyphens).
  • locations/{loc}/spacesTemplate: templates/spaces.fluidData scope: SpaceListingNotes: Location-scoped listing (LocationSlug set). An unresolvable slug fails closed to an empty listing, never org-wide data.
  • locations/{loc}/spaces/{slug}Template: templates/space-detail.fluidData scope: SpaceDetailNotes: Detail resolved within that location only.
  • contact or contact-usTemplate: templates/contact.fluidData scope: Page (slug contact) — Notes: Both aliases normalise onto one page key so section settings don't split.
  • attributes or featuresTemplate: templates/attributes.fluidData scope: Page (slug attributes) — Notes: Same aliasing; page title "Features".
  • embed/{anything}Template: inner route's template — Data scope: inner route's scope — Notes: Prefix stripped, inner path resolved normally, IsEmbed = true. Exception: an embedded space listing swaps to templates/embed-spaces.fluid (self-contained: no breadcrumbs/heading, inline detail view).
  • anything elseTemplate: templates/{slug}.fluidData scope: PageNotes: If no such template exists but a CMS page matches the slug, renders through templates/page.fluid; otherwise templates/404.fluid.

?embed=1 on any path is a fallback trigger for embed mode without the /embed/ prefix (usedby the admin preview panel). Embed mode changes the layout choice and the cache key, and setsRequest.IsEmbed / the layout's IsEmbed so templates can adapt.

What each data scope populates

Locations, Categories, Attributes, CmsPages, Menus, Footer, Header and Settingsare populated on every route. On top of that:

  • HomeExtra data: Spaces = all vacant, active spaces across the org's active non-hidden locations, ordered by Id, capped at 200 (SpaceListingMaxItems).
  • SpaceListingExtra data: Same as Home, further narrowed by the validated location/category/attribute filters (attribute filters require all listed attributes).
  • SpaceDetailExtra data: Space = the resolved space; Spaces = a one-element list containing it.
  • LocationDetailExtra data: Location = the location matched by slug.
  • PageExtra data: CmsPage = the stored page matching the slug, if any.

Whenever spaces are present, active promotions are matched per space (mirroring the publicsite's baseline rules: same location, same duration type, AppliesTo by entity UId, ascendingpriority) and the winning promotion's label/price fields are stamped onto the space (§4.3).