Skip to main content

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:

  1. 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>
  1. 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​

  1. React DevTools - Inspect component tree and props
  2. Redux DevTools - View state changes and actions
  3. Network Tab - Monitor API calls

VS Code Debugging​

  1. Add breakpoints in your TypeScript code
  2. Press F5 to start debugging
  3. 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:

  1. Linting runs automatically
  2. Code is formatted with Prettier/Biome
  3. 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​

  1. Go to GitHub
  2. Click "New Pull Request"
  3. 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​

  1. Use React.memo for expensive components
  2. Optimize re-renders with useMemo/useCallback
  3. Lazy load large components
  4. Virtualize long lists

Bundle Size​

  1. Tree shake unused code
  2. Dynamic imports for code splitting
  3. 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! 🚀