opik-frontend
Provides architectural guidelines and best practices for the Opik React frontend codebase.
Install
mkdir -p .claude/skills/opik-frontend && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/814" && unzip -o skill.zip -d .claude/skills/opik-frontend && rm skill.zipInstalls to .claude/skills/opik-frontend
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
React frontend patterns for Opik. Use when working in apps/opik-frontend, on components, state, or data fetching.Key capabilities
- →Fetch data using TanStack Query
- →Build components with shadcn/ui and Radix UI
- →Validate forms with React Hook Form and Zod
- →Apply selective memoization with useMemo and useCallback
How it works
The skill enforces specific patterns for data fetching using TanStack Query, state management with Zustand, and component creation with shadcn/ui, ensuring consistency and performance.
Inputs & outputs
When to use opik-frontend
- →Implementing efficient data fetching
- →Managing global state with Zustand
- →Applying consistent component architecture
- →Refactoring legacy useEffect fetching
About this skill
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();
Browser Translation Safety (Google Translate)
Many users auto-translate the page; the translator wraps text nodes in <font> elements, so React throws NotFoundError: removeChild when it reconciles a bare dynamic text node it re-parented. Wrap dynamic/conditional strings in their own element instead of rendering bare text.
// ❌ bare dynamic text → crash under translation
<button>{icon}{label}</button>
// ✅ wrap it → React swaps a stable element, stays translatable
<button>{icon}<span>{label}</span></button>
For timer-driven text (typewriter/counter), also avoid per-tick setState — write into a ref'd node's textContent (React never reconciles it), or mark a decorative node translate="no". Ref: facebook/react#11538 (OPIK-7428, OPIK-7435).
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}notisV2={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
- forms.md - React Hook Form + Zod patterns
- ui-components.md - Button variants, typography, dark theme
- responsive-design.md - Tailwind breakpoints vs useIsPhone
- testing.md - When to test, Vitest patterns
- code-quality.md - Lodash imports, naming, deps:validate
- performance.md - Bundle optimization, rendering, memoization
- permissions.md -
usePermissions()guard guidance for UI actions
When not to use it
- →For simple values or primitives that do not require memoization
- →For local functions that are not passed to children components
- →When importing from different version layers (e.g., v1 from v2)
Limitations
- →Cannot use raw fetch or useEffect for data fetching
- →Cannot import from `src/components/`
- →Shared components must be backward-compatible and not version-aware
How it compares
This skill provides a defined architectural framework for Opik's frontend development, preventing ad-hoc implementations like raw useEffect for data fetching and promoting selective memoization.
Compared to similar skills
opik-frontend side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| opik-frontend (this skill) | 3 | 2mo | No flags | Intermediate |
| accessibility-compliance | 45 | 2mo | No flags | Intermediate |
| frontend-code-review | 11 | 2mo | No flags | Advanced |
| feature-flags | 6 | 6mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by comet-ml
View all by comet-ml →You might also like
accessibility-compliance
wshobson
Implement WCAG 2.2 compliant interfaces with mobile accessibility, inclusive design patterns, and assistive technology support. Use when auditing accessibility, implementing ARIA patterns, building for screen readers, or ensuring inclusive user experiences.
frontend-code-review
langgenius
Trigger when the user requests a review of frontend files (e.g., `.tsx`, `.ts`, `.js`). Support both pending-change reviews and focused file reviews while applying the checklist rules.
feature-flags
Use when feature flag tests fail, flags need updating, understanding @gate pragmas, debugging channel-specific test failures, or adding new flags to React.
react-useeffect
jarrodwatts
React useEffect best practices from official docs. Use when writing/reviewing useEffect, useState for derived values, data fetching, or state synchronization. Teaches when NOT to use Effect and better alternatives.
react-ui-patterns
ChrisWiles
Modern React UI patterns for loading states, error handling, and data fetching. Use when building UI components, handling async data, or managing UI states.
fullstack-guardian
Jeffallan
Use when implementing features across frontend and backend, building APIs with UI, or creating end-to-end data flows. Invoke for feature implementation, API development, UI building, cross-stack work.