Development Workflow
This guide covers the day-to-day development workflow for contributing to the Logic Apps UX project, from setting up your feature branch to getting your code merged.
Development Process Overview
Setting Up Your Development Environment
1. Create a Feature Branch
Always create a new branch from the latest main
:
# Update your local main branch
git checkout main
git pull origin main
# Create and checkout a new feature branch
git checkout -b feature/your-feature-name
# For bug fixes
git checkout -b fix/bug-description
# For documentation
git checkout -b docs/what-you-are-documenting
2. Start Development Server
# Start the standalone designer (most common)
pnpm run start
# Or start specific apps
pnpm turbo run dev --filter=standalone
pnpm turbo run dev --filter=vs-code-react
The development server includes:
- Hot Module Replacement (HMR) - See changes instantly
- Mock APIs - Work offline with realistic data
- Source Maps - Debug TypeScript directly
- Error Overlay - See errors in the browser
Writing Code
Code Style Guidelines
TypeScript Best Practices
// ✅ Good - Use interfaces for props
interface ButtonProps {
label: string;
onClick: () => void;
disabled?: boolean;
}
// ✅ Good - Use functional components with proper typing
export const Button: React.FC<ButtonProps> = ({ label, onClick, disabled = false }) => {
return (
<button onClick={onClick} disabled={disabled}>
{label}
</button>
);
};
// ❌ Bad - Avoid any types
const handleClick = (event: any) => { /* ... */ };
// ✅ Good - Be specific with types
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => { /* ... */ };
React Patterns
// ✅ Good - Use hooks for state management
const MyComponent: React.FC = () => {
const [count, setCount] = useState(0);
// Memoize expensive computations
const expensiveValue = useMemo(() => {
return computeExpensiveValue(count);
}, [count]);
// Memoize callbacks to prevent re-renders
const handleIncrement = useCallback(() => {
setCount(prev => prev + 1);
}, []);
return <div>{/* ... */}</div>;
};
// ✅ Good - Custom hooks for reusable logic
const useDebounce = <T,>(value: T, delay: number): T => {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => clearTimeout(handler);
}, [value, delay]);
return debouncedValue;
};
File Organization
feature/
├── components/
│ ├── FeatureComponent.tsx # Component implementation
│ ├── FeatureComponent.test.tsx # Component tests
│ └── index.ts # Barrel export
├── hooks/
│ ├── useFeature.ts
│ └── useFeature.test.ts
├── utils/
│ ├── featureHelpers.ts
│ └── featureHelpers.test.ts
└── index.ts # Public API
Localization
When adding user-facing strings:
- Add to the localization file:
// Don't hardcode strings
<div>Welcome to Logic Apps</div>
// Do use localization
<div>{intl.formatMessage({ defaultMessage: 'Welcome to Logic Apps' })}</div>
- Extract strings after adding them:
pnpm run extract
Testing Your Changes
Running Tests During Development
# Run unit tests in watch mode
pnpm vitest --watch
# Run specific test file
pnpm vitest MyComponent.test.tsx
# Run tests with coverage
pnpm vitest --coverage
Writing Unit Tests
import { render, screen, fireEvent } from '@testing-library/react';
import { Button } from './Button';
describe('Button Component', () => {
it('should render with label', () => {
render(<Button label="Click me" onClick={() => {}} />);
expect(screen.getByText('Click me')).toBeInTheDocument();
});
it('should call onClick when clicked', () => {
const handleClick = vi.fn();
render(<Button label="Click me" onClick={handleClick} />);
fireEvent.click(screen.getByText('Click me'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
it('should be disabled when disabled prop is true', () => {
render(<Button label="Click me" onClick={() => {}} disabled />);
expect(screen.getByText('Click me')).toBeDisabled();
});
});
E2E Testing
import { test, expect } from '@playwright/test';
test.describe('Workflow Designer', () => {
test('should create a new workflow', async ({ page }) => {
// Navigate to the designer
await page.goto('/');
// Click new workflow button
await page.getByRole('button', { name: 'New workflow' }).click();
// Add a trigger
await page.getByTestId('add-trigger-button').click();
await page.getByText('When an HTTP request is received').click();
// Verify trigger was added
await expect(page.getByText('When an HTTP request is received')).toBeVisible();
});
});
Debugging
Browser DevTools
- React DevTools - Inspect component tree and props
- Redux DevTools - View state changes and actions
- Network Tab - Monitor API calls
VS Code Debugging
- Add breakpoints in your TypeScript code
- Press
F5
to start debugging - Use the Debug Console for evaluation
Common Debugging Scenarios
// Debug Redux actions
store.subscribe(() => {
console.log('State changed:', store.getState());
});
// Debug React renders
useEffect(() => {
console.log('Component rendered with props:', props);
});
// Debug API calls
try {
const response = await api.getWorkflow(id);
console.log('API Response:', response);
} catch (error) {
console.error('API Error:', error);
}
Code Quality Checks
Before Committing
Run these commands to ensure code quality:
# Format code
pnpm run check
# Run linting
eslint . --fix
# Run type checking
tsc --noEmit
# Run all tests
pnpm run test:lib
pnpm run test:e2e --grep @mock
Pre-commit Hooks
The project uses Husky for git hooks. On commit:
- Linting runs automatically
- Code is formatted with Prettier/Biome
- Tests run for changed files
Submitting Your Changes
1. Commit Your Changes
Write clear, descriptive commit messages:
# Good commit messages
git commit -m "feat(designer): Add undo/redo functionality"
git commit -m "fix(data-mapper): Resolve connection line rendering issue"
git commit -m "docs: Update development workflow guide"
git commit -m "test(designer): Add tests for workflow validation"
# Bad commit messages
git commit -m "Fixed stuff"
git commit -m "WIP"
git commit -m "Updates"
2. Push Your Branch
git push origin feature/your-feature-name
3. Create a Pull Request
- Go to GitHub
- Click "New Pull Request"
- Fill out the PR template:
- Clear description of changes
- Link to related issues
- Screenshots for UI changes
- Test plan
4. Code Review Process
- Automated Checks - CI runs tests and linting
- Peer Review - At least one approval required
- Address Feedback - Make requested changes
- Keep Updated - Rebase on main if needed
# Update your branch with latest main
git checkout main
git pull origin main
git checkout feature/your-feature-name
git rebase main
Working with Specific Features
Designer Development
# Start designer in standalone
pnpm run start
# Key files to know
libs/designer/src/lib/core/ # Core designer logic
libs/designer/src/lib/ui/ # UI components
libs/designer/src/lib/store/ # Redux state
Data Mapper Development
# Data Mapper is part of standalone
pnpm run start
# Key files
libs/data-mapper-v2/src/core/ # Core mapping logic
libs/data-mapper-v2/src/components/ # UI components
libs/data-mapper-v2/src/utils/ # Utilities
VS Code Extension Development
# Build and test extension
pnpm run build:extension
# Key files
apps/vs-code-designer/src/ # Extension host code
apps/vs-code-react/src/ # Webview code
Performance Considerations
React Performance
- Use React.memo for expensive components
- Optimize re-renders with useMemo/useCallback
- Lazy load large components
- Virtualize long lists
Bundle Size
- Tree shake unused code
- Dynamic imports for code splitting
- Analyze bundle with build tools
# Analyze bundle size
pnpm turbo run build --filter=designer -- --analyze
Troubleshooting Development Issues
Common Issues and Solutions
HMR not working
# Clear Vite cache
rm -rf node_modules/.vite
pnpm run start
Type errors after pulling changes
# Rebuild TypeScript definitions
pnpm run build:lib
Tests failing locally but not in CI
# Run tests in CI mode
CI=true pnpm run test:lib
Best Practices Checklist
Before submitting your PR, ensure:
- Code follows TypeScript best practices
- Components are accessible (keyboard navigation, ARIA labels)
- Unit tests cover new functionality
- E2E tests added for user flows
- No console.log statements left
- Localization strings extracted
- Documentation updated if needed
- Performance impact considered
- Security best practices followed
Getting Help
- Team Chat: Reach out on Teams
- GitHub Discussions: Ask questions
- Code Reviews: Learn from feedback
- Pair Programming: Schedule sessions with team members
Remember: Good development workflow leads to maintainable code and happy developers! 🚀