# Livespace plugins

A plugin is a web page. Livespace embeds it in an `<iframe>` on a deal, company,
person or space profile, and talks to it over `postMessage`. You host it
yourself, on your own origin, in whatever stack you like — the SDK is one script
tag and has no dependencies.

```html
<!doctype html>
<html>
	<head>
		<script src="https://cdn.jsdelivr.net/npm/@livespace/plugin-sdk@1/dist/ls-plugin.js"></script>
		<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@livespace/plugin-sdk@1/dist/ls-tokens.css" />
	</head>
	<body>
		<p id="out">Loading…</p>
		<script>
			LsPlugin.on("ready", ({ context, config }) => {
				document.getElementById("out").textContent =
					`Deal: ${context?.deal?.name ?? "—"}`
			})
		</script>
	</body>
</html>
```

That is a complete, working plugin.

## The three modes

Your page is loaded in one of three modes, and it is told which one before
anything else arrives. Check it if you render differently in any of them.

| Mode | What it is | You get |
|---|---|---|
| `view` | Running on a real profile. The normal case. | `context` + `config`, each re-sent when it changes |
| `preview` | An admin is looking at your plugin while configuring it. There is no object to be about. | `config` only, re-sent on every keystroke |
| `config` | Livespace is asking what settings you need. Nothing you draw is shown. | Neither — answer and stop |

In `config` mode you must reply, even if you have no settings. See
[Configuration forms](./config-forms.md).

## Where to go next

- [Getting started](./getting-started.md) — the script tag, the handshake, and
  the one thing that catches everyone out
- [API reference](./api-reference.md) — every method and property
- [Your backend](./backend.md) — verify the token Livespace gives your plugin,
  if it has a backend of its own (preview)
- [Objects](./objects.md) — what a deal, company, person or space carries, with
  full examples
- [Styling](./styling.md) — design tokens, so your plugin looks like Livespace
- [Configuration forms](./config-forms.md) — let admins configure your plugin
  without you building a settings UI
- [Protocol](./protocol.md) — the raw messages, if you cannot use the SDK

## Rules that will bite you

Each of these is a real failure, not a style preference.

- **Serve your plugin over HTTPS, from a whitelisted domain, and not from the
  Livespace origin.** Livespace only accepts HTTPS plugin URLs whose host is on
  the account's plugin whitelist: `*.livespace.dev` is on it for every account,
  and any other domain has to be added for the account by Livespace support. A
  plugin on the host's own origin would defeat the iframe sandbox, so Livespace
  refuses to render it and logs an error.
- **Reply in `config` mode even when you have no settings.** Silence is not an
  answer; Livespace waits out a timeout and the admin sees nothing.
- **Configuration values are not secret.** Anyone who can open the plugin's
  settings can read them. Never put an API secret in one; declare it with
  `addSecretInput`, which only your backend can read.
- **`null` config is not `{}`.** `null` means nobody has ever configured this
  plugin; `{}` means they configured it and left everything blank.
