Best Practices
Code Organization
Section titled “Code Organization”Directory Structure
Section titled “Directory Structure”packages/plugins/my-plugin/├── src/│ ├── components/ # UI components│ ├── server/ # tRPC routers│ ├── hooks/ # Custom hooks│ ├── lib/ # Utilities│ ├── types.ts # TypeScript types│ ├── manifest.ts # Plugin manifest│ └── index.ts # ExportsComponent Organization
Section titled “Component Organization”- One component per file
- Export from index.ts
- Group related components in subdirectories
- Use TypeScript for all code
Performance
Section titled “Performance”Optimize Queries
Section titled “Optimize Queries”// ✅ GOOD: Fetch only what you needconst { data } = trpc.timer.getEntries.useQuery({ workUnitId, select: ['id', 'startTime', 'duration'], limit: 50,});
// ❌ BAD: Fetch all dataconst { data } = trpc.timer.getAllData.useQuery();Memoize Expensive Calculations
Section titled “Memoize Expensive Calculations”const expensiveValue = useMemo(() => { return calculateComplexMetric(data);}, [data]);Debounce User Input
Section titled “Debounce User Input”const [searchQuery, setSearchQuery] = useState('');const debouncedSearch = useDebouncedValue(searchQuery, 300);
useEffect(() => { performSearch(debouncedSearch);}, [debouncedSearch]);Error Handling
Section titled “Error Handling”export function MyComponent() { const { data, isLoading, error } = trpc.getData.useQuery();
if (isLoading) return <Loader />;
if (error) { return ( <Alert color="error"> Failed to load data: {error.message} </Alert> ); }
return <DataDisplay data={data} />;}Type Safety
Section titled “Type Safety”// Define typed propsinterface MyTabProps { context: WorkUnitContext; config: PluginConfig;}
// Use typed hooksconst { data } = trpc.myPlugin.getData.useQuery<DataType>({ id });
// Type guardsfunction isWorkUnit(entity: any): entity is WorkUnit { return entity && typeof entity.id === 'string';}Testing
Section titled “Testing”import { render, screen } from '@testing-library/react';import { MyComponent } from './MyComponent';
describe('MyComponent', () => { it('renders correctly', () => { render(<MyComponent data={mockData} />); expect(screen.getByText('Expected Text')).toBeInTheDocument(); });});Accessibility
Section titled “Accessibility”- Use semantic HTML
- Provide alt text for images
- Ensure keyboard navigation
- Use ARIA labels where needed
- Test with screen readers
Security
Section titled “Security”- Validate all inputs
- Sanitize user content
- Check permissions before actions
- Use parameterized queries
- Never expose secrets in client code