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

# Overview

> Render your integration's surfaces locally in real Ekanos chrome, with fixtures or live requests to your own API.

The Ekanos harness (`@ekanos/harness`) is a local development environment that renders every surface of your integration—widgets, the marketplace tile, activation form, and triggers—in actual Ekanos chrome, without Supabase, authentication, or network traffic.

## Key features

* **Real chrome, no backend** — widgets render in the actual Ekanos dashboard grid with real `Widget.*` compound components and design tokens
* **Fixtures by default** — HTTP exchanges recorded per variant (`default`, `empty`, `error`) answer all requests; the network is refused
* **Live mode opt-in** — switch the toolbar to **Live API** to send real requests to your vendor under your declared egress, with a real localhost OAuth loop for OAuth integrations
* **Fixture variants** — switch between happy path, empty state, and error from the toolbar; the widget subtree is rebuilt, so any widget that re-fetches gets the new recording
* **Triggers surface** — run webhooks and schedules locally, and (in live mode) the OAuth loop against your own developer app
* **Actions surface** — invoke your declared `actions` handlers from a widget's Save button; runs in fixtures or live
* **No configuration required** — `useIntegrationFetch()` and `useActivationData()` from `@ekanos/sdk/hooks` already work; write fixtures and you're done

## Installation

A project created by `ekanos init` already lists `@ekanos/harness` in its `package.json`. Install dependencies, then run:

```bash theme={null}
ekanos dev
```

`ekanos dev` checks that the harness and its peers (`next`, `react`, `react-dom`, `tailwindcss`, `@tailwindcss/postcss`) are installed, generates the shell under `.ekanos/harness/`, writes a starter `harness.config.ts` at your project root the first time (the only file you edit), and starts the dev server. The generated shell is rewritten on upgrade; your `harness.config.ts` is never touched after it is created.

## Quick start

Set up `harness.config.ts` with one integration:

```ts theme={null}
import { defineHarnessConfig } from '@ekanos/harness/config';
import {
  asHarnessDefinition,
  harnessWidgetsFromDefinition,
} from '@ekanos/harness/registry';
import { integration as myDefinition } from '@you/integration';

export const harnessIntegrations = defineHarnessConfig([
  {
    slug: 'my-integration',
    name: 'My Integration',
    description: 'A test integration',

    // Derived from your definition to avoid duplication
    widgets: harnessWidgetsFromDefinition(myDefinition, {}),

    // Recorded HTTP exchanges per variant
    fixtures: {
      default: [
        {
          request: 'GET https://api.example.com/data',
          response: { items: [] },
        },
      ],
    },

    // Your integration definition, for Triggers
    definition: asHarnessDefinition(myDefinition),

    // Opt in to live mode for real requests
    live: {
      seeds: [], // optional: Ekanos-side state that stays mocked
    },
  },
]);
```

`ekanos dev` serves the harness at `http://localhost:3100` by default (bound to loopback; `--port` and `--host` change that). Select your integration to see tabs for **Widgets**, **Marketplace tile**, **Activation**, and **Triggers**.

## Surfaces

Each integration is rendered at `/<slug>` with four tabbed surfaces:

* **Widgets** — your dashboard grid, rendered with real `Widget.*` components
* **Marketplace tile** — your marketplace card, in the catalogue grid (if declared)
* **Activation** — the form users see when connecting your integration
* **Triggers** — your declared webhooks, schedules, and OAuth (requires `definition`)

Each widget can also be opened on its own at `/<slug>/widgets/<widgetId>`.

## How data flows

### Fixtures mode (default)

1. The toolbar's **Data** dropdown is on **Fixtures** (the default)
2. `globalThis.fetch` is patched to intercept third-party and `/api/…` requests
3. Requests match against your `fixtures` list for the active variant
4. A matching fixture is returned; no request leaves the machine
5. An unmatched request rejects with `NoRecordedResponseError`, whose message includes the fixture line to paste

### Live mode (opt-in)

1. A `live` block is declared on the integration entry
2. The toolbar's **Data** dropdown is set to **Live API**
3. Widgets' own requests reach your real API
4. Requests are checked against your definition's `egress` allowlist
5. The OAuth loop runs on localhost using client credentials from `.ekanos/local-secrets.json`
6. One server-held context per integration holds tokens and storage for the life of the dev server

## What's in the bundle

**Everything in `harness.config.ts` is compiled into the browser bundle**, including `triggerMocks.secrets`. Keep mock values fake. The `.ekanos/` directory (and its `.next` build output) is gitignored; never commit the generated build.

## Exports

| Entry | Contents |
| - | - |
| `@ekanos/harness/registry` | Types: `HarnessIntegration`, `HarnessWidget`, `HttpFixture`, `FixtureSeed`, and constants like `HARNESS_ACCOUNT_ID` |
| `@ekanos/harness/config` | `defineHarnessConfig()` — identity function that also checks slugs and widget ids are URL-safe and unique |
| `@ekanos/harness/app` | `RootLayout`, `IndexPage`, `harnessMetadata` |
| `@ekanos/harness/routes` | Page components: `IntegrationLayout`, `WidgetsPage`, `SingleWidgetPage`, `TilePage`, `ActivationPage`, `TriggersPage` |
| `@ekanos/harness/hooks` | `useHarnessDataMode()`, `useLiveActivationData()` — harness-only hooks |
| `@ekanos/harness/api` | `createHarnessApiHandlers()` — server entry, never import from a `'use client'` module |
| `@ekanos/harness/styles.css` | Tailwind layer + design tokens + Font Awesome repairs |
| `@ekanos/harness/mocks/team-account-workspace` | Drop-in mock for `useTeamAccountWorkspace()` |

## Next steps

* [Configure your integration](/harness/configuration)
* [Write HTTP fixtures](/harness/fixtures)
* [Set up live mode](/harness/live-mode)
* [Run triggers locally](/harness/triggers)
* [Invoke actions from widgets](/harness/actions)


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