Developer guide

Install @nzila/sdk@0.1.14+, wire reporters, send runs, instrument runtime/VESL/DOM signals, and use feature intelligence in the dashboard.

Set up in the dashboard

  1. Create a project under Projects and copy its App name — every payload must use this exact appName.
  2. Under API Keys, generate a key for that project. Copy it when shown; you cannot view it again.
  3. Use the project switcher in the header to choose which project you are viewing; keys only ingest into their own project.

Hosted platform

Production dashboard: https://nzila-kappa.vercel.app — sign in, create projects, and manage API keys. After ingestion, use Regression insights, Release health, Journeys, global search (Ctrl/Cmd+K), and execution replay on each run.

Install & configure @nzila/sdk

Reporters send one webhook per finished run. Use nzila.config.ts from the CLI or environment variables in CI. Set NZILA_DEBUG=1 if nothing arrives.

Install

npm install @nzila/sdk

Vitest projects need vitest as a peer. TypeScript: use moduleResolution bundler, node16, or nodenext for @nzila/sdk/* subpaths.

CLI

# Open the hosted dashboard and print setup steps
npx @nzila/sdk

# Sign in, then link this repo to a project
npx @nzila/sdk login
npx @nzila/sdk link --api-key nzl_… --project-id <uuid> --app-name my-app

# Verify nzila.config.ts and integration
npx @nzila/sdk doctor
npx @nzila/sdk repair --dry-run
npx @nzila/sdk repair --apply
# Roll back Vitest config patches: npx @nzila/sdk repair --rollback

nzila.config.ts

Copy project ID from API Keys after creating a key. locale drives AI run summaries, grouped test steps, failure analysis, and PDF export text.

// nzila.config.ts (created by npx @nzila/sdk link)
export default {
  apiKey: "nzl_xxxxxxxx",
  projectId: "00000000-0000-0000-0000-000000000000",
  appName: "my-app", // must match Projects → App name
  endpoint: "https://nzila-kappa.vercel.app",
  framework: "vitest",
  locale: "en", // en | pt | fr | zh — AI summaries & failure copy
} as const;

Vitest (recommended)

Use nzilaVitestReporter(reporterOptionsFromNzilaConfig(...)) — do not use new NzilaVitestReporter() in vitest.config (worker serialization).

import { defineConfig } from "vitest/config";
import { nzilaVitestReporter } from "@nzila/sdk/vitest";
import { reporterOptionsFromNzilaConfig } from "@nzila/sdk";
import nzilaConfig from "./nzila.config";

// Important: use nzilaVitestReporter(...) — never new NzilaVitestReporter()
// (Vitest worker pools cannot serialize class instances).

export default defineConfig({
  test: {
    reporters: [
      "default",
      nzilaVitestReporter(reporterOptionsFromNzilaConfig(nzilaConfig)),
    ],
  },
});

Or pass webhookUrl, apiKey, appName, and projectId directly:

import { defineConfig } from "vitest/config";
import { nzilaVitestReporter } from "@nzila/sdk/vitest";

export default defineConfig({
  test: {
    reporters: [
      "default",
      nzilaVitestReporter({
        webhookUrl: process.env.NZILA_WEBHOOK_URL!,
        apiKey: process.env.NZILA_API_KEY!,
        appName: process.env.NZILA_APP_NAME!,
        projectId: process.env.NZILA_PROJECT_ID,
        locale: "en",
        maxRetries: 3,
      }),
    ],
  },
});

Jest

Use the tuple form ["@nzila/sdk/jest", options] in jest.config.cjs or jest.config.js.

/** @type {import('jest').Config} */
module.exports = {
  testEnvironment: "node",
  reporters: [
    "default",
    [
      "@nzila/sdk/jest",
      {
        webhookUrl: process.env.NZILA_WEBHOOK_URL,
        apiKey: process.env.NZILA_API_KEY,
        appName: process.env.NZILA_APP_NAME,
        projectId: process.env.NZILA_PROJECT_ID,
        framework: "jest",
        locale: "en",
        // feature names auto-detected from test file + describe()
      },
    ],
  ],
};

Mocha

const { createMochaNzilaReporter } = require("@nzila/sdk/mocha");

module.exports = {
  reporter: createMochaNzilaReporter({
    webhookUrl: process.env.NZILA_WEBHOOK_URL,
    apiKey: process.env.NZILA_API_KEY,
    appName: process.env.NZILA_APP_NAME,
    framework: "mocha",
    locale: "en",
  }),
};

Manual / custom CI

Build the same tests[] array and call sendNzilaRun from Node after your suite finishes.

import { sendNzilaRun } from "@nzila/sdk";

