opik-frontend

star 19.7k

React frontend patterns for Opik. Use when working in apps/opik-frontend, on components, state, or data fetching.

comet-ml By comet-ml schedule Updated 5/27/2026

name: opik-frontend description: React frontend patterns for Opik. Use when working in apps/opik-frontend, on components, state, or data fetching.

Opik Frontend

Architecture Decisions

  • Routing: TanStack Router (file-based)
  • Data fetching: TanStack Query (never raw fetch/useEffect)
  • State: Zustand for global, React state for local
  • Components: shadcn/ui + Radix UI base
  • Forms: React Hook Form + Zod validation

Critical Gotchas

Never useEffect for Data Fetching

// ❌ BAD
useEffect(() => {
  fetch('/api/data').then(setData);
}, []);

// ✅ GOOD
const { data } = useQuery({
  queryKey: ['data'],
  queryFn: fetchData,
});

Selective Memoization

// ✅ USE useMemo for: complex computations, large data transforms
const filtered = useMemo(() =>
  data.filter(x => x.status === 'active').map(transform),
  [data]
);

// ✅ USE useCallback for: functions passed to children
const handleClick = useCallback(() => doSomething(id), [id]);

// ❌ DON'T memoize: simple values, primitives, local functions
const name = data?.name ?? '';  // No useMemo needed

Zustand Selectors

// ✅ GOOD - specific selector
const selectedEntity = useEntityStore(state => state.selectedEntity);

// ❌ BAD - selecting entire store causes re-renders
const { selectedEntity, filters } = useEntityStore();

Layer Architecture

Shared layers (used by all versions)

ui → shared (one-way only)

Per-version layers

ui → shared → v1/pages-shared → v1/pages (one-way only) ui → shared → v2/pages-shared → v2/pages (one-way only)

Module boundaries

  • v1/ CANNOT import from v2/
  • v2/ CANNOT import from v1/
  • src/components/ is BLOCKED (old structure, no longer exists)
  • After modifying imports: npm run deps:validate

Shared component rules

  • Backward-compatible changes only
  • Must not be version-aware (use showProjectSelector={true} not isV2={true})
  • If behavior needs to change, create a new component instead

State Location Decisions

  • URL state: filters, pagination, selected items
  • Zustand: user preferences, cross-component state
  • React state: form inputs, UI toggles

Component Structure

const Component: React.FC<Props> = ({ prop }) => {
  // 1. State hooks
  // 2. Queries/mutations
  // 3. Memoization (only when needed)
  // 4. Event handlers

  if (isLoading) return <Loader />;
  if (error) return <ErrorComponent />;

  return <div>...</div>;
};

Query Patterns

// Query with params
const { data } = useQuery({
  queryKey: [ENTITY_KEY, params],
  queryFn: (context) => fetchEntity(context, params),
});

// Mutation with invalidation
const mutation = useMutation({
  mutationFn: updateEntity,
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: [ENTITY_KEY] });
  },
});

Reference Files

Install via CLI
npx skills add https://github.com/comet-ml/opik --skill opik-frontend
Repository Details
star Stars 19,668
call_split Forks 1,522
navigation Branch main
article Path SKILL.md
More from Creator