@datalyr/wizard 1.0.4 → 1.0.5

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.
@@ -132,9 +132,11 @@ Install and configure the Datalyr analytics SDK in the user's project. Complete
132
132
  | SDK | Use Case | Install Command |
133
133
  |-----|----------|-----------------|
134
134
  | @datalyr/web | Browser apps (React, Vue, Svelte, Next.js client) | npm install @datalyr/web |
135
- | @datalyr/api | Server-side (Next.js API routes, Express, Node) | npm install @datalyr/api |
135
+ | @datalyr/api | Server-side only (API routes, Express, Node) | npm install @datalyr/api |
136
136
  | @datalyr/react-native | React Native & Expo mobile apps | npm install @datalyr/react-native |
137
137
  | DatalyrSDK | Native iOS Swift apps | Swift Package Manager |
138
+
139
+ IMPORTANT: For most projects, you only need @datalyr/web. Do NOT install @datalyr/api unless the user explicitly needs server-side tracking.
138
140
  </sdks>
139
141
 
140
142
  <rules>
@@ -143,40 +145,140 @@ Install and configure the Datalyr analytics SDK in the user's project. Complete
143
145
  3. MATCH the project's code style (indentation, quotes, semicolons)
144
146
  4. USE TypeScript if the project uses TypeScript
145
147
  5. PLACE initialization in the correct entry point for the framework
146
- 6. UPDATE .env or .env.local with NEXT_PUBLIC_DATALYR_WORKSPACE_ID
148
+ 6. UPDATE .env or .env.local with the correct env var name for the framework
147
149
  7. CHECK for existing Datalyr setup first - don't duplicate
150
+ 8. ONLY install @datalyr/web unless server-side tracking is explicitly needed
148
151
  </rules>
149
152
 
153
+ <critical-nextjs-rules>
154
+ NEXT.JS APP ROUTER REQUIRES SPECIAL HANDLING:
155
+
156
+ 1. SERVER VS CLIENT COMPONENTS:
157
+ - By default, all components in app/ directory are Server Components
158
+ - Server Components CANNOT use: useEffect, useState, useRef, onClick, or any browser APIs
159
+ - To use these, you MUST add 'use client' directive at the TOP of the file
160
+
161
+ 2. THE 'use client' DIRECTIVE:
162
+ - MUST be the FIRST line of the file (before any imports)
163
+ - Makes the component and all its children Client Components
164
+ - Required for any component that uses React hooks or browser APIs
165
+
166
+ 3. THE PROVIDER PATTERN (REQUIRED FOR NEXT.JS APP ROUTER):
167
+ - Create a separate Client Component file for the provider
168
+ - The layout.tsx stays as a Server Component
169
+ - Import and use the provider inside layout.tsx
170
+
171
+ 4. WINDOW/DOCUMENT CHECKS:
172
+ - Even in Client Components, code runs on server first for SSR
173
+ - useEffect is the safest way to run client-only code
174
+ - Never access window/document outside of useEffect
175
+
176
+ CORRECT PATTERN:
177
+ - app/providers.tsx -> 'use client' + DatalyrProvider with useEffect
178
+ - app/layout.tsx -> Server Component that imports and wraps with DatalyrProvider
179
+ </critical-nextjs-rules>
180
+
150
181
  <workflow>
151
182
  Step 1: Read package.json to detect framework and package manager
152
183
  Step 2: List files to find entry points (app/layout.tsx, src/main.tsx, App.tsx, etc.)
153
184
  Step 3: Read entry point files to understand current structure
154
- Step 4: Install SDK packages using detected package manager
155
- Step 5: Create initialization file (lib/datalyr.ts or similar)
185
+ Step 4: Install SDK package using detected package manager (usually just @datalyr/web)
186
+ Step 5: Create initialization file (for Next.js App Router: app/providers.tsx with 'use client')
156
187
  Step 6: Update entry point to import and initialize Datalyr
157
- Step 7: Update or create .env.local with workspace ID placeholder
188
+ Step 7: Update or create .env.local with workspace ID
158
189
  Step 8: Call task_complete with summary of changes
159
190
  </workflow>
160
191
 
161
192
  <examples>
162
193
  <example name="nextjs-app-router">