await sendNzilaRun(
  {
    runId: "ci-123",
    appName: "my-app",
    framework: "other",
    locale: "pt",
    startedAt: new Date().toISOString(),
    finishedAt: new Date().toISOString(),
    tests: [
    {
      appName: "my-app",
      framework: "other",
      startedAt: "...",
      finishedAt: "...",
      describePath: ["Payment API", "pricing"],
      testName: "applies coupon to subtotal",
      status: "passed",
      duration: 12,
      errors: [],
    },
  ],
  },
  {
    webhookUrl: process.env.NZILA_WEBHOOK_URL!,
    apiKey: process.env.NZILA_API_KEY!,
    maxRetries: 3,
  },
);

Environment variables

# Required for test reporters (CI secrets)
NZILA_API_KEY=nzl_xxxxxxxx
NZILA_PROJECT_ID=00000000-0000-0000-0000-000000000000
NZILA_WEBHOOK_URL=https://your-nzila-host/api/webhooks/tests
NZILA_APP_NAME=my-app
NZILA_LOCALE=en

# Runtime signals (optional — Feature health)
NZILA_SIGNALS_URL=https://your-nzila-host/api/signals/runtime
NEXT_PUBLIC_NZILA_SIGNALS_URL=https://your-nzila-host/api/signals/runtime
NEXT_PUBLIC_NZILA_API_KEY=nzl_xxxxxxxx

# Debug reporter delivery (stderr)
# NZILA_DEBUG=1

Interactive dashboard guide

Each workspace section (Overview, Projects, Runs, Feature health, and the rest) has a step-by-step tour in your UI language.

  • The first time you open a section, the tour starts automatically and explains every control on that page.
  • Finish the last step (Done) to mark the section complete; closing early will show the tour again on your next visit.
  • Use Guide in the header anytime to replay the tour for the current page.

Authentication

Send your project API key on every request. Keys are tied to one project and can expire.

Authorization: Bearer nzl_your_api_key

Send a completed test run

Call this endpoint once per finished run (all tests in one JSON body). Use your Nzila host URL in production.

POST /api/webhooks/tests

Re-sending the same runId for the same project is safe — the API returns 200 and does not duplicate the run.

JSON body

  • runId — unique id from your CI or test runner (UUID recommended).
  • appName — must match the project's App name in Nzila.
  • framework — vitest, jest, mocha, playwright, jasmine, cypress, karma, node-test, or other.
  • startedAt / finishedAt — ISO 8601 timestamps for the whole run.
  • tests[] — each item: describePath, testName, status (passed | failed | skipped | pending), duration (ms), errors[{ message, stack? }].
  • locale (optional) — en, pt, fr, or zh: all AI summaries, failure analysis, and report outlines for that run are generated in this language.
  • Per test: optional feature override, context (e.g. skipReason for skipped tests).
{
  "runId": "ci-run-2026-05-16-abc123",
  "appName": "my-app",
  "framework": "vitest",
  "startedAt": "2026-05-16T14:00:00.000Z",
  "finishedAt": "2026-05-16T14:00:04.200Z",
  "locale": "pt",
  "tests": [
    {
      "describePath": ["LikesModal – desktop"],
      "testName": "renders Modal on desktop",
      "feature": "Social",
      "status": "passed",
      "duration": 120,
      "errors": []
    },
    {
      "describePath": ["ActivateAccountModal"],
      "testName": "calls reset on modal open",
      "status": "failed",
      "duration": 45,
      "errors": [
        {
          "message": "AssertionError: expected \"vi.fn()\" to be called 1 times, but got 0 times"
        }
      ]
    },
    {
      "describePath": ["Checkout UI", "coupons"],
      "testName": "skips when flag off",
      "status": "skipped",
      "duration": 0,
      "context": { "skipReason": "feature flag disabled" },
      "errors": []
    }
  ]
}

HTTP responses

  • 202 Run accepted and queued for metrics and insights.
  • 200Same runId already ingested (idempotent retry).
  • 401 / 403 Invalid, expired, or revoked key (codes API_KEY_INVALID, API_KEY_EXPIRED, API_KEY_REVOKED).
  • 400Invalid JSON or schema validation errors in the body.

Example (curl)

curl -X POST "$NZILA_WEBHOOK_URL/api/webhooks/tests" \
  -H "Authorization: Bearer $NZILA_API_KEY" \
  -H "Content-Type: application/json" \
  -d @run-payload.json

Test runners

Use the same webhook from any runner. Nzila ships reporters for Vitest, Jest, and Mocha; everything else can POST the JSON payload (Python, Go, .NET, etc.).

Playwright, Cypress, and Karma: export results after the run and POST with framework set to playwright, cypress, or karma, or use framework other.

npm install @nzila/sdk — reporters under @nzila/sdk/vitest, @nzila/sdk/jest, @nzila/sdk/mocha; CLI via npx @nzila/sdk.

Full Vitest, Jest, and Mocha examples are in the Install & configure section above.

