langflow/.cursor/rules/frontend_development.mdc
Gabriel Luiz Freitas Almeida ab1ed8ea01
docs: add comprehensive cursor guidelines and rules for development practices (#8401)
* Update cursor rules with specific backend, frontend, docs

* Update image example

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* update image example

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Refactor frontend development guidelines: streamline sections, remove outdated icon development instructions, and update checklist for clarity and consistency.

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-06-12 12:51:18 +00:00

374 lines
8.3 KiB
Text

---
description: "Guidelines for frontend development in Langflow, focusing on React/TypeScript UI components, build processes, and frontend testing."
globs:
- "src/frontend/**/*.{ts,tsx,js,jsx}"
- "src/frontend/**/*.{css,scss,json}"
- "src/frontend/package*.json"
- "src/frontend/vite.config.*"
- "src/frontend/tailwind.config.*"
- "src/frontend/tsconfig.json"
alwaysApply: false
---
## 1. Frontend Environment Setup
### Prerequisites
- **Node.js:** v22.12 LTS for JavaScript runtime
- **Package Manager:** npm (v10.9) for dependency management
- **Development Tools:** Vite for build tooling
### Frontend Service
```bash
make frontend # Start Vite dev server on port 3000
```
- Hot-reload enabled for UI changes
- Access at: http://localhost:3000/
- Frontend source: `src/frontend/`
---
## 2. Frontend Structure
### Directory Layout
```
src/frontend/src/
├── components/ # Reusable UI components
├── pages/ # Page-level components
├── icons/ # Component icons and lazy loading
├── stores/ # State management (Zustand)
├── types/ # TypeScript type definitions
├── utils/ # Utility functions
├── hooks/ # Custom React hooks
├── services/ # API service functions
└── assets/ # Static assets
```
### Key Technologies
- **React 18** with TypeScript
- **Vite** for build tooling and dev server
- **Tailwind CSS** for styling
- **Zustand** for state management
- **React Flow** for flow graph visualization
- **Lucide React** for icons
---
## 3. Frontend Code Quality
### Formatting
```bash
make format_frontend # Format TypeScript/JavaScript code
```
### Linting
```bash
make lint # Run ESLint and TypeScript checks
```
### Testing
```bash
make tests_frontend # Run frontend tests (requires additional setup)
```
### Pre-commit Workflow
1. Run `make format_frontend`
2. Run `make lint`
3. Test changes in browser
4. Commit changes
---
## 4. State Management
### Zustand Stores
```typescript
// stores/myStore.ts
import { create } from 'zustand';
interface MyState {
value: string;
setValue: (value: string) => void;
}
export const useMyStore = create<MyState>((set) => ({
value: '',
setValue: (value) => set({ value }),
}));
```
### Using Stores in Components
```typescript
// components/MyComponent.tsx
import { useMyStore } from '@/stores/myStore';
export function MyComponent() {
const { value, setValue } = useMyStore();
return (
<input
value={value}
onChange={(e) => setValue(e.target.value)}
/>
);
}
```
---
## 5. API Integration
### Service Functions
```typescript
// services/api.ts
import { api } from '@/controllers/API';
export async function createFlow(flowData: FlowData) {
const response = await api.post('/flows/', flowData);
return response.data;
}
export async function getFlows() {
const response = await api.get('/flows/');
return response.data;
}
```
### Error Handling
```typescript
// hooks/useApi.ts
import { useState, useCallback } from 'react';
export function useApi<T>(apiFunction: (...args: any[]) => Promise<T>) {
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const execute = useCallback(async (...args: any[]) => {
try {
setLoading(true);
setError(null);
const result = await apiFunction(...args);
return result;
} catch (err) {
setError(err instanceof Error ? err.message : 'Unknown error');
throw err;
} finally {
setLoading(false);
}
}, [apiFunction]);
return { execute, loading, error };
}
```
---
## 6. React Flow Integration
### Flow Graph Components
```typescript
// components/FlowGraph.tsx
import ReactFlow, {
Node,
Edge,
Controls,
Background
} from 'reactflow';
interface FlowGraphProps {
nodes: Node[];
edges: Edge[];
onNodesChange: (changes: NodeChange[]) => void;
onEdgesChange: (changes: EdgeChange[]) => void;
}
export function FlowGraph({
nodes,
edges,
onNodesChange,
onEdgesChange
}: FlowGraphProps) {
return (
<div className="w-full h-full">
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
fitView
>
<Controls />
<Background />
</ReactFlow>
</div>
);
}
```
### Custom Node Types
```typescript
// components/nodes/ComponentNode.tsx
import { memo } from 'react';
import { Handle, Position } from 'reactflow';
interface ComponentNodeProps {
data: {
label: string;
icon?: string;
};
}
export const ComponentNode = memo(({ data }: ComponentNodeProps) => {
return (
<div className="px-4 py-2 shadow-md rounded-md bg-white border">
<Handle type="target" position={Position.Top} />
<div className="flex items-center">
{data.icon && (
<img src={data.icon} alt="" className="w-4 h-4 mr-2" />
)}
<span className="text-sm">{data.label}</span>
</div>
<Handle type="source" position={Position.Bottom} />
</div>
);
});
```
---
## 7. Styling with Tailwind
### Component Styling
```typescript
// components/Button.tsx
import { cn } from '@/utils/cn';
interface ButtonProps {
variant?: 'primary' | 'secondary';
size?: 'sm' | 'md' | 'lg';
children: React.ReactNode;
onClick?: () => void;
}
export function Button({
variant = 'primary',
size = 'md',
children,
onClick
}: ButtonProps) {
return (
<button
className={cn(
'rounded-md font-medium transition-colors',
{
'bg-blue-600 hover:bg-blue-700 text-white': variant === 'primary',
'bg-gray-200 hover:bg-gray-300 text-gray-900': variant === 'secondary',
'px-2 py-1 text-sm': size === 'sm',
'px-4 py-2 text-base': size === 'md',
'px-6 py-3 text-lg': size === 'lg',
}
)}
onClick={onClick}
>
{children}
</button>
);
}
```
### Dark Mode Support
```typescript
// hooks/useDarkMode.ts
import { useDarkStore } from '@/stores/darkStore';
export function useDarkMode() {
const { dark, setDark } = useDarkStore();
const toggle = () => setDark(!dark);
return { isDark: dark, toggle };
}
```
---
## 8. Frontend Testing
### Component Testing
```typescript
// __tests__/Button.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { Button } from '@/components/Button';
describe('Button', () => {
it('renders with correct text', () => {
render(<Button>Click me</Button>);
expect(screen.getByText('Click me')).toBeInTheDocument();
});
it('calls onClick when clicked', () => {
const handleClick = jest.fn();
render(<Button onClick={handleClick}>Click me</Button>);
fireEvent.click(screen.getByText('Click me'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
});
```
### Integration Testing
```typescript
// __tests__/FlowEditor.test.tsx
import { render, screen } from '@testing-library/react';
import { FlowEditor } from '@/pages/FlowEditor';
describe('FlowEditor', () => {
it('loads flow data correctly', async () => {
render(<FlowEditor flowId="test-flow-id" />);
// Wait for flow to load
await screen.findByText('Flow loaded');
expect(screen.getByTestId('flow-canvas')).toBeInTheDocument();
});
});
```
---
## 9. Build and Deployment
### Development Build
```bash
make build_frontend # Build frontend static files
```
### Production Build
```bash
cd src/frontend
npm run build # Creates dist/ directory
```
### Build Integration
- Frontend builds to `src/frontend/dist/`
- Backend serves static files from this directory in production
- `make init` includes frontend build step
---
## Frontend Development Checklist
- [ ] Frontend service running with `make frontend`
- [ ] Changes hot-reload correctly in browser
- [ ] State management uses Zustand stores
- [ ] API calls use proper error handling
- [ ] Components styled with Tailwind CSS
- [ ] Dark mode support implemented where needed
- [ ] Code formatted with `make format_frontend`
- [ ] Linting passed with `make lint`
- [ ] Changes tested in both light and dark mode
- [ ] Components styled with Tailwind CSS
- [ ] Dark mode support implemented where needed
- [ ] Code formatted with `make format_frontend`
- [ ] Changes tested in both light and dark mode