ai-client

star 504

Conventions for the opentrons-ai-client React/TypeScript frontend — project structure, API integration, state management (Jotai), feature flags, types, and testing. Use when working with files in opentrons-ai-client/ or discussing the AI client application.

Opentrons By Opentrons schedule Updated 3/31/2026

name: ai-client description: Conventions for the opentrons-ai-client React/TypeScript frontend — project structure, API integration, state management (Jotai), feature flags, types, and testing. Use when working with files in opentrons-ai-client/ or discussing the AI client application.

AI Client Instructions

Overview

opentrons-ai-client is a React/TypeScript single-page application that generates and updates Opentrons protocols from natural language descriptions. It lives in the monorepo and is built with Vite.

Deployed environments: staging (staging.opentrons.ai) and prod (ai.opentrons.com).

Project Structure

opentrons-ai-client/
├── src/
│   ├── OpentronsAI.tsx           # Root component, Auth0 bootstrap, feature flag sync
│   ├── main.tsx                  # Auth0 provider, router, app entry
│   ├── analytics/                # Mixpanel event tracking
│   ├── assets/localization/en/   # i18next translation strings
│   ├── components/               # atoms/, molecules/, organisms/
│   ├── pages/                    # Chat, CreateProtocol, UpdateProtocol, Landing, Settings
│   ├── resources/
│   │   ├── atoms.ts              # Jotai atoms (app-wide state)
│   │   ├── constants.ts          # API base URLs and Auth0 config per environment
│   │   ├── types.ts              # Shared TypeScript types (ChatData, CreatePrompt, etc.)
│   │   ├── hooks/
│   │   │   ├── useInputPromptController.ts  # Main submit logic
│   │   │   ├── useGetAccessToken.ts         # Auth0 token fetching
│   │   │   ├── useApiCall.ts                # Axios wrapper (callApi, data, isLoading, error)
│   │   │   └── useAttachFiles.ts            # File attachment handling
│   │   └── utils/
│   │       ├── buildRequestConfig.ts        # Builds Axios config per endpoint type
│   │       ├── buildChatHistory.ts          # Formats chat history for the API
│   │       ├── createUserInput.ts           # Creates ChatData for user turns
│   │       ├── protocolUtils.ts             # Prompt builders for create/update
│   │       └── resolveErrorMessage.ts       # Maps API error_type to user-facing strings
│   └── feature-flags/            # Feature flag types and DEPRECATED_FLAGS cleanup
└── vite.config.mts

Types — Use camelCase Throughout

All types in src/resources/types.ts use camelCase field names. The API request/response bodies also use camelCase. Do not use snake_case for any new TypeScript types or API payload fields.

Key types:

Type Purpose
ChatData A single turn in the chat display (user or assistant)
Chat A history entry sent to the server (role, content, protocolContent)
CreatePrompt Atom shape for the create-protocol form state
UpdatePrompt Atom shape for the update-protocol form state

State Management (Jotai)

Key atoms in src/resources/atoms.ts:

Atom Purpose
chatDataAtom All turns displayed in the chat UI
chatHistoryAtom History sent to the server in API requests
createProtocolChatAtom Create-protocol form values
updateProtocolChatAtom Update-protocol form values
featureFlagsAtom Feature flags (persisted to localStorage)
feedbackModalAtom Whether the feedback modal is open

tokenAtom has been removed. Always use useGetAccessToken() to fetch a fresh token before making API calls.

API Integration

The client communicates with the server via a standard JSON HTTP API. Endpoint selection is handled in buildRequestConfig.ts.

Request type Endpoint
Update protocol (no files) POST /api/chat/update-protocol
Create protocol (no files) POST /api/chat/create-protocol
Chat completion (no files) POST /api/chat/completion
Chat completion (with files) POST /api/chat/completion-multipart

The useInputPromptController hook is the single entry point for all submissions. It:

  1. Calls getAccessToken() to get a fresh token before each request
  2. Calls buildRequestConfig() to assemble the Axios config
  3. Calls callApi(config) from useApiCall
  4. On completion, updates chatDataAtom and chatHistoryAtom

Authentication

  • Use useGetAccessToken() (not the removed tokenAtom) whenever a token is needed
  • getAccessToken() is async — always await it and wrap in try/catch
  • FeedbackModal and other components that POST independently also use useGetAccessToken()

Environment-Driven URLs

constants.ts exports endpoint constants for three environments (LOCAL_*, STAGING_*, PROD_*). buildRequestConfig.ts uses _NODE_ENV_ (a Vite define) via pickEndpoint() to select the right URL.

Feature Flags

Feature flags live in featureFlagsAtom and are persisted to localStorage. Flags listed in DEPRECATED_FLAGS (src/feature-flags/types.ts) are automatically cleaned up on startup.

User-facing flags are toggled on the Settings page. The enablePrereleaseMode flag is toggled via window.enablePrereleaseMode() in the browser console.

useEffect Exhaustive-Deps Convention

New code wraps useEffect callbacks in the multi-line form and adds a FIXME comment for any suppressed exhaustive-deps lint rule:

useEffect(
  () => {
    // ...
  },
  // FIXME(YYYY-MM-DD): Supply all missing dependencies, if it's safe. If it's unsafe, explain why.
  // eslint-disable-next-line react-hooks/exhaustive-deps
  [dep1, dep2]
)

Dev Commands

Run from the monorepo root:

make -C opentrons-ai-client dev     # Start Vite dev server
make test-js-opentrons-ai-client    # Run unit tests
make format-js                      # Prettier auto-fix
make lint-js                        # ESLint + Prettier check
make lint-css                       # Stylelint check
make check-js                       # TypeScript type check
Install via CLI
npx skills add https://github.com/Opentrons/opentrons --skill ai-client
Repository Details
star Stars 504
call_split Forks 204
navigation Branch main
article Path SKILL.md
More from Creator