# Crooli Collective launcher

This directory is the single source of truth for the shared TIZZLE product launcher. Product sites load `launcher.js`; the web component then fetches `apps.json`, filters out disabled entries, sorts the remainder by `order`, and renders the launcher inside Shadow DOM. Icons are served from `apps/icons/`.

## Edit the product list

Open **Crooli Collective** in PagesCMS. Add, remove, rename, reorder, enable or disable products there. `order` accepts numbers, so gaps such as `10`, `20`, and `30` make later insertion easy. Icon files can be selected or uploaded from the **App Icons** media library, with an optional dark-mode icon for artwork that should not be colour-inverted. Every URL is stored only in `apps.json`, including the initial product URLs, so uncertain or changing destinations can be edited without changing the launcher code.

Saving in PagesCMS commits `public/apps/apps.json`. Once the content site deployment completes, every product fetches the updated directory automatically.

## Add it to a TIZZLE website

```html
<script
  src="https://content.crooli.com/apps/launcher.js"
  defer
></script>

<tizzle-app-launcher></tizzle-app-launcher>
```

No CSS import or framework package is required. Load the script once per page. Multiple launcher elements are supported, and the custom element definition is guarded against duplicate script initialisation.

The default theme is automatic, so existing integrations do not need to change. To override the visitor's operating-system preference, set `theme="light"` or `theme="dark"`:

```html
<tizzle-app-launcher theme="light"></tizzle-app-launcher>
<tizzle-app-launcher theme="dark"></tizzle-app-launcher>
```

Sites with a manual theme toggle can update the attribute at runtime. Remove the attribute or set it to `auto` to return to automatic mode.

## Caching

The launcher keeps a successful response in the current browser tab for one minute. It also requests revalidation from the network and the host gives `apps.json` a one-minute shared cache with no stale-response window. Editors should normally see a deployed CMS change within about one minute.

`launcher.js` automatically adds its version to the `launcher.css` request, such as `launcher.css?v=1.0.7`. This prevents a previously cached stylesheet from blocking new theme or layout behaviour after a launcher release. JavaScript and CSS responses must revalidate after one minute in the browser and do not use long stale-response windows.

## Release a future version

The current component version is declared near the top of `launcher.js`. For a breaking release, copy the implementation to a new public file such as `launcher.v2.js`, update its version constant, test it independently, and migrate product sites deliberately. Keep `launcher.js` compatible for existing consumers. Versioned files should use their own custom-element tag if both versions may appear on one page.

## Test locally

From the repository root:

```sh
npm run build
npm run serve
```

Then open `http://localhost:4173/apps/test.html`. The fixture loads the local JSON through the component's test-only `data-source` override. Use the controls to switch between the working directory and a missing JSON response. Test Tab, Shift+Tab, Enter, Space, Escape, Home, End, and the arrow keys; resize below 420px; and switch the operating-system colour scheme to check mobile and dark modes.
