npm package: @liteguard/liteguard-react
Description: React bindings for Liteguard. Feature guards, observability, and CVE auto-disable via LiteguardProvider and useIsOpen hook
Latest version: 0.6.20260405

# @liteguard/liteguard-react

[![JavaScript SDK](https://github.com/liteguard/liteguard/actions/workflows/test-js.yml/badge.svg)](https://github.com/liteguard/liteguard/actions/workflows/test-js.yml)
[![npm](https://img.shields.io/npm/v/@liteguard/liteguard-react)](https://www.npmjs.com/package/@liteguard/liteguard-react)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/liteguard/liteguard/blob/main/LICENSE)

- Website: [liteguard.io](https://liteguard.io)
- Project Page: [https://github.com/liteguard/liteguard](https://github.com/liteguard/liteguard)
- Issues: [https://github.com/liteguard/liteguard/issues/new](https://github.com/liteguard/liteguard/issues/new)

> Feature guards, observability, and security response in a single import. Evaluated locally, zero network overhead per check.

React bindings for Liteguard. Drop in `<LiteguardProvider>` and use the `useIsOpen` hook to gate any component tree. Guards are evaluated locally with no network round-trips.

Powered by [`@liteguard/liteguard-browser`](https://www.npmjs.com/package/@liteguard/liteguard-browser) under the hood, so runtime behavior, signal telemetry, and CVE auto-disable all work out of the box.

---

## Installation

```bash
npm install @liteguard/liteguard-react
```

React 18+ and react-dom 18+ are required as peer dependencies.

---

## Quick Start

```tsx
import { LiteguardProvider, useIsOpen } from '@liteguard/liteguard-react';

function CheckoutButton() {
  const enabled = useIsOpen('payments.checkout');
  if (!enabled) return null;
  return <button onClick={checkout}>Checkout</button>;
}

export function App() {
  return (
    <LiteguardProvider projectClientToken="pct-..." properties={{ userId: 'user-123', plan: 'pro' }}>
      <CheckoutButton />
    </LiteguardProvider>
  );
}
```

---

## API Reference

### `<LiteguardProvider>`

Context provider that initializes the Liteguard browser client and makes it available to all descendant components. Place it near the top of your component tree, typically alongside your other providers.

If you pass an externally created `client`, call `await client.start()` before rendering the provider. When you pass `projectClientToken`, the provider creates and starts the browser client for you.

```tsx
<LiteguardProvider
  projectClientToken="pct-..."
  environment="env-production"  // optional uses workspace default if omitted
  properties={{ userId: 'user-123', plan: 'pro' }}  // optional initial properties
  fallback={false}              // default result while guards are loading
>
  {children}
</LiteguardProvider>
```

All `init` options are accepted as props with the same `camelCase` names:

| Prop | Default | Description |
|---|---|---|
| `projectClientToken` | required | Your Liteguard project client token |
| `environment` | workspace default | Environment slug |
| `fallback` | `false` | Guard result before rules load |
| `refreshRateSeconds` | `30` | Guard rule refresh interval |
| `flushRateSeconds` | `10` | Signal flush interval |
| `flushSize` | `500` | Max buffered signals before forced flush |
| `httpTimeoutSeconds` | `4` | HTTP request timeout |
| `backendUrl` | `https://api.liteguard.io` | API base URL override |

### `useIsOpen(name, options?) → boolean`

Hook that returns `true` if the named guard is open for the current context. Re-renders when guard rules are refreshed.

```tsx
const enabled = useIsOpen('payments.checkout');

// With per-call property override
const enabled = useIsOpen('payments.checkout', { properties: { region: 'us-east-1' } });
```

> `useIsOpen` is intentionally render-safe and does not emit `guard_execution` measurement signals. For guarded execution with telemetry, use `useLiteguardClient().executeIfOpen(...)`.

### `useLiteguardClient() → LiteguardClient`

Returns the underlying `LiteguardClient` instance. Use this for guarded execution with measurement signals, programmatic property management, or direct guard checks outside of React rendering.

```tsx
function CheckoutButton() {
  const client = useLiteguardClient();

  const handleClick = async () => {
    const session = await client.executeIfOpenAsync('payments.checkout', async () => {
      return createCheckoutSession();
    });

    if (session === undefined) {
      // guard was closed
    }
  };

  return <button onClick={handleClick}>Checkout</button>;
}
```

---

## Guard Evaluation

Guards are evaluated **client-side** against rules fetched once at initialization and refreshed periodically. Rules are evaluated in order **first matching rule wins**. If no rule matches the guard's configured default applies.

```
guard "payments.checkout"
  rule: plan == "pro"           → open
  rule: userId in [canary-list] → open
  default                       → closed
```

### Operators

| Operator | Description |
|---|---|
| `EQUALS` | Exact match |
| `NOT_EQUALS` | Negated exact match |
| `IN` | Value in a set |
| `NOT_IN` | Value not in a set |
| `REGEX` | Regular expression match |
| `GT` / `GTE` | Greater than / greater or equal |
| `LT` / `LTE` | Less than / less or equal |

---

## License

Apache 2.0 see [LICENSE](https://github.com/liteguard/liteguard/blob/main/LICENSE).