--- title: The integration folder description: How integration/ is laid out — configuration, hooks, styles, templates and translations per widget — and the global settings every widget shares. slug: luma/integration-folder docKind: reference hub: luigisbox-ai --- Everything specific to your site lives in `integration/` of your repository. Luma itself is installed in `node_modules/@luigisbox/luma/` and is not edited. ```text integration/ __integration.ts hands the folder to Luma _global/ shared by every widget _config.ts _init.ts _widget.ts _analytics.ts _translations.ts style-*.css template-*.ts autocomplete/ _config.ts _init.ts _widget.ts style-host.css template-*.ts search/ _config.ts _translations.ts style-host.css template-search-*.ts plp/ category pages: _config.ts _init.ts style-host.css recommender / one folder per recommender: _config.ts _init.ts _translations.ts ``` A widget runs when its folder has a `_config.ts`. A recommender folder is named `recommender ` plus a name of your choosing — `recommender similar`, `recommender cart` — and you can have any number of them. ## The files | File | Contains | Loaded | |---|---|---| | `_config.ts` | The widget's configuration, as a default-exported object. JSON values only — strings, numbers, booleans, arrays, objects. | On every page | | `_init.ts` | A function that receives the configuration and may change it. Anything that needs code goes here. | On every page | | `_widget.ts` | A function like `_init.ts`, for hooks only the widget itself calls | With the widget | | `_translations.ts` | Text overrides, keyed by locale | With the widget | | `_analytics.ts` | `_global/` only: the analytics events Luma sends — see [Analytics](/luma/analytics/) | After the page has loaded | | `style-host.css` | CSS that hides your own UI the widget replaces, applied only while Luma's is shown | On every page | | `style-*.css` | The widget's styles | With the widget | | `template-.ts` | A template override — see [Templates](/luma/templates/) | With the widget | `_config.ts` is read as JSON at start-up. A function in it is dropped, and the browser console names the file and the key. ### `_init.ts` versus `_widget.ts` `_init.ts` ships and runs on every page, so keep in it only what decides whether and where a widget runs: `disabled`, `active`, `readQuery`, `items`, `intent`, selectors computed in code, switching your site's own widgets off. Hooks only a widget calls — `computedAttributes`, `toFilter`, `facetsFor`, `onRender`, `onOpen` and the like — go in `_widget.ts`, which loads with the widget's code. Its return value is ignored. ```ts // integration/plp/_init.ts import type { PlpConfigType } from '@/types'; export default (c: PlpConfigType) => { // Not on the outlet section, which has its own listing. c.active = (url) => !url.pathname.startsWith('/outlet/'); }; ``` `_global/_init.ts` runs first and receives the whole configuration. Returning `false` from it stops the integration on that page. Returning `false` from a widget's `_init.ts` stops that widget. Types for every key are in `@/types` — `LumaConfigType`, `SearchConfigType`, `PlpConfigType`, `AutocompleteConfigType`, `RecommenderConfigType`. ## Global settings `_global/_config.ts`: ```ts export default { publishableKey: 'pub_xxx', channelId: 'lbn_4hj9tv', region: 'eu1', locale: 'de', currency: 'EUR', inputSelector: 'header input[name="q"]', }; ``` | Key | Default | | |---|---|---| | `publishableKey` | — | Required. The channel's [publishable key](/authentication/browser-tokens/). Without it, Luma does not start. | | `channelId` | — | Required. The [channel](/concepts/catalogs-and-channels/) every request reads. Without it, Luma does not start. | | `region` | `eu1` | The API region | | `locale` | `en` | Text and number formatting. Built-in text exists for `en`, `de` and `cs`; other locales need [translations](#translations). | | `currency` | — | ISO 4217 code, used by the `price()` template helper | | `priceFormat` | — | `Intl.NumberFormat` options for `price()`, for example `{ "trailingZeroDisplay": "stripIfInteger" }` | | `itemType` | `product` | The object type listings and recommenders show | | `inputSelector` | — | CSS selector of your search input(s). Autocomplete attaches to whatever matches, and search uses it to recognise your search form. | | `disabled` | `false` | `true` turns the whole integration off | | `images` | — | How product images are sized and loaded — see [Templates](/luma/templates/#images) | | `speculation` | `prerender` | Product links in Luma's widgets are prerendered (`prerender`) or fetched (`prefetch`) when the shopper hovers them; `false` turns it off. See [Behaviour](/luma/behaviour/#speeding-up-navigation). | | `speculationEagerness` | `moderate` | `moderate`: on hover. `conservative`: on press only. | | `speculationSelector` | Links in Luma's widgets | CSS selector of the links speculation applies to | | `prefetchFilters` | `true` | A filter, sort or "show more" is fetched when the shopper hovers, touches or focuses it | | `preconnectImages` | `true` | On later page loads, Luma preconnects to the image host it saw in results | | `contrastToggle` | `false` | Shows a high-contrast switch at the start of every listing. The high-contrast mode itself follows the visitor's operating-system setting without it. | | `analytics` | — | `false` turns [analytics](/luma/analytics/) off, whatever `_analytics.ts` says | | `dataLayer` | `dataLayer` | The name of the global array [`dl()`](/luma/analytics/#triggers) reads | Set in `_global/_widget.ts` or `_global/_init.ts`, because they are functions: | Key | | |---|---| | `computedAttributes` | Values derived from a result, available to templates as `r.c.`. See [Templates](/luma/templates/#results). | | `addToCart` | `(result, { count, el, event })`: puts a product in your cart when a `[data-lbx-cart]` button in a Luma tile is clicked. See [Add to cart from a tile](/luma/analytics/#add-to-cart-from-a-tile). | Any widget's configuration can also set `disabled: true`, and `computedAttributes` that apply to that widget only. ## Translations Luma's built-in text — button labels, headings, announcements for screen readers — comes from a dictionary per locale. Override any key, or supply a whole locale, in `_translations.ts`: ```ts // integration/_global/_translations.ts export default { de: { search: { sort: 'Sortieren', sorts: { '': 'Relevanz', 'lbx:price:asc': 'Preis aufsteigend' } }, }, }; ``` - `_global/_translations.ts` applies to every widget; a widget folder's applies to that widget only. - `{name}` in a string is a placeholder. - A plural is an object of [`Intl.PluralRules`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules) categories, picked by the `count` parameter. `other` is required: `{ "one": "{count} produkt", "few": "{count} produkty", "other": "{count} produktů" }`. - Only the configured locale is loaded. ## See also - [Templates](/luma/templates/) — rendering results in your markup - [Autocomplete](/luma/widgets/autocomplete/), [Search results](/luma/widgets/search/), [Category pages](/luma/widgets/category-pages/), [Recommenders](/luma/widgets/recommenders/) — each widget's keys