# Dynamic sources

## Available objects

| Object | Available data |
| --- | --- |
| `site` | `site.name` |
| `page` | `page.title`, `page.slug` |
| `settings` | Global Loom settings |
| `section` | Current section instance and settings |
| `block` | Current block instance and settings |
| `locale` | Current storefront language |

A Loom expression such as `[[ site.name ]]` always reads site context. A schema text setting can instead let the customer choose between literal text and a dynamic source.

## Store a binding

```json
{"title":{"$source":"page.title","fallback":"Our services"}}
```

Place this object in an instance's `settings`, where `title` is a declared text setting. The editor currently offers the site name, page title and page slug for text/textarea controls. With a binding selected, the input edits the fallback. The preview resolves the actual page value.

Resolution order is the available source value, the binding fallback, then the schema default. Missing values trigger fallback; an intentional empty string, false or zero remains a value. Test unavailable sources separately from empty strings.

## Sources are data paths

`$source` is not executable Loom. Do not write `[[ page.title ]]`, filters or a function call inside it. The runtime reads permitted own properties and rejects prototype traversal. Source roots are `site`, `page` and `closest`.

`closest` only works when a platform integration explicitly passes resource context. Automatic custom resource binding is not available. Theme authors cannot invent `product` or `collection` objects by adding source strings.

## Troubleshooting a stale heading

Confirm the setting contains a binding, the current page actually has a title, and markup uses `section.settings.title` rather than a hardcoded string. Inspect fallback separately. If an inline rich text override exists, check it is cleared by the setting edit. Save, reload and compare the public renderer with the preview.
