# Install Little Heads Up with a coding assistant

These instructions are for the coding assistant working in the customer's app repository. Follow that project's instructions and the customer's authorized scope. This document does not authorize deployment, charges, or customer communications.

## Before editing

Inspect the framework, browser entry point, backend runtime, existing monitoring and tests. When the customer supplies a saved alert-setup brief, instrument only its selected workflows using its exact action labels and success definitions. If there is no brief, choose one useful customer workflow, such as generating and delivering a report. Do not invent a backend for a static site. Explain any unsupported runtime or missing access.

The customer creates an app at https://littleheadsup.com/app/apps/ and registers its exact browser origin (scheme, hostname, and port if present). They receive a public browser token and a private server key. Do not rotate working keys as part of installation: rotation revokes existing integrations.

- Browser token: safe in frontend code; use the token for this app.
- Server key: customer sets `LHU_SERVER_KEY` directly in their backend's environment or secret manager. Never request it in chat, print it, commit it, or put it in `NEXT_PUBLIC_*`, `VITE_*`, browser storage, HTML, or URLs. Keep local secret files ignored by version control.
- Ingestion endpoint: `https://cvhroninwjjxszveqqrj.supabase.co/functions/v1/lhu-ingest`.

No customer-owned Resend account, monitoring database, edge function, or cron job is needed. Use the existing app backend. Managed email availability depends on the customer's workspace; installation does not enable it.

## Browser installation

For a saved setup brief, install browser reporting only if browser errors, actions, or forms were selected. Disable automatic errors/fetch reporting when only a selected action or form is wanted. Set form `data-lhu-timeout` and action timeouts to the selected browser deadline (maximum 300 seconds).

Load this classic script once in the app's shared browser layout, replacing the placeholder:

```html
<script src="https://littleheadsup.com/sdk/lhu.js"
  data-key="YOUR_BROWSER_TOKEN"
  data-endpoint="https://cvhroninwjjxszveqqrj.supabase.co/functions/v1/lhu-ingest"
  data-errors="true" data-fetch="true" defer></script>
```

Use the framework's supported script-loading mechanism, preserving the data attributes on the executing script. This SDK initializes from `document.currentScript`; do not import it as an ES module. Wait for load before using `window.LittleHeadsUp`, and do not reinitialize it on every route change. With a content security policy, add only the required script origin and ingestion connection origin; do not disable the policy. Keep browser globals out of server rendering.

Automatic monitoring observes browser errors and same-origin fetch failures. It does not cover every network request or infer business completion. The initial browser heartbeat proves the collector sent an event. Reports contain coarse categories, not request bodies or query strings.

For one important visible action, use `LittleHeadsUp.trackAction('load-report', work, 30000)` after the SDK is ready. The callback must include displaying the result. If the SDK is unavailable, run the original work anyway. Do not let monitoring block the app. Check `response.ok` yourself: a failed HTTP response does not automatically throw.

For forms, add `data-lhu-form="booking"` and call `LittleHeadsUp.completeForm(form)` only after the server accepts the submission. Use `LittleHeadsUp.failForm(form, 'submission_rejected')` for rejection. Never report field contents. Do not mark a click or a submit attempt as success.

## Server workflow

For a saved setup brief, add backend reporting only for selected server jobs, payments, or AI usage. Cost-only installations also need `outcome.delivered` after the entire related workflow actually completes, using the same opaque outcome ID. Omit explicit server deadlines to use the dashboard default for new outcomes.

Read the full reference: https://littleheadsup.com/install/workflow-sdk.md

Download https://littleheadsup.com/sdk/server.mjs into the customer's backend repository as `lhu-server.mjs`, inspect it, then import the local file. There is no npm package to invent. The helper uses standard fetch, AbortController and crypto.randomUUID APIs available in Node.js 20+ and compatible runtimes. For another backend language, explain that this JavaScript helper does not run there rather than claiming installation is complete.

```js
import { createReporter } from './lhu-server.mjs';

// Read configuration only on the server. Handle absent/invalid configuration
// without breaking the original business workflow; log no secret values.
const monitor = createReporter({
  key: process.env.LHU_SERVER_KEY,
  endpoint: 'https://cvhroninwjjxszveqqrj.supabase.co/functions/v1/lhu-ingest',
});

export async function runReport(order) {
  try {
    return await monitor.trackJob('generate-report', async () => {
      const report = await generateReport(order);
      await deliverReport(order, report);
      return report;
    }, { outcomeId: order.monitoringId, deadlineSeconds: 300 });
  } finally {
    await monitor.flush();
  }
}
```

Adapt the example to existing functions; it is not a standalone runnable app. Put delivery inside the callback and throw when delivery fails. Preserve the original return value, error, authorization and job retry behavior. Never retry a business operation just because telemetry failed. Avoid double instrumentation.

The helper emits `job.started` and then `job.failed` or `outcome.delivered`. It returns/rethrows the callback's result/error without collecting either. `createReporter` can throw for invalid configuration, so keep initialization errors from blocking customer work. In serverless handlers, await `trackJob` before awaiting `flush` in finally, or register the flush with the host's supported background lifetime mechanism after the job finishes.

Use a stable opaque outcome ID shared by related server events (maximum 120 characters: letters, digits, underscore, dot, colon, hyphen). Do not include emails, prompts, customer content or secrets. Use stable action labels, maximum 80 characters with the same character set.

Where the app already verifies payment, optionally report `payment.succeeded` from that trusted server handler with the actual amount in minor units, currency and the same outcome ID. Give each event its own stable event ID; reuse that ID for a transport retry. Never infer payment from the browser or create a charge to test monitoring. Report `ai.usage` only when the app supplies a meaningful estimated `cost_usd`; do not fabricate spend or change model providers. See the reference for the exact report API.

The helper is bounded, best-effort telemetry. `report()` acceptance and `flush()` completion do not prove receipt. It does not retry business jobs, stop spending, cancel jobs at the monitoring deadline, or independently prove a customer received the result.

## Verify, then hand back

1. Run relevant existing tests and the app build. Check no private key enters the frontend bundle or version control.
2. In a development/staging app with its own correctly registered origin, load a page and confirm a browser event from that app in Signal history.
3. Run a safe successful workflow; confirm server `job.started` and `outcome.delivered` with the same outcome ID. Run a safe controlled failure and confirm `job.failed` and its case. Use mocked delivery/payment providers so tests cannot contact real customers or charge them.
4. Open Apps & setup → Installation checks. Distinguish actual browser/server events from the built-in workspace setup test, which only checks case creation. Do not turn on recurring availability checks, email, or billing as part of SDK installation.
5. If account or browser access is unavailable, give exact manual steps and mark live receipt unverified. An accepted telemetry request alone is not proof of an inbox alert. Email requires enabled delivery and a separately authorized inbox test.

Summarize changed files, installed sources, the workflow covered, test results, observed live evidence and remaining manual steps. Do not imply this one integration covers every page, job, payment or outcome.
