Next.js
Start the local hub and load the client before the app runs.
init adds GenieScript to the root layout and creates instrumentation.ts. This is a Next.js
App Router setup. TanStack Router is not installed or used.
import { GenieScript } from 'genie-react/next'
import type { ReactNode } from 'react'
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body>
<GenieScript />
{children}
</body>
</html>
)
}export async function register(): Promise<void> {
if (
process.env.NODE_ENV !== 'production' &&
process.env.NEXT_RUNTIME === 'nodejs'
) {
const { registerGenie } = await import('genie-react/next')
await registerGenie()
}
}This loads the core session, React, memory, performance, and timeline tools. Query tools require the separate registration below. The timeline initially has browser request and React lanes; inspect its lane availability before expecting Query or Router events.
Add Query tools
Skip this section when the app does not use TanStack Query.
Use the same client that your existing QueryClientProvider owns. The minimal example below creates
one browser client. Preserve your app's existing per-request server client and hydration setup if it
already has one:
'use client'
import { QueryClient } from '@tanstack/react-query'
export const queryClient = new QueryClient()Register Query tools on the client started by GenieScript:
'use client'
import { queryCollector } from 'genie-react/collectors/query'
import { registerGenieCollector } from 'genie-react/protocol'
import { useEffect } from 'react'
import { queryClient } from './query-client'
export function GenieQueryTools() {
useEffect(() => {
if (process.env.NODE_ENV === 'production') return
return registerGenieCollector(queryCollector(queryClient))
}, [])
return null
}Render it after GenieScript:
import { GenieScript } from 'genie-react/next'
import type { ReactNode } from 'react'
import { GenieQueryTools } from './genie-query-tools'
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body>
<GenieScript />
<GenieQueryTools />
{children}
</body>
</html>
)
}Use the same client in the page that owns the Query provider:
'use client'
import { QueryClientProvider } from '@tanstack/react-query'
import type { ReactNode } from 'react'
import { queryClient } from './query-client'
export function QueryPage({ children }: { children: ReactNode }) {
return (
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
)
}Check Query tools
Keep the Next.js development server running in one terminal, open the app, and check it from another:
pnpm devOpen the page that mounts the Query provider and has fetched at least one query. Add
?_genie=next-check to its URL. The repository demo uses
http://localhost:3000/query-demo?_genie=next-check.
export GENIE_SESSION=next-check
status_json="$(npx @genie-react/cli status)"
tools_json="$(npx @genie-react/cli tools)"
query_json="$(npx @genie-react/cli call query_list '{"limit":10}')"
jq '{
connected,
ready,
sessionId,
domains,
toolCount
}' <<<"$status_json"
jq '{app, total, query: [.groups[] | select(.group == "query")]}' \
<<<"$tools_json"
jq '{queries, total}' <<<"$query_json"
jq -e '
.connected and .ready and
((.domains | index("query")) != null)
' <<<"$status_json" >/dev/null
jq -e '
any(.groups[]; .group == "query" and (.tools | index("query_list") != null))
' <<<"$tools_json" >/dev/null
jq -e '
.total > 0 and
any(.queries[]; .status == "success" and .observerCount > 0)
' <<<"$query_json" >/dev/null
unset GENIE_SESSION query_json status_json tools_jsonExample selected fields, with formatting added for readability:
{
"connected": true,
"ready": true,
"domains": ["session", "react", "memory", "perf", "timeline", "query"]
}{
"queries": [
{
"queryHash": "[\"greeting\"]",
"queryKey": ["greeting"],
"status": "success",
"fetchStatus": "idle",
"isActive": true,
"observerCount": 1
}
],
"total": 1
}The first assertion checks the supported status fields. The second checks the separate tool
inventory. A query domain plus query_list proves that the runtime received the Query collector.
Both components import the same queryClient. No TanStack Router package, provider, or runtime is
involved. Router tools do not appear in this setup.