Guidelines for AI coding agents working in this repository.
React + TypeScript + Vite frontend for Broxy MCP server management. Uses Tailwind CSS and Radix UI (shadcn/ui pattern). Deployed to Cloudflare Pages with PWA support.
npm run dev # Start dev server on port 3000
npm run build # Type-check and build (tsc -b && vite build)
npm run lint # Run ESLint on all files
npm run preview # Preview production build locally
npm run deploy # Build and deploy to Cloudflare PagesNote: No test framework is configured. Run lint and build before committing.
Order imports with blank line separators:
- React imports
- Third-party packages (Radix UI, Lucide icons, i18next)
- Local imports using
@/alias - Type-only imports last
import { useState, useEffect, useRef } from 'react';
import { Button } from '@/components/ui/button';
import { useToast } from '@/hooks/useToast';
import { Download, Settings, Code } from 'lucide-react';
import type { AppState } from '@/types';Always use @/ for src imports:
import { cn } from '@/lib/utils';
import type { Route } from '@/types';- Named exports only (no default exports):
export function ComponentName({ prop }: Props) { ... }
- Define props interface before component:
interface SettingsProps { state: AppState; actions: { saveConfig: (mcpConfig: any, initScript: string) => Promise<void>; }; }
- forwardRef components need displayName:
Button.displayName = 'Button';
- PascalCase for component files:
Settings.tsx,RouteEditorDialog.tsx
- Strict mode with
noUnusedLocals,noUnusedParameters,noFallthroughCasesInSwitch - Use
interfacefor object shapes,typefor unions/aliases - Use
import typefor type-only imports - Catch errors as
err: anyfor error.message access
- Tailwind CSS utilities only - no custom CSS classes
- Use
cn()for conditional class merging:className={cn('base-classes', condition && 'conditional-class')}
- CSS variables for theming (defined in index.css)
- Follow shadcn/ui patterns in
src/components/ui/
- Custom hooks in
src/hooks/withuseprefix - Use
useCallbackfor stable function references - Use
useReffor mutable values without re-renders
- ALL user-facing strings MUST use i18next
- Use
useLocale()hook:const { t } = useLocale(); return <span>{t('settings.title')}</span>;
- Translation files:
src/i18n/locales/en.json,src/i18n/locales/zh-CN.json - Add keys to BOTH locale files
- Interpolation:
t('toast.jsonParseFailed', { message: err.message })
- Use try/catch for async operations
- Display errors via toast notifications:
try { await actions.saveConfig(config); toast({ title: t('toast.saveSuccess'), variant: 'success' }); } catch (err: any) { toast({ title: t('toast.error'), description: err.message, variant: 'destructive' }); }
| Type | Convention | Example |
|---|---|---|
| Components | PascalCase | RoutesManager, CodeEditorDialog |
| Functions | camelCase | handleSave, formatDuration |
| Constants | SCREAMING_SNAKE_CASE | TOAST_LIMIT |
| Files | PascalCase (components), camelCase (hooks/utils) | useToast.ts |
- Use React built-in hooks (useState, useReducer, useContext)
- Lift state up when multiple components need it
- Prefer useReducer for complex state with typed actions
src/
components/ # React components
ui/ # Base UI components (shadcn/ui)
hooks/ # Custom hooks (useToast, useLocale, useTheme)
lib/ # Utility functions (cn)
types/ # TypeScript definitions (index.ts)
i18n/ # Internationalization
locales/ # Translation files (en.json, zh-CN.json)
- Target: ES2020, Module: ESNext with bundler resolution
- JSX: react-jsx, Strict mode enabled
- Path alias:
@/*maps to./src/*
- Uses
vite-plugin-pwafor offline caching - Service worker registered in main.tsx
- App icon at
public/icon.svg
- Cloudflare Pages via wrangler
- Use
npm run deployto build and deploy
- Run
npm run lint- fix all errors - Run
npm run build- must compile without errors - Add i18n keys to both en.json and zh-CN.json
- Verify both light and dark themes work
- Do NOT commit unless explicitly requested
- Never run
git pushwithout user request