Trace test failures to a feature

Every test is identified by describePath + testName (fingerprint). Map suites to product features, then follow failures from the dashboard back to the exact it() block and error output.

Fingerprint = suite path + test name

Nested describe() segments become describePath[]. The fingerprint is joined with › and shown in Stability and run details.

// Vitest — suite path becomes describePath[] in the webhook
describe("ActivateAccountModal", () => {
  it("calls reset, invalidates query and tracks on modal open", async () => {
    // ...
    expect(vi.fn()).toHaveBeenCalledTimes(1); // failure → message in errors[]
  });
});

// Dashboard fingerprint (stable id):
// ActivateAccountModal › calls reset, invalidates query and tracks on modal open

Trace a failed test (step by step)

  1. Run tests with the Nzila reporter and locale set (so failure text matches your team language).
  2. Open Test runs → pick the run → What was tested: grouped steps mirror describe() blocks.
  3. Click the status pill on a failed step for plain-language why, technical Vitest/Jest output, and bad-test hints (e.g. mock not called).
  4. Open Failure analysis for the same run — AI detail is stored per locale.
  5. In the repo, search for the fingerprint or describe title + it() name; fix the product or the test setup.

AssertionError and vi.fn() / toHaveBeenCalled failures are flagged as possible test issues, not only product bugs.

Attach tests to a feature

  • With the Nzila Vitest reporter, each test’s feature is auto-detected from the file name (e.g. activate-account-modal.test.tsx → Activate Account Modal) and describe() blocks.
  • You only need mapFeature when you want to override that default.
  • Optional: set feature on each test in a manual JSON payload.
import { defineConfig } from "vitest/config";
import { nzilaVitestReporter } from "@nzila/sdk/vitest";
import { reporterOptionsFromNzilaConfig } from "@nzila/sdk";
import nzilaConfig from "./nzila.config";

// Important: use nzilaVitestReporter(...) — never new NzilaVitestReporter()
// (Vitest worker pools cannot serialize class instances).

export default defineConfig({
  test: {
    reporters: [
      "default",
      nzilaVitestReporter(reporterOptionsFromNzilaConfig(nzilaConfig)),
    ],
  },
});

Where to trace in the dashboard

  1. Execution Overview — health and recent failures.
  2. Test runs — open a run; see every test status and label.
  3. Failure analysis — readable messages from failed tests (not raw stacks).
  4. Stability metrics — pass rate, flake, regressions per check.
  5. Features — aggregates by feature name.
  6. In your repo — match describePath and testName to describe / it blocks.
  7. Export PDF — same grouped steps and plain-language descriptions for stakeholders.

Runtime tracing (frontend and backend)

After tests are wired, instrument live code with the SDK. Call one entry at the top of the screen or API handler; use captureError in your own catch blocks. Signals use the same feature string as Vitest.

POST /api/signals/runtime

Initialize once (server or app bootstrap)

import { initNzilaRuntime } from "@nzila/sdk";

// Node / Route Handlers only — not at module scope in React
initNzilaRuntime({
  signalsUrl: process.env.NZILA_SIGNALS_URL!,
  apiKey: process.env.NZILA_API_KEY!,
  locale: "en",
});

React — useNzilaFeature at the top of the component

Wrap the app with NzilaProvider (do not call initNzilaRuntime at module scope in React). useNzilaFeature must be the first hook in components that own the feature — same string as mapFeature / describe.

"use client";
import { NzilaProvider } from "@nzila/sdk/react";

export function AppProviders({ children }: { children: React.ReactNode }) {
  return (
    <NzilaProvider
      signalsUrl={process.env.NEXT_PUBLIC_NZILA_SIGNALS_URL!}
      apiKey={process.env.NEXT_PUBLIC_NZILA_API_KEY!}
      locale="en"
    >
      {children}
    </NzilaProvider>
  );
}
"use client";
import { useNzilaFeature } from "@nzila/sdk/react";

export function CheckoutPage() {
  const nzila = useNzilaFeature("Checkout");

  async function pay() {
    try {
      await nzila.runApi("POST /api/checkout", () =>
        fetch("/api/checkout", { method: "POST" }),
      );
    } catch (err) {
      nzila.captureError(err, { step: "pay", handled: true });
    }
  }
}

Also detects likely render loops (too many re-renders), unhandled errors, and promise rejections while mounted.

Backend — traceNzilaFeature at the top of the handler

First line inside the route or service that matches your tested feature. Wrap outbound calls with runApi or call captureError in catch.

import { traceNzilaFeature } from "@nzila/sdk";

export async function POST(req: Request) {
  const nzila = traceNzilaFeature("Checkout");
  try {
    const res = await nzila.runApi("charge", () => charge(req));
    return Response.json({ ok: true, data: res });
  } catch (err) {
    nzila.captureError(err, { route: "POST /checkout" });
    return Response.json({ error: "failed" }, { status: 502 });
  }
}

Manual errors (shared helpers)

When you already handle the error (toast, 4xx response), still report it:

import { reportFeatureError } from "@nzila/sdk";

reportFeatureError("Checkout", error, { layer: "validation" });

Handle API

  • captureError(error, detail?) — any caught error (type: error).
  • captureApiError(error, label, detail?) — HTTP/upstream failures you caught without runApi.
  • runApi(label, fn) — wraps async calls; records api success/failure.
  • reportFeatureError(feature, error, detail?) — from utilities when you only have feature + error.

Open Feature health to compare test results with live api, ui (render_loop), and error signals for that feature.

Feature intelligence & execution observability

Nzila goes beyond pass/fail reporting: correlate tests with runtime signals, replay execution, detect regressions, and explain impact in plain language (en, pt, fr, zh).

DOM snapshot replay

Lightweight JSON snapshots (component tree, modals, toasts, loading). SDK 0.1.14+ captures on interaction when VESL auto-instrumentation is active; manual POST supported.

POST /api/signals/dom-snapshots
# Lightweight UI state (not video). Linked to runs via externalRunId / runId.

{
  "externalRunId": "same-as-webhook-runId",
  "snapshots": [{
    "feature": "Checkout",
    "route": "/checkout",
    "componentName": "PaymentStep",
    "snapshot": { "version": 1, "loading": false, "modals": [], "tree": [] }
  }]
}

Snapshots share externalRunId with the test run and appear in the replay panel when you scrub the timeline.

Regression intelligence

After each processed run, degraded features are compared to the last healthy run. Suspected deployments fall between healthy and degraded timestamps.

  • POST deployments from CI so regressions can name a commit/version.
  • Dashboard: Regression insights — summary, first degraded run, suspected component.
  • Root-cause hints are structured categories (navigation, cache, race) — not a chat UI.
curl -X POST "$NZILA_URL/api/deployments" \
  -H "Authorization: Bearer $NZILA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"version":"1.4.2","commitSha":"abc123","environment":"production"}'

Release health score

Aggregates feature_correlations into a health score and stable / at-risk / degraded lists. Recalculate from the Release health page after major deploys.

Flaky test detection

Stability metrics drive flake scores; the regression page shows a flaky leaderboard. Stability Metrics remains the full per-check history.

Failure triage

On Failure analysis and run failure cards: acknowledge flaky behavior or mark false positives. Activity is scoped to your organization and project.

POST /api/test-results/<resultId>/annotations — acknowledge_flaky | false_positive

Feature dependencies

Store edges between features (depends_on) via API or future SDK signals; view the dependency table under Dependencies.

CLI doctor & auto-repair

Diagnose missing Vitest reporter wiring and apply safe config patches with rollback.

npx @nzila/sdk doctor          # config + reporter diagnostics
npx @nzila/sdk repair --dry-run  # list fixable issues
npx @nzila/sdk repair --apply    # patch vitest.config (creates .nzila.bak)
npx @nzila/sdk repair --rollback # restore from backup

CI or custom HTTP client

Build the same JSON payload from any runner (GitHub Actions, GitLab, Jenkins, etc.) and POST after the suite finishes.

Run the worker on your Nzila deployment so ingestion is processed into overview, stability, and failure analysis.

Using the product after ingestion

Once a run is accepted, open the dashboard for that project:

  • Execution Overview — pass/fail counts, AI run summary, and recent runs.
  • Failure Analysis — friendly explanations for failed checks.
  • Stability Metrics — pass rate, flake score, and regression flags per test.
  • Performance Trends — duration deltas when historical data exists.
  • Switch projects in the header to compare apps or services separately.
  • Feature health — test vs runtime signals when you use useNzilaFeature or traceNzilaFeature.
  • Interactive Guide — first-visit tours per section; empty states explain what to do when a list has no data yet.
  • What was tested — describe() groups as suites with numbered steps and AI/plain descriptions.
  • PDF export — grouped steps per run for a date range, localized via payload/reporter locale.
  • Regression insights — degraded features, suspected deploys, flaky leaderboard.
  • Release health — portfolio score with stable, at-risk, and degraded feature lists.
  • Execution replay — human & developer views, phased timeline, Vitest step events, DOM frames.
  • Failure triage — acknowledge flaky tests or mark false positives on failures.

Full feature intelligence guide ↓

Language for insights

Set locale on the webhook payload, nzila.config.ts, or reporter options (en | pt | fr | zh). Nzila stores execution summaries and failure analysis per locale. The dashboard header language picks which locale to display; they should match for consistent AI copy.

Security

Never put API keys in browser bundles or public repos. Call the webhook from CI, a secure server, or your test runner process only.