163
- For Next.js 13+ with App Router, create app/providers.tsx:
194
+ For Next.js 13+ with App Router:
195
+
196
+ STEP 1: Create app/providers.tsx (Client Component):
164
197
  \`\`\`tsx
165
198
  'use client';
199
+
166
200
  import datalyr from '@datalyr/web';
167
201
  import { useEffect } from 'react';
168
202
 
169
203
  export function DatalyrProvider({ children }: { children: React.ReactNode }) {
170
204
  useEffect(() => {
205
+ // useEffect only runs on client, safe to initialize here
171
206
  datalyr.init({
172
207
  workspaceId: process.env.NEXT_PUBLIC_DATALYR_WORKSPACE_ID!,
173
208
  debug: process.env.NODE_ENV === 'development',
174
209
  });
175
210
  }, []);
211
+
176
212
  return <>{children}</>;
177
213
  }
178
214
  \`\`\`
179
- Then wrap children in app/layout.tsx with <DatalyrProvider>.
215
+
216
+ STEP 2: Update app/layout.tsx (stays as Server Component):
217
+ \`\`\`tsx
218
+ import { DatalyrProvider } from './providers';
219
+
220
+ export default function RootLayout({
221
+ children,
222
+ }: {
223
+ children: React.ReactNode;
224
+ }) {
225
+ return (
226
+ <html lang="en">
227
+ <body>
228
+ <DatalyrProvider>
229
+ {children}
230
+ </DatalyrProvider>
231
+ </body>
232
+ </html>
233
+ );
234
+ }
235
+ \`\`\`
236
+
237
+ STEP 3: Add to .env.local:
238
+ \`\`\`
239
+ NEXT_PUBLIC_DATALYR_WORKSPACE_ID=your_workspace_id
240
+ \`\`\`
241
+
242
+ CRITICAL: The 'use client' directive MUST be at the very top of providers.tsx, before any imports!
243
+ </example>
244
+
245
+ <example name="nextjs-pages-router">
246
+ For Next.js Pages Router (pages/ directory):
247
+
248
+ STEP 1: Create lib/datalyr.ts:
249
+ \`\`\`ts
250
+ import datalyr from '@datalyr/web';
251
+
252
+ let initialized = false;
253
+
254
+ export function initDatalyr() {
255
+ if (initialized || typeof window === 'undefined') return;
256
+
257
+ datalyr.init({
258
+ workspaceId: process.env.NEXT_PUBLIC_DATALYR_WORKSPACE_ID!,
259
+ debug: process.env.NODE_ENV === 'development',
260
+ });
261
+
262
+ initialized = true;
263
+ }
264
+
265
+ export { datalyr };
266
+ \`\`\`
267
+
268
+ STEP 2: Update pages/_app.tsx:
269
+ \`\`\`tsx
270
+ import { useEffect } from 'react';
271
+ import { initDatalyr } from '../lib/datalyr';
272
+ import type { AppProps } from 'next/app';
273
+
274
+ export default function App({ Component, pageProps }: AppProps) {
275
+ useEffect(() => {
276
+ initDatalyr();
277
+ }, []);
278
+
279
+ return <Component {...pageProps} />;
280
+ }
281
+ \`\`\`
180
282
  </example>
181
283
 
182
284
  <example name="react-vite">
@@ -197,7 +299,16 @@ export function initDatalyr() {
197
299
 
198
300
  export { datalyr };
199
301
  \`\`\`
200
- Then call initDatalyr() at the top of src/main.tsx.
302
+
303
+ Update src/main.tsx:
304
+ \`\`\`tsx
305
+ import { initDatalyr } from './lib/datalyr';
306
+
307
+ // Initialize before rendering
308
+ initDatalyr();
309
+
310
+ // ... rest of app
311
+ \`\`\`
201
312
  </example>
202
313
 
203
314
  <example name="react-native">
@@ -205,20 +316,66 @@ For React Native, create src/utils/datalyr.ts:
205
316
  \`\`\`ts
206
317
  import { Datalyr } from '@datalyr/react-native';
207
318
 
208
- export async function initDatalyr(apiKey: string) {
319
+ let initialized = false;
320
+
321
+ export async function initDatalyr() {
322
+ if (initialized) return;
323
+
324
+ const apiKey = process.env.DATALYR_API_KEY;
325
+ if (!apiKey) {
326
+ console.warn('[Datalyr] API key not configured');
327
+ return;
328
+ }
329
+
209
330
  await Datalyr.initialize({
210
331
  apiKey,
211
332
  enableAutoEvents: true,
212
333
  debug: __DEV__,
213
334
  });
335
+
336
+ initialized = true;
214
337
  }
215
338
 
216
339
  export { Datalyr };
217
340
  \`\`\`
218
- Then call initDatalyr() in App.tsx useEffect.
341
+
342
+ Update App.tsx:
343
+ \`\`\`tsx
344
+ import { useEffect } from 'react';
345
+ import { initDatalyr } from './src/utils/datalyr';
346
+
347
+ export default function App() {
348
+ useEffect(() => {
349
+ initDatalyr();
350
+ }, []);
351
+
352
+ return (/* your app */);
353
+ }
354
+ \`\`\`
219
355
  </example>
220
356
  </examples>
221
357
 
358
+ <common-mistakes>
359
+ AVOID THESE MISTAKES:
360
+
361
+ 1. WRONG: Adding useEffect directly in layout.tsx without 'use client'
362
+ This will error: "useEffect only works in Client Components"
363
+
364
+ 2. WRONG: Putting 'use client' after imports
365
+ The directive MUST be the first line of the file
366
+
367
+ 3. WRONG: Trying to access window/document at module level
368
+ Always use useEffect or check typeof window !== 'undefined'
369
+
370
+ 4. WRONG: Installing @datalyr/api when only client tracking is needed
371
+ Most apps only need @datalyr/web
372
+
373
+ 5. WRONG: Using the wrong env var prefix
374
+ - Next.js: NEXT_PUBLIC_
375
+ - Vite: VITE_
376
+ - SvelteKit: PUBLIC_
377
+ </common-mistakes>
378
+
222
379
  <signals>
223
380
  When complete: ${AGENT_SIGNALS.SUCCESS}
224
381
  On error: ${AGENT_SIGNALS.ERROR_FAILED}
@@ -370,7 +527,6 @@ function getSDKsForFramework(framework) {
370
527
  case "sveltekit":
371
528
  case "nuxt":
372
529
  case "astro":
373
- return ["@datalyr/web", "@datalyr/api"];
374
530
  case "react":
375
531
  case "react-vite":
376
532
  case "svelte":
@@ -1008,17 +1164,12 @@ var NEXTJS_CONFIG = {
1008
1164
  id: "nextjs",
1009
1165
  name: "Next.js",
1010
1166
  detectPackage: "next",
1011
- sdks: ["@datalyr/web", "@datalyr/api"],
1167
+ sdks: ["@datalyr/web"],
1012
1168
  envVars: [
1013
1169
  {
1014
1170
  key: "NEXT_PUBLIC_DATALYR_WORKSPACE_ID",
1015
1171
  description: "Your Datalyr workspace ID",
1016
1172
  isPublic: true
1017
- },
1018
- {
1019
- key: "DATALYR_API_KEY",
1020
- description: "Server-side API key",
1021
- isPublic: false
1022
1173
  }
1023
1174
  ],
1024
1175
  estimatedTime: 3,
@@ -1083,17 +1234,12 @@ var SVELTEKIT_CONFIG = {
1083
1234
  id: "sveltekit",
1084
1235
  name: "SvelteKit",
1085
1236
  detectPackage: "@sveltejs/kit",
1086
- sdks: ["@datalyr/web", "@datalyr/api"],
1237
+ sdks: ["@datalyr/web"],
1087
1238
  envVars: [
1088
1239
  {
1089
1240
  key: "PUBLIC_DATALYR_WORKSPACE_ID",
1090
1241
  description: "Your Datalyr workspace ID",
1091
1242
  isPublic: true
1092
- },
1093
- {
1094
- key: "DATALYR_API_KEY",
1095
- description: "Server-side API key",
1096
- isPublic: false
1097
1243
  }
1098
1244
  ],
1099
1245
  estimatedTime: 3,
@@ -1146,17 +1292,12 @@ var NUXT_CONFIG = {
1146
1292
  id: "nuxt",
1147
1293
  name: "Nuxt",
1148
1294
  detectPackage: "nuxt",
1149
- sdks: ["@datalyr/web", "@datalyr/api"],
1295
+ sdks: ["@datalyr/web"],
1150
1296
  envVars: [
1151
1297
  {
1152
1298
  key: "NUXT_PUBLIC_DATALYR_WORKSPACE_ID",
1153
1299
  description: "Your Datalyr workspace ID",
1154
1300
  isPublic: true
1155
- },
1156
- {
1157
- key: "DATALYR_API_KEY",
1158
- description: "Server-side API key",
1159
- isPublic: false
1160
1301
  }
1161
1302
  ],
1162
1303
  estimatedTime: 3,
@@ -1171,17 +1312,12 @@ var REMIX_CONFIG = {
1171
1312
  id: "remix",
1172
1313
  name: "Remix",
1173
1314
  detectPackage: "@remix-run/react",
1174
- sdks: ["@datalyr/web", "@datalyr/api"],
1315
+ sdks: ["@datalyr/web"],
1175
1316
  envVars: [
1176
1317
  {
1177
1318
  key: "DATALYR_WORKSPACE_ID",
1178
1319
  description: "Your Datalyr workspace ID",
1179
1320
  isPublic: true
1180
- },
1181
- {
1182
- key: "DATALYR_API_KEY",
1183
- description: "Server-side API key",
1184
- isPublic: false
1185
1321
  }
1186
1322
  ],
1187
1323
  estimatedTime: 3,