Contributing to Kumo
We welcome contributions to Kumo! This guide will help you get started with adding new components and blocks to the library.
Components vs Blocks vs Layouts
Components
Atomic, reusable UI elements
- Single responsibility
- Highly reusable
- Minimal dependencies
- Style-focused
Examples: Button, Input, Badge, Tabs
Blocks
Composed patterns for page layouts
- Compose multiple components
- Implement common patterns
- Layout-focused
- May include business logic
Examples: Breadcrumbs, PageHeader, Empty
Layouts
Page-level structure patterns
- Full-page composition
- Consistent structure
- Responsive patterns
- Application-wide use
Examples: ResourceListPage, DashboardPage
Creating New Components
Kumo includes a scaffolding tool that automates component creation. This ensures all components follow the same structure and are properly configured.
Run the Scaffolding Tool
From the workspace root, run:
pnpm --filter @cloudflare/kumo new-component
What the Scaffolding Tool Does
The tool automatically creates and updates several files:
- Component file -
src/components/{name}/{name}.tsx - Index file -
src/components/{name}/index.ts - Test file -
src/components/{name}/{name}.test.tsx - Main exports - Updates
src/index.ts - Build config - Updates
vite.config.ts - Package exports - Updates
package.json
Example
Here's what the scaffolding process looks like:
? Component name: Alert Banner
✅ Component scaffolded successfully!
📁 Files created:
- src/components/alert-banner/alert-banner.tsx
- src/components/alert-banner/index.ts
- src/components/alert-banner/alert-banner.test.tsx
📝 Files updated:
- src/index.ts
- vite.config.ts
- package.json
💡 Import examples:
import { AlertBanner } from "@cloudflare/kumo";
import { AlertBanner } from "@cloudflare/kumo/components/alert-banner";Component Naming
The scaffolding tool handles naming automatically. You can input the name in any format:
- Spaces - "Alert Banner" →
alert-bannerdirectory,AlertBannercomponent - PascalCase - "AlertBanner" →
alert-bannerdirectory,AlertBannercomponent - kebab-case - "alert-banner" →
alert-bannerdirectory,AlertBannercomponent
Creating New Blocks
Blocks are higher-level components that compose multiple base components. Use the block scaffolding tool to create them:
Run the Block Scaffolding Tool
From the workspace root, run:
pnpm --filter @cloudflare/kumo new-block
What It Creates
The block scaffolding tool creates the same structure as components, but in the src/blocks directory:
- Block file -
src/blocks/{name}/{name}.tsx - Index file -
src/blocks/{name}/index.ts - Test file -
src/blocks/{name}/{name}.test.tsx - Main exports - Updates
src/index.ts(Blocks section) - Build config - Updates
vite.config.ts - Package exports - Updates
package.json
Example
? Block name: Navigation Bar
✅ Block scaffolded successfully!
📁 Files created:
- src/blocks/navigation-bar/navigation-bar.tsx
- src/blocks/navigation-bar/index.ts
- src/blocks/navigation-bar/navigation-bar.test.tsx
📝 Files updated:
- src/index.ts
- vite.config.ts
- package.json
💡 Import examples:
import { NavigationBar } from "@cloudflare/kumo";
import { NavigationBar } from "@cloudflare/kumo/blocks/navigation-bar";
📝 Note: Blocks are higher-level components that compose base components.Creating New Layouts
Layouts are page-level components that provide consistent structure for common page patterns. Use the layout scaffolding tool:
Run the Layout Scaffolding Tool
From the workspace root, run:
pnpm --filter @cloudflare/kumo new-layout
What It Creates
The layout scaffolding tool creates the same structure as components and blocks, but in the src/layouts directory:
- Layout file -
src/layouts/{name}/{name}.tsx - Index file -
src/layouts/{name}/index.ts - Test file -
src/layouts/{name}/{name}.test.tsx - Main exports - Updates
src/index.ts(Layouts section) - Build config - Updates
vite.config.ts - Package exports - Updates
package.json
Example
? Layout name: Dashboard Page
✅ Layout scaffolded successfully!
📁 Files created:
- src/layouts/dashboard-page/dashboard-page.tsx
- src/layouts/dashboard-page/index.ts
- src/layouts/dashboard-page/dashboard-page.test.tsx
📝 Files updated:
- src/index.ts
- vite.config.ts
- package.json
💡 Import examples:
import { DashboardPage } from "@cloudflare/kumo";
import { DashboardPage } from "@cloudflare/kumo/layouts/dashboard-page";
📝 Note: Layouts are page-level components for consistent structure.Development Workflow
After scaffolding a component, block, or layout, follow these steps:
- Implement the component/block/layout
Edit the generated
.tsxfile with your implementation. Use Storybook for rapid development. - Create stories
Add a
.stories.tsxfile to showcase component variants in Storybook. - Write tests
Add tests to the generated
.test.tsxfile. - Run tests
pnpm --filter @cloudflare/kumo test
- Build the package
pnpm --filter @cloudflare/kumo build
- Add documentation
Create a documentation page in
kumo-docs/app/routes/
Storybook Development
Kumo uses Storybook as a live development environment for building and testing components in isolation. It provides instant feedback and serves as interactive documentation.
Start Storybook
pnpm --filter @cloudflare/kumo storybook
Opens at http://localhost:6006 with hot module replacement enabled.
Why Use Storybook
- Build components without running the full application
- Test all variations and edge cases interactively
- Auto-generated documentation from TypeScript types
- Instant HMR updates as you code
- Shared tool for designers and developers
Creating Stories
Story files live alongside components and follow the pattern {name}.stories.tsx:
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './button';
const meta = {
title: 'Components/Button',
component: Button,
tags: ['autodocs'],
} satisfies Meta<typeof Button>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Primary: Story = {
args: { children: 'Click me' },
};Story Organization
- Components -
src/components/{name}/{name}.stories.tsx - Blocks -
src/blocks/{name}/{name}.stories.tsx - Layouts -
src/layouts/{name}/{name}.stories.tsx
Best Practice: Always create stories for new components, blocks, and layouts. Stories serve as living documentation and make development faster.
For comprehensive Storybook documentation, see packages/kumo/STORYBOOK.md
Testing
The test suite automatically validates your component, block, or layout configuration:
- Main entry point exports the component/block/layout
- Deep import paths work correctly (
@cloudflare/kumo/components/*,@cloudflare/kumo/blocks/*, or@cloudflare/kumo/layouts/*) - Package.json exports are properly configured
- Build configuration is correct
- All files exist in the correct locations
Run the test suite to ensure everything is configured correctly:
pnpm --filter @cloudflare/kumo test:run
The tests will provide helpful error messages with exact code snippets if any configuration is missing.
Component Guidelines
When implementing components, follow these guidelines:
- Accessibility - Include proper ARIA attributes and keyboard navigation
- TypeScript - Export prop types and use proper type annotations
- Styling - Use Tailwind CSS classes and the
cnutility - Consistency - Follow existing component patterns and naming conventions
- Documentation - Add clear JSDoc comments and usage examples
- Testing - Include unit tests for component behavior
- Single Responsibility - Keep components focused on one task
Block Guidelines
When implementing blocks, follow these additional guidelines:
- Composition - Compose existing components rather than reimplementing functionality
- Framework Agnostic - Use
LinkProviderfor routing to remain framework-agnostic - Flexible Props - Accept both simple and complex props to support various use cases
- Common Patterns - Focus on patterns that appear in multiple applications
- Documentation - Include JSDoc explaining the block's purpose and when to use it
- Examples - Provide clear usage examples showing composition
When to Create a Block
- Pattern appears in multiple places across applications
- Combines 2+ base components
- Implements a common layout or page structure
- Has specific business logic or behavior
When NOT to Create a Block
- Single component with styling variations (use component variants instead)
- Application-specific logic (keep in application code)
- One-off patterns (wait for reuse before abstracting)
Additional Resources
For more detailed information, refer to: