> ## Documentation Index
> Fetch the complete documentation index at: https://docs.feedbackloop.page/llms.txt
> Use this file to discover all available pages before exploring further.

# React websites

> Offer a safe refresh for new deployments and preview the release that is already loaded.

Mount one `WebsiteUpdates` beside your application. It needs no provider, API key, Tailwind setup or Tauri dependencies. Import the package stylesheet once. In frameworks with Server Components, mount it inside a client component (for example, a module with `'use client'`). Its package can be imported during SSR without accessing browser state; notification work begins after the client mounts.

```tsx theme={null}
import { WebsiteUpdates, type WebsiteBuild } from '@feedbackloop/react'
import '@feedbackloop/react/styles.css'

// Replace these literals during your build. Never fetch currentBuild from the manifest.
const currentBuild: WebsiteBuild = {
  buildId: 'deployment-2026-10-25-1',
  releaseVersion: '1.2.3',
}

export function App() {
  return (
    <>
      <YourWebsite />
      <WebsiteUpdates
        projectId="YOUR_PROJECT_ID"
        currentBuild={currentBuild}
        theme="system"
        beforeRefresh={async () => {
          await savePendingWork()
        }}
      />
    </>
  )
}
```

Install the SDK with `pnpm add @feedbackloop/react`. `WebsiteUpdates` was introduced in `0.2.0` and is available in the published `0.2.1` package. The `ReleaseNotes` component remains available when you want the complete embedded release history instead.

## Publish a deployment manifest

Serve `/version.json` from the same website by default. You may choose another URL with `manifestUrl`. Publish the manifest after the matching application assets are available and configure your hosting provider to return `Cache-Control: no-store` for it.

```json theme={null}
{
  "buildId": "deployment-2026-10-25-2",
  "releaseVersion": "1.2.4"
}
```

Build IDs are opaque strings. Any deployed ID different from the one compiled into the running JavaScript offers **Refresh**, including a rollback. Do not change the current running build value when the fetched manifest changes. The fetched `releaseVersion` is optional and never selects the after-refresh notes.

The SDK checks on mount, every five minutes while visible, on focus or return to a visible tab with a sixty-second throttle, and immediately when the browser returns online. It requests the manifest without cookies or cache. Only the newest deployment candidate is retained. **Not now** defers that same candidate in this tab; another deployment can prompt again.

## Save safely before refresh

`beforeRefresh` may return `void` or a promise. The SDK waits for it before reloading. Use it to flush autosaves, editor drafts or other pending consumer work. A rejection keeps the current document running and offers a retry. Refresh runs once at a time, and a pending callback cannot reload after the component unmounts or switches project/build/manifest identity.

## Show what changed after loading

The release preview uses `currentBuild.releaseVersion`, which describes the JavaScript already loaded. On the first visit, the SDK records that version silently. A later strictly greater semantic version requests its exact fresh published release from Feedback Loop. A missing release never falls back to the latest note, and an offline cache does not open this automatic panel. Publish the note with the matching **App version**; missing or unavailable notes retry on future lifecycle checks.

The acknowledgement is stored only after the matching preview renders. It keeps that panel open until **Dismiss what's new** or **Read release notes** is selected. The article is a real link that opens in a new tab. Preview images preserve their original proportions; unavailable images leave the title, excerpt and article link usable. If a new deployment is discovered while the panel is open, its refresh prompt waits until the panel is dismissed.

Preferences are isolated by project and resolved manifest URL. Another tab's newer acknowledgement is respected, and stale tabs cannot deliberately replace it with an older version. Storage denial suppresses automatic release previews; deployment prompts continue to work. Same-version builds and semantic downgrades stay quiet for release previews, while different build IDs can still offer a refresh.

## WebsiteUpdates props

| Prop | Type | Default |
| - | - | - |
| `projectId` | `string` | Required public project ID |
| `currentBuild` | `{ buildId: string; releaseVersion?: string }` | Required compiled build |
| `manifestUrl` | `string` | `/version.json` |
| `theme` | `system`, `light` or `dark` | `system` |
| `beforeRefresh` | `() => void` or `() => Promise<void>` | No save barrier |

All presentation CSS is scoped under `.fl-website-updates`, inherits your font and semantic palette variables, and keeps text at `text-sm` or larger. The notification is nonmodal and does not move keyboard focus. Icon motion uses upstream Animate UI defaults and is disabled for reduced motion.

## Embedded release reader

Use `ReleaseNotes` when you want a full embedded timeline or exact-version document in an existing route, page or dialog. Its reader contract remains compatible with `0.1.1`, alongside the new website notifications. Find your public project ID in **Release notes → Add to app** and [publish a note](https://docs.feedbackloop.page/integrations/release-notes.md#prepare-a-release) before testing.

### Install and render

Install the package:

```sh theme={null}
pnpm add @feedbackloop/react@0.2.1
```

Import the reader and its scoped stylesheet:

```tsx theme={null}
import { ReleaseNotes } from '@feedbackloop/react'
import '@feedbackloop/react/styles.css'

export function WhatsNew() {
  return <ReleaseNotes projectId="YOUR_PROJECT_ID" theme="system" />
}
```

Import the stylesheet once in your application's client entry point. Render `WhatsNew` from your existing route, dialog or page. Keep this browser component in client-rendered code when your framework separates server and client components.

### Props

| Prop | Type | Behavior |
| - | - | - |
| `projectId` | `string` (required) | Public Feedback Loop project ID. |
| `version` | `string` (optional) | Initial exact complete semantic version; omit for full history. |
| `theme` | `system`, `light` or `dark` (optional) | Defaults to `system`; the fallback palette follows the OS live. |

```tsx theme={null}
import { ReleaseNotes } from '@feedbackloop/react'
import '@feedbackloop/react/styles.css'

export function InstalledRelease() {
  return (
    <ReleaseNotes
      projectId="YOUR_PROJECT_ID"
      version="1.2.3+desktop.7"
      theme="dark"
    />
  )
}
```

The embedded reader has only these three public props. There are no custom fetch, endpoint, authentication or rendered-note callback props.

### History and exact versions

Omit `version` to browse the newest publications and load earlier pages. Pass `version="1.2.3"` to start with that exact app release. An unavailable exact version offers the full history rather than substituting another version. Set `theme` to `system`, `light` or `dark`; system follows the operating system.

Full history includes unversioned updates and loads ten notes per page. It preserves publication order, including earlier publication dates edited by an owner; it does not sort by semantic version. Unversioned notes use their titles. **All versions** returns from an exact release to history. A project can publish only one active note for each full version, including its build suffix.

Markdown uses the SDK's restricted renderer for headings, lists, tables, code, task lists, links and images. Managed images resolve through the release-specific image endpoint; HTTP(S) links open safely. No owner-only inventory or private image keys are exposed.

### Theme and layout

The precompiled stylesheet is scoped to `.fl-release-notes`. It does not require your application to install Tailwind or import private Feedback Loop CSS.

Existing application variables `--background`, `--foreground`, `--muted-foreground`, `--border`, `--accent` and `--ring` take precedence over the fallback palette selected by `theme`. Supply your own app theme through those variables; setting `theme="dark"` does not override a light value you already define.

Place the reader in a container with the width you want. It adapts to narrow layouts and scrolls long Markdown without requiring an app-wide layout change.

If your app defines a CSP, allow `https://feedbackloop.page` in `connect-src`. In `img-src`, allow the API origin and the actual redirected storage/CDN or external Markdown image origins. An API-origin-only image policy can block the final signed-image redirect.

### Loading, errors and saved copies

The reader owns loading, empty history, missing exact release, unavailable project, and retry controls. An unavailable exact version offers full history instead of substituting another version. A missing/deleted project is an authoritative unavailable response and clears affected cached content.

A network failure may show a clearly labelled saved copy. The best-effort browser cache is isolated by project and exact version, bounded to five recent views and one megabyte total. It stores Markdown, not image bytes, and tolerates denied storage. A missing exact release never shows another version's cached note. An open saved-copy or failed view retries on the browser's `online` event without polling.

A saved copy is not evidence that a note is still published. When testing, distinguish a live response from the reader's offline label; images may be unavailable while offline.

### Verify your integration

Check history and a known exact version, **All versions**, pagination, keyboard navigation, narrow layout, both palettes and live system changes. Test offline/reconnect and an unavailable project. Publishing a note does not distribute an app binary.

For native windows and update controls, use the separate [Tauri guide](https://docs.feedbackloop.page/integrations/release-notes/tauri.md). For your own renderer, use the [HTTP API](https://docs.feedbackloop.page/integrations/release-notes/http-api.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.