Contributing to Forge UI Component Library
October 2, 2025 · View on GitHub
Thank you for your interest in contributing to Forge UI! This document provides guidelines and instructions for contributing to the project.
📋 Table of Contents
- Code of Conduct
- Getting Started
- Development Process
- Creating Components
- Testing Requirements
- Submitting Changes
- Style Guidelines
Code of Conduct
We are committed to providing a welcoming and inclusive environment. Please be respectful and considerate in all interactions.
Getting Started
Prerequisites
- Node.js 18+ (20+ recommended) and npm 9+
- Git
- Basic knowledge of Web Components and Lit
- Familiarity with TypeScript
Setup
- Fork the repository
- Clone your fork:
git clone https://github.com/your-username/forge.git
cd forge
- Install dependencies:
npm install
- Create a feature branch:
git checkout -b feature/your-feature-name
- Start development:
npm run dev # Component development
npm run storybook # Interactive documentation
Development Process
Branch Strategy
main- Production-ready codedevelop- Integration branchfeature/*- New featuresfix/*- Bug fixeschore/*- Maintenance tasks
Workflow
- Create a feature branch from
develop - Make your changes
- Write/update tests
- Update documentation
- Submit a pull request to
develop
Creating Components
Using the Generator
npm run generate:component MyComponent atoms
This creates:
src/components/atoms/my-component/my-component.tssrc/components/atoms/my-component/my-component.test.tssrc/components/atoms/my-component/my-component.stories.tssrc/components/atoms/my-component/index.ts
Component Requirements
1. Extend BaseElement
import { BaseElement } from '../../../core/BaseElement';
@customElement('forge-my-component')
export class ForgeMyComponent extends BaseElement {
// Component implementation
}
2. Follow Naming Conventions
- Custom element:
forge-component-name - Class name:
ForgeComponentName - File name:
component-name.ts - Events:
forge-component-name-event
3. Implement Required Features
- ✅ Keyboard navigation
- ✅ ARIA attributes
- ✅ Focus management
- ✅ Screen reader announcements
4. Use Design Tokens
:host {
color: var(--forge-color-text);
font-size: var(--forge-font-size-base);
}
Testing Requirements
Coverage Minimums
- Statements: 70%
- Branches: 70%
- Functions: 70%
- Lines: 70%
Test Types Required
Unit Tests
describe('ForgeMyComponent', () => {
it('renders with default properties', async () => {
const el = await fixture<ForgeMyComponent>(html`
<forge-my-component></forge-my-component>
`);
expect(el).to.exist;
});
// Test all props, events, and methods
});
Accessibility Tests
it('is accessible', async () => {
const el = await fixture<ForgeMyComponent>(html`
<forge-my-component></forge-my-component>
`);
await expect(el).to.be.accessible();
});
Visual Tests (Storybook)
Create stories for all states and variants:
export const Default: Story = { /* ... */ };
export const Disabled: Story = { /* ... */ };
export const Loading: Story = { /* ... */ };
Running Tests
npm run test # Unit tests (vitest)
npm run test:watch # Watch mode
npm run test:coverage # Coverage report
Submitting Changes
Pre-submission Checklist
- Tests pass (
npm run test) - Linting passes (
npm run lint) - Documentation updated
- Storybook stories created/updated
- Accessibility audit passes
- Bundle size checked
- AI artifacts valid (
npm run validate:ai)
Commit Messages
Follow conventional commits:
type(scope): description
Types:
- feat: New feature
- fix: Bug fix
- docs: Documentation
- style: Code style
- refactor: Refactoring
- test: Tests
- chore: Maintenance
Examples:
feat(button): add loading state
fix(modal): correct focus trap
docs(readme): update installation
Pull Request Process
- Title: Use conventional commit format
- Description: Explain what and why
- Testing: Describe testing done
- Screenshots: Include for UI changes
- Breaking Changes: Clearly marked
PR Template
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation
## Testing
- [ ] Unit tests pass
- [ ] Visual tests pass
- [ ] E2E tests pass
- [ ] Accessibility audit passes
## Checklist
- [ ] Code follows style guidelines
- [ ] Self-review completed
- [ ] Documentation updated
- [ ] Storybook stories updated
Style Guidelines
TypeScript
- Use TypeScript strict mode
- Provide explicit types (no
any) - Document public APIs with JSDoc
- Use interfaces over type aliases
CSS
- Use Shadow DOM for encapsulation
- Use CSS Custom Properties for theming
- Follow BEM-like naming in Shadow DOM
- Mobile-first responsive design
General
- Keep components focused (single responsibility)
- Prefer composition over configuration
AI-Native Requirements (Important)
All components in Forge are AI‑ready. When adding or modifying components:
- Implement AI methods in the component class (inherited from
BaseElement):getPossibleActions()explainState()- Ensure
aiStatereflects meaningful state/attributes
- Annotate slots with JSDoc
@slotfor CEM extraction (used by the AI manifest) - Provide semantic and a11y context where applicable:
semantic-role,ai-context, ARIA labels and descriptions
- Keep prop and event typings accurate (TypeScript) to drive correct manifest output
- Run
npm run build:locallocally when feasible to ensure AI artifacts generate and validate
AI Artifact Debugging (Quick Tip)
If AI artifacts look empty or tools can’t find metadata:
- Generate and validate locally:
npm run build:local(runs CEM + AI generators)npm run validate:ai(basic checks)
- Inspect outputs:
- Repo root:
ai-manifest.json(should list all components) - Dist:
dist/ai-manifest.json(bundled types alongside) - Published package (node_modules/@nexcraft/forge):
ai-manifest.json,ai-index.json,ai-tools/*
- Repo root:
- Sanity checks:
components.lengthshould be > 0 (expect ~30)custom-elements.jsonshould be present in the package- Exports resolve:
require.resolve('@nexcraft/forge/ai-manifest.json')
- See also:
- Docs:
docs/ai-manifest.md,docs/ai/metadata-reference.md,docs/ai/integration-guide.md
- Docs:
Pre-commit Hooks
We use Husky to run staged‑aware checks. The hook will skip expensive steps when non‑code files change, and will:
- Lint staged files (via lint‑staged)
- Type‑check on TS/config changes
- Run tests on source/test changes
- Build (core) only on build‑critical changes
You generally don’t need to run these manually; CI will re‑verify everything.
- Make components controlled when possible
- Emit CustomEvents for all state changes
Questions?
- Check existing issues and discussions
- Join our Discord/Slack community
- Contact the maintainers
Recognition
Contributors are recognized in:
- README.md contributors section
- Release notes
- Annual contributor spotlight
Thank you for helping make Forge UI better! 🎉