A production-ready template for building micro frontend (MFE) applications with React, TypeScript, and modern tooling. This template provides essential components, utilities, and patterns to quickly scaffold new MFE projects.
- Atomic Design: Components organized as Atoms → Molecules → Organisms
- Design System: Comprehensive design tokens with WCAG AA compliance
- Theme Support: Light, dark, and system theme modes
- Modern Stack: React 18, TypeScript, Vite, Tailwind CSS
- Testing Ready: Vitest configuration with 90%+ coverage thresholds
- Build Optimized: tsup for library builds, Vite for development
- Developer Experience: ESLint, Prettier, and comprehensive tooling
- Accessibility: ARIA labels, keyboard navigation, semantic HTML
# Clone the template
git clone https://github.com/jonmatum/react-mfe-template.git my-mfe-project
cd my-mfe-project
# Install dependencies
npm install
# Start development
npm run dev
# Build for production
npm run build
import React from 'react';
import { SettingsProvider, Button, Modal, useSettings } from 'my-mfe-library';
import 'my-mfe-library/dist/style.css';
function App() {
return (
<SettingsProvider>
<MyComponent />
</SettingsProvider>
);
}
function MyComponent() {
const { settings, updateSettings } = useSettings();
return (
<div className="p-4">
<Button onClick={() => console.log('Clicked!')}>
Hello MFE!
</Button>
</div>
);
}
- Button: Configurable button with variants (primary, secondary, ghost)
- LoadingSpinner: Animated loading indicator with customizable sizes
- Switch: Toggle switch for settings and preferences
- Modal: Accessible modal dialog with backdrop and keyboard support
- SettingsProvider: Global state management for theme and layout preferences
- classNames: Utility for combining CSS classes
- storage: Local storage helpers with error handling
- theme: Theme management utilities
- tokens: Comprehensive design token system
- Colors: Primary, secondary, and semantic color palettes
- Typography: Font families, sizes, and weights
- Spacing: Consistent spacing scale
- Shadows: Elevation system
- Breakpoints: Responsive design breakpoints
src/
├── components/
│ ├── atoms/ # Basic building blocks
│ │ ├── Button.tsx
│ │ ├── LoadingSpinner.tsx
│ │ └── Switch.tsx
│ ├── molecules/ # Simple combinations
│ │ └── Modal.tsx
│ └── organisms/ # Complex combinations (add as needed)
├── contexts/ # React contexts
│ └── SettingsContext.tsx
├── types/ # TypeScript definitions
│ └── index.ts
├── utils/ # Utility functions
│ ├── index.ts
│ └── tokens.ts
├── styles/ # CSS files
│ └── index.css
└── index.ts # Main exports
The template includes a comprehensive theming system:
import { useSettings } from 'my-mfe-library';
function ThemeToggle() {
const { settings, updateSettings } = useSettings();
return (
<button
onClick={() => updateSettings({
theme: settings.theme === 'light' ? 'dark' : 'light'
})}
>
Toggle Theme
</button>
);
}
light
: Light themedark
: Dark themesystem
: Follows system preference
# Development
npm run dev # Start development server
npm run build # Build for production
npm run build:lib # Build library only
# Quality
npm run lint # Run ESLint
npm run lint:fix # Fix ESLint issues
npm run type-check # TypeScript type checking
npm run test # Run tests
npm run test:coverage # Run tests with coverage
# Formatting
npm run format # Format with Prettier
npm run format:check # Check formatting
- Atoms: Basic UI elements (buttons, inputs, icons)
- Molecules: Simple combinations (search box, card header)
- Organisms: Complex combinations (navigation, forms)
// Example: Adding a new atom
// src/components/atoms/Input.tsx
import React from 'react';
import { BaseComponentProps } from '../../types';
import { classNames } from '../../utils';
interface InputProps extends BaseComponentProps {
type?: string;
placeholder?: string;
value?: string;
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
}
const Input: React.FC<InputProps> = ({ className, ...props }) => {
return (
<input
className={classNames(
'block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500',
className
)}
{...props}
/>
);
};
export default Input;
Don't forget to export new components in src/index.ts
:
export { default as Input } from './components/atoms/Input';
Use atoms to build more complex components:
// src/components/molecules/SearchBox.tsx
import React, { useState } from 'react';
import { MagnifyingGlassIcon } from '@heroicons/react/24/outline';
import Input from '../atoms/Input';
import Button from '../atoms/Button';
interface SearchBoxProps {
onSearch: (query: string) => void;
placeholder?: string;
}
const SearchBox: React.FC<SearchBoxProps> = ({
onSearch,
placeholder = 'Search...'
}) => {
const [query, setQuery] = useState('');
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
onSearch(query);
};
return (
<form onSubmit={handleSubmit} className="flex gap-2">
<Input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder={placeholder}
className="flex-1"
/>
<Button type="submit" variant="primary">
<MagnifyingGlassIcon className="h-5 w-5" />
</Button>
</form>
);
};
export default SearchBox;
import { colors, spacing, typography } from 'your-mfe-project';
// Use tokens in your components
const customStyles = {
backgroundColor: colors.primary[500],
padding: spacing[4],
fontSize: typography.fontSize.base[0],
};
// Prefer utility classes
<div className="bg-blue-500 p-4 text-base rounded-md shadow-sm">
Content
</div>
// Use design tokens for consistency
<div className="bg-primary-500 p-4 text-base rounded-md shadow-sm">
Content
</div>
// Test component behavior
describe('MyComponent', () => {
it('renders correctly', () => {
render(<MyComponent />);
expect(screen.getByRole('button')).toBeInTheDocument();
});
it('handles user interactions', () => {
const handleClick = vi.fn();
render(<MyComponent onClick={handleClick} />);
fireEvent.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalled();
});
it('applies custom className', () => {
render(<MyComponent className="custom-class" />);
expect(screen.getByRole('button')).toHaveClass('custom-class');
});
});
The template enforces 90%+ coverage thresholds:
- Statements: 90%
- Branches: 90%
- Functions: 90%
- Lines: 90%
npm run build:watch # Watch mode for development
npm run build # Full production build
npm run build:lib # Library build only
# Update version
npm version patch|minor|major
# Publish to npm
npm publish
Create .env
files for different environments:
# .env.development
VITE_API_URL=http://localhost:3001
# .env.production
VITE_API_URL=https://api.yourproject.com
Modify tsup.config.ts
for build customization:
export default defineConfig({
entry: ['src/index.ts'],
format: ['cjs', 'esm'],
dts: true,
sourcemap: true,
external: ['react', 'react-dom', '@heroicons/react'],
// Add your customizations
});
# Build for production
npm run build
# Deploy to GitHub Pages (if configured)
npm run deploy
# Ensure you're logged in to npm
npm login
# Publish the package
npm publish
- Follow the atomic design principles
- Write comprehensive tests
- Use TypeScript for all new code
- Follow the existing code style
- Update documentation as needed
This template is licensed under the MIT License. See LICENSE for details.