feature-development
Guide for developing new features in the DEVS platform following the modular feature architecture. Use this when asked to add a new feature, create a feature module, or understand the feature structure.
Installation
Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.
View source ↗GuidesSkill instructions
Feature Development for DEVS
Features in DEVS are self-contained modules that encapsulate related functionality. Each feature has its own components, hooks, stores, and logic.
Feature Directory Structure
src/features/{feature-name}/
├── index.ts # Public exports
├── components/ # Feature-specific components
│ ├── FeatureComponent.tsx
│ └── index.ts
├── hooks/ # Feature-specific hooks
│ ├── useFeatureHook.ts
│ └── index.ts
├── stores/ # Feature-specific stores (if needed)
│ └── featureStore.ts
├── lib/ # Feature-specific utilities
│ └── feature-utils.ts
├── types/ # Feature-specific types
│ └── index.ts
└── README.md # Feature documentation
Existing Features Reference
| Feature | Directory | Description |
|---|---|---|
| Battle Arena | src/features/battle/ |
Agent vs agent competitions |
| Connectors | src/features/connectors/ |
OAuth integrations (Google, Notion) |
| Live | src/features/live/ |
Real-time collaboration |
| Sync | src/features/sync/ |
P2P data synchronization via Yjs |
| Traces | src/features/traces/ |
LLM observability and analytics |
| Local Backup | src/features/local-backup/ |
File system sync |
Creating a New Feature
1. Create Feature Directory
mkdir -p src/features/my-feature/{components,hooks,lib,types}
2. Define Types
// src/features/my-feature/types/index.ts
export interface MyFeatureConfig {
enabled: boolean
option1: string
option2: number
}
export interface MyFeatureState {
isActive: boolean
data: MyFeatureData[]
}
export interface MyFeatureData {
id: string
name: string
createdAt: Date
}
3. Create Feature Store (if needed)
// src/features/my-feature/stores/myFeatureStore.ts
import { create } from 'zustand'
import type { MyFeatureState, MyFeatureData } from '../types'
interface MyFeatureActions {
initialize: () => Promise<void>
addData: (data: MyFeatureData) => void
clear: () => void
}
export const useMyFeatureStore = create<MyFeatureState & MyFeatureActions>(
(set) => ({
isActive: false,
data: [],
initialize: async () => {
// Initialize feature
set({ isActive: true })
},
addData: (data) => {
set((state) => ({ data: [...state.data, data] }))
},
clear: () => {
set({ data: [], isActive: false })
},
}),
)
4. Create Components
// src/features/my-feature/components/MyFeaturePanel.tsx
import { Card, CardBody, Button } from '@heroui/react'
import { useTranslation } from 'react-i18next'
import { useMyFeatureStore } from '../stores/myFeatureStore'
export function MyFeaturePanel() {
const { t } = useTranslation()
const { isActive, data, initialize } = useMyFeatureStore()
if (!isActive) {
return (
<Card>
<CardBody>
<Button onPress={initialize}>
{t('myFeature.activate')}
</Button>
</CardBody>
</Card>
)
}
return (
<Card>
<CardBody>
<h2>{t('myFeature.title')}</h2>
{data.map((item) => (
<div key={item.id}>{item.name}</div>
))}
</CardBody>
</Card>
)
}
5. Create Hooks
// src/features/my-feature/hooks/useMyFeature.ts
import { useCallback, useEffect } from 'react'
import { useMyFeatureStore } from '../stores/myFeatureStore'
export function useMyFeature() {
const store = useMyFeatureStore()
useEffect(() => {
// Setup on mount
return () => {
// Cleanup on unmount
}
}, [])
const handleAction = useCallback(async () => {
// Feature-specific logic
}, [])
return {
...store,
handleAction,
}
}
6. Create Public Exports
// src/features/my-feature/index.ts
export { MyFeaturePanel } from './components/MyFeaturePanel'
export { useMyFeature } from './hooks/useMyFeature'
export { useMyFeatureStore } from './stores/myFeatureStore'
export type { MyFeatureConfig, MyFeatureState, MyFeatureData } from './types'
7. Add Feature Documentation
<!-- src/features/my-feature/README.md -->
# My Feature
Brief description of what this feature does.
## Usage
\`\`\`tsx
import { MyFeaturePanel, useMyFeature } from '@/features/my-feature'
function App() {
const { isActive, handleAction } = useMyFeature()
return <MyFeaturePanel />
}
\`\`\`
## Configuration
Describe configuration options...
## API Reference
### Components
- `MyFeaturePanel` - Main UI component
### Hooks
- `useMyFeature()` - Primary hook for feature functionality
### Store
- `useMyFeatureStore` - Zustand store for feature state
Integration Points
Adding to Navigation
// In relevant page or layout
import { MyFeaturePanel } from '@/features/my-feature'
function MyPage() {
return (
<div>
<MyFeaturePanel />
</div>
)
}
Feature Flags
For features that need to be toggleable:
// src/features/my-feature/lib/feature-flags.ts
export function isMyFeatureEnabled(): boolean {
// Check user settings, environment, etc.
return localStorage.getItem('myFeature.enabled') === 'true'
}
Adding Translations
// Add to src/i18n/locales/en.ts
export default {
// ... existing translations
myFeature: {
title: 'My Feature',
activate: 'Activate Feature',
description: 'Feature description',
},
}
Testing Features
// src/test/features/my-feature/MyFeaturePanel.test.tsx
import { render, screen } from '@testing-library/react'
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { MyFeaturePanel } from '@/features/my-feature'
import { useMyFeatureStore } from '@/features/my-feature/stores/myFeatureStore'
vi.mock('react-i18next', () => ({
useTranslation: () => ({ t: (key: string) => key }),
}))
describe('MyFeaturePanel', () => {
beforeEach(() => {
useMyFeatureStore.setState({ isActive: false, data: [] })
})
it('shows activate button when inactive', () => {
render(<MyFeaturePanel />)
expect(screen.getByText('myFeature.activate')).toBeInTheDocument()
})
it('shows data when active', () => {
useMyFeatureStore.setState({
isActive: true,
data: [{ id: '1', name: 'Test', createdAt: new Date() }],
})
render(<MyFeaturePanel />)
expect(screen.getByText('Test')).toBeInTheDocument()
})
})
Best Practices
- Keep features isolated: Minimize dependencies between features
-
Use index exports: Only expose public API through
index.ts - Document thoroughly: Each feature should have a README
- Test in isolation: Feature tests shouldn't depend on other features
- Lazy load when possible: Use dynamic imports for large features
Examples
Read the usage examples in the source repository.
View source ↗Source history
- Indexed on
- 2026-01-20
- Index updated
- 2026-02-02
- Branch
- main
Index and sync dates describe this directory. View the source repository for code history.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!