Skill: FNF React

Use this when the task touches @higgsfield/fnf-react: React providers, TanStack Query options, generation run controllers, attachments, profile queries, workspace switching, cache keys, or request previews.

Before coding, read app/packages/fnf-react/ai/AGENTS.md and, for model contracts, app/packages/fnf/ai/AGENTS.md. For generated apps with real generation/media/ profile/credits, also read references/auth.md. For the visible UI around these hooks, also read app/packages/quanta/ai/AGENTS.md and references/quanta-design.md.

Package Philosophy

Provider Shape

Use QueryClientProvider above the website, then FnfProvider where SDK clients are needed.

For real SDK-backed generation/media/profile/credits, render FnfProvider only inside an authenticated website boundary or pass clients that call authenticated server functions. Signed-out users should see sign-in UI, not active generation controls.

This boundary means Higgsfield auth, not the generated website's own local sign-in. If the website also has in-app accounts for its product data, keep those sessions separate. FnfProvider and every SDK-backed route still require /api/user and server-side https://fnf.internal/user guards.

import { FnfProvider } from '@higgsfield/fnf-react'

<FnfProvider
  adapter={adapter}
  jobs={jobs}
  mediaAdapter={adapter}
  profileAdapter={adapter}
  scopeKey={workspaceId}
>
  {children}
</FnfProvider>

Provider hooks:

Keep adapter, jobs, blobUploader, resolveJob, and observability references stable. Do not create a new adapter or new job array on every render.

Cache Rules

Common query helpers:

characterQueryOptions(characterClient, characterId, { scopeKey })
referenceQueryOptions(referenceClient, elementId, { scopeKey })
referencesQueryOptions(referenceClient, { category: 'character' }, { scopeKey })
generationQueryOptions(jobClient, id, { scopeKey })
jobSetQueryOptions(jobClient, jobSetId, { scopeKey })
jobsFeedQueryOptions(jobClient, { type: 'image', size: 20 }, { scopeKey })
profileSnapshotQueryOptions(profileClient, { scopeKey })
profileCreditsQueryOptions(profileClient, { scopeKey, includeOnDemand: true })
costQueryOptions(jobClient, input, { scopeKey, enabled })
realtimeChainCostQueryOptions(realtimeClient, input, { scopeKey, enabled })
realtimeCustomStylesQueryOptions(realtimeClient, query, { scopeKey, enabled })

The realtime query helpers cache read-only cost estimates and saved-style pages. Run editChain, finalizeChain, and style mutations through the realtime client and the authenticated server boundary; after a style mutation, invalidate the matching fnfKeys.realtime({ scopeKey }) subtree. Poll edit results with getEditJob / pollEditJob and render their normal Generation shape. Workspace switching clears the previous scope's realtime cache. Full contract: references/fnf-sdk.md → "Stateful realtime image editing and saved custom styles".

For Elements and character workflows, use referencesQueryOptions for the Elements picker and characterQueryOptions to poll newly trained characters. After training completes, invalidate the matching fnfKeys.references(...) query so the new Character Element appears. The Element id and reference.characterId are different; Soul generation uses characterId as settings.customReferenceId. Full server recipe: references/fnf-sdk.md → "Elements and custom-reference character training".

Use flattenFeedPages with infinite feeds. Use applyGenerations, prependGenerations, and removeGenerationQueries for generation cache writes. Do not call queryClient.setQueryData on generation caches directly unless the package guide documents the exact helper path.

For any model form generated from a prompt, the default React structure is:

If the website uses SDK generation and lacks a feed/history view, treat it as incomplete.

Generation Feed And Preview Rendering

For SDK-backed generators, React UI must handle both the submit lifecycle and the historical feed:

import { HiggsfieldGenerationCard } from "@/components/higgsfield-generation-card"
import { jobsFeedQueryOptions, flattenFeedPages, useGenerationRun } from "@higgsfield/fnf-react"

Required behavior:

Never render a completed generation as a blank rectangle that only says completed or only shows an id. That means the website ignored SDK Generation.results or the backend response was not normalized correctly.

Request Helpers

useGenerationRun is the right default for generator screens:

useAttachments is the right default for upload controls:

Profile And Workspace

Use profile query options for profile/credits/workspace panels. Use useSwitchWorkspaceMutation or switchWorkspaceMutationOptions for backend context switching. On success, update host auth/session/router state if needed; the package only updates SDK/profile caches and clears scoped generation data.

Client Boundary

Use fnf-react in client React code only after the server has provided a safe adapter/proxy boundary. Browser components must not receive fnf service secrets or raw backend credentials.

When in doubt, keep privileged fnf work in a TanStack server function and let client components call that app-local server function.

For generated websites, browser auth display should use /api/user from references/auth.md. Do not use fnf-react profile queries as a replacement for the app-local auth proxy unless the adapter is explicitly safe for browser use.

Auth enforcement rule: