@variantlab/react 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +169 -5
  2. package/package.json +5 -5
package/README.md CHANGED
@@ -1,11 +1,175 @@
1
1
  # @variantlab/react
2
2
 
3
- React hooks and components for variantlab.
3
+ > React hooks and components for variantlab — the universal, zero-dependency A/B testing toolkit.
4
4
 
5
- > **Status:** Phase 1 — Pre-alpha. Not ready for production use.
5
+ ![npm version](https://img.shields.io/npm/v/@variantlab/react/alpha?label=npm&color=blue)
6
+ ![bundle size](https://img.shields.io/badge/gzip-%3C2KB-brightgreen)
6
7
 
7
- ## Peer dependencies
8
+ ## Install
8
9
 
9
- - `react` `^18.2.0 || ^19.0.0`
10
+ ```bash
11
+ npm install @variantlab/core@alpha @variantlab/react@alpha
12
+ ```
10
13
 
11
- See the [root README](../../README.md) for project overview, motivation, and roadmap.
14
+ **Peer dependencies:** `react ^18.2.0 || ^19.0.0`
15
+
16
+ ## Quick start
17
+
18
+ ### 1. Create the engine and wrap your app
19
+
20
+ ```tsx
21
+ import { createEngine } from "@variantlab/core";
22
+ import { VariantLabProvider } from "@variantlab/react";
23
+ import experiments from "./experiments.json";
24
+
25
+ const engine = createEngine(experiments);
26
+
27
+ export default function App() {
28
+ return (
29
+ <VariantLabProvider engine={engine}>
30
+ <YourApp />
31
+ </VariantLabProvider>
32
+ );
33
+ }
34
+ ```
35
+
36
+ ### 2. Use hooks
37
+
38
+ ```tsx
39
+ import { useVariant, useVariantValue } from "@variantlab/react";
40
+
41
+ function HeroSection() {
42
+ // Get the assigned variant ID
43
+ const variant = useVariant("hero-layout"); // "centered" | "split"
44
+
45
+ return variant === "split" ? <SplitHero /> : <CenteredHero />;
46
+ }
47
+
48
+ function CheckoutButton() {
49
+ // Get a value experiment's value directly
50
+ const copy = useVariantValue<string>("cta-copy"); // "Buy now" | "Get started"
51
+
52
+ return <button>{copy}</button>;
53
+ }
54
+ ```
55
+
56
+ ### 3. Or use components
57
+
58
+ ```tsx
59
+ import { Variant, VariantValue } from "@variantlab/react";
60
+
61
+ function HeroSection() {
62
+ return (
63
+ <Variant experimentId="hero-layout" fallback={<CenteredHero />}>
64
+ {{
65
+ centered: <CenteredHero />,
66
+ split: <SplitHero />,
67
+ }}
68
+ </Variant>
69
+ );
70
+ }
71
+
72
+ function CheckoutButton() {
73
+ return (
74
+ <VariantValue experimentId="cta-copy">
75
+ {(value) => <button>{value}</button>}
76
+ </VariantValue>
77
+ );
78
+ }
79
+ ```
80
+
81
+ ## Hooks API
82
+
83
+ ### `useVariant(experimentId)`
84
+
85
+ Returns the assigned variant ID for a render experiment.
86
+
87
+ ```tsx
88
+ const variantId = useVariant("hero-layout"); // "centered" | "split"
89
+ ```
90
+
91
+ ### `useVariantValue<T>(experimentId)`
92
+
93
+ Returns the value of a value experiment.
94
+
95
+ ```tsx
96
+ const copy = useVariantValue<string>("cta-copy"); // "Buy now"
97
+ const price = useVariantValue<number>("pricing"); // 9.99
98
+ ```
99
+
100
+ ### `useExperiment(experimentId)`
101
+
102
+ Returns the full experiment state including metadata.
103
+
104
+ ```tsx
105
+ const { variantId, experiment, isOverridden } = useExperiment("hero-layout");
106
+ ```
107
+
108
+ ### `useSetVariant()`
109
+
110
+ Returns a function to override variant assignments (useful for debug UIs).
111
+
112
+ ```tsx
113
+ const setVariant = useSetVariant();
114
+ setVariant("hero-layout", "split"); // force split variant
115
+ ```
116
+
117
+ ### `useVariantLabEngine()`
118
+
119
+ Returns the engine instance directly.
120
+
121
+ ```tsx
122
+ const engine = useVariantLabEngine();
123
+ engine.resetAll();
124
+ ```
125
+
126
+ ### `useRouteExperiments()`
127
+
128
+ Returns experiments that target the current route.
129
+
130
+ ```tsx
131
+ const experiments = useRouteExperiments();
132
+ ```
133
+
134
+ ## Components
135
+
136
+ ### `<Variant>`
137
+
138
+ Renders the matching variant child by ID.
139
+
140
+ ```tsx
141
+ <Variant experimentId="hero-layout" fallback={<Default />}>
142
+ {{
143
+ centered: <CenteredHero />,
144
+ split: <SplitHero />,
145
+ }}
146
+ </Variant>
147
+ ```
148
+
149
+ ### `<VariantValue>`
150
+
151
+ Render-prop component for value experiments.
152
+
153
+ ```tsx
154
+ <VariantValue experimentId="cta-copy">
155
+ {(value) => <span>{value}</span>}
156
+ </VariantValue>
157
+ ```
158
+
159
+ ### `<VariantErrorBoundary>`
160
+
161
+ Error boundary with crash-rollback integration. If a variant crashes N times, the engine auto-reverts to the default variant.
162
+
163
+ ```tsx
164
+ <VariantErrorBoundary experimentId="hero-layout" fallback={<ErrorFallback />}>
165
+ <HeroSection />
166
+ </VariantErrorBoundary>
167
+ ```
168
+
169
+ ## Type safety with codegen
170
+
171
+ Run `npx variantlab generate` to generate TypeScript types from your `experiments.json`. Experiment IDs and variant IDs become literal types — typos become compile errors.
172
+
173
+ ## License
174
+
175
+ [MIT](./LICENSE)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@variantlab/react",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "React hooks and components for variantlab.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -40,18 +40,18 @@
40
40
  ],
41
41
  "repository": {
42
42
  "type": "git",
43
- "url": "git+https://github.com/variantlab/variantlab.git",
43
+ "url": "git+https://github.com/Minhaj-Rabby/variantlab.git",
44
44
  "directory": "packages/react"
45
45
  },
46
46
  "bugs": {
47
- "url": "https://github.com/variantlab/variantlab/issues"
47
+ "url": "https://github.com/Minhaj-Rabby/variantlab/issues"
48
48
  },
49
- "homepage": "https://github.com/variantlab/variantlab#readme",
49
+ "homepage": "https://github.com/Minhaj-Rabby/variantlab#readme",
50
50
  "engines": {
51
51
  "node": ">=18.17"
52
52
  },
53
53
  "dependencies": {
54
- "@variantlab/core": "0.1.0"
54
+ "@variantlab/core": "0.1.2"
55
55
  },
56
56
  "peerDependencies": {
57
57
  "react": "^18.2.0 || ^19.0.0"