Showing {{ previewCount }} items.
+ + +``` + +Vue templates unwrap refs. In JavaScript, use `.value` inside a render function or computed expression; copying `.value` into a plain variable loses reactivity. A lookup maps each literal variant to another typed value: + +```ts +const { variant: buttonText, onAct } = sdk.useAbby("welcome", { + calm: "Take a look", + bright: "Explore now", +}); +``` + +`useFeatureFlags()` and `useRemoteConfigVariables()` return computed lists. `useAbby()` emits PING when a mounted selection becomes available or changes; `onAct()` sends ACT for the current raw variant, including when a lookup is used. Neither sends during SSR or before mount. The real SDK uses the core's telemetry transport; the local demo intercepts it separately. + +## Imperative access and updates + +Getters return snapshots, not refs. They resolve the nearest runtime in setup. Outside injection context, pass the **installed Vue app** explicitly; there is no implicit global client: + +```ts +// In setup: +const client = sdk.useAbbyClient(); +const choices = sdk.getVariants("welcome"); +const resetWelcome = sdk.getABResetFunction("welcome"); + +// Safe to use the captured client in a later component event handler: +const toggle = () => client.updateFlag("showDetails", !client.getFeatureFlag("showDetails")); + +// Outside setup, after plugin installation: +sdk.getFeatureFlagValue("showDetails", app); +sdk.getRemoteConfig("headline", app); +sdk.getABTestValue("welcome", undefined, app); // undefined until client mount +sdk.getABTestValue("welcome", { calm: "A", bright: "B" }, app); +sdk.getVariants("welcome", app); +sdk.getABResetFunction("welcome", app)(); +sdk.useAbbyClient(app); +``` + +`updateUserProperties(properties, app?)` accepts properties declared by the core config's `user` validators and recalculates rules. `enableCookies(app?)`, `disableCookies(app?)`, and `loadProjectData(app?)` also resolve an injected runtime or the explicit app. Prefer the SDK cookie helpers over direct core consent calls so Vue snapshots and storage cleanup stay coordinated. + +The exposed core supports `init`, `updateFlag`, `updateRemoteConfig`, and other existing core methods; notifications update mounted composables. `updateLocalVariant` is a **development override** in core, not a production experiment-assignment API. `withDevtools(factory, options?)` accepts a factory with `create({ abby, ...options })` returning an optional cleanup function; it does not add a devtools UI dependency. It shows only in development unless `dangerouslyForceShow` is enabled. + +## SSR, Nuxt, cookies, and cleanup + +- Every app installation and every provider owns a distinct core and cloned configuration/data. Never place a mutable per-request core or user properties in a server singleton. +- A/B variants are `undefined` during SSR and the initial hydration render, then become available after client mount. Render the same placeholder on both sides. Feature flags and remote configuration use the supplied initial data or configured defaults. +- SSR does not automatically fetch, access browser storage, or send events. Without initial data, the client loads project data after mount. With initial data, give server and client the same public payload. +- Variant persistence uses project-scoped cookies when enabled. Configure consent for your application; `disableCookies` clears this runtime's known values and records disabled consent. Reset helpers clear the selected test's stored assignment; they do not promise a different next variant. No HttpOnly cookie can be read by this client SDK. +- Cookie-based `Number` remote-config overrides accept finite integers only. Decimal and exponent strings are ignored before reaching core's legacy integer parser, which would otherwise truncate them. This cookie-override restriction does not apply to numeric values supplied in `initialData` or project-data responses. +- Component/effect-scope subscriptions stop on disposal. Provider unmount and `app.unmount()` dispose their owned runtimes; devtools cleanup runs on unmount. Do not keep using a disposed runtime. + +This is a **Nuxt plugin integration example**, not a shipped Nuxt module or a claim that a Nuxt application test suite has run: + +```ts +// plugins/abby.ts — runs once for each Nuxt app/request, not at module scope. +import { defineNuxtPlugin, useState } from "#app"; +import type { AbbyDataResponse } from "@tryabby/core"; +import { createAbby } from "@tryabby/vue"; + +export default defineNuxtPlugin((nuxtApp) => { + const sdk = createAbby({ + projectId: "your-public-project-id", + environments: ["production"], + currentEnvironment: "production", + flags: ["showDetails"], + tests: { welcome: { variants: ["calm", "bright"] } }, + remoteConfig: { headline: "String" }, + cookies: { disableByDefault: true }, + }); + + // A host-controlled server loader may populate this with public Abby data. + // useState serializes it for hydration: never put secrets/user profiles here. + const initialData = useState