Self-contained feature slices following Vertical Slice Architecture. Each feature owns its domain logic, state, services, and components.
Features organize code by category subdirectories when complexity warrants it:
features/
├── dreamnode/ # Complex feature - full structure
│ ├── store/
│ │ └── slice.ts # Zustand slice for feature state
│ ├── services/ # Orchestrators with state/side-effects
│ │ ├── git-dreamnode-service.ts
│ │ ├── udd-service.ts
│ │ └── media-loading-service.ts
│ ├── utils/ # Stateless pure functions
│ │ ├── git-utils.ts
│ │ ├── vault-scanner.ts
│ │ └── repo-initializer.ts
│ ├── components/ # React/R3F components
│ │ ├── DreamNode3D.tsx
│ │ └── ...
│ ├── types/ # TypeScript interfaces
│ │ └── dreamnode.ts
│ ├── styles/ # CSS and style constants
│ ├── commands.ts # Obsidian command registrations
│ ├── test-utils.ts # Mock factories for testing
│ ├── README.md # Feature documentation
│ └── index.ts # Barrel export
│
├── settings/ # Simple feature - flat structure
│ ├── settings-tab.ts # Single service file (no services/ needed)
│ ├── settings-status-service.ts
│ ├── README.md
│ └── index.ts
| Category | Create subdirectory when... |
|---|---|
store/ |
Feature has Zustand state (always use for slices) |
services/ |
2+ service files, or 1 complex service |
utils/ |
2+ utility files |
components/ |
2+ React components |
types/ |
2+ type definition files |
styles/ |
2+ style files |
Guidance: Use subdirectories for semantic clarity, not just file count. A single store/slice.ts is clearer than feature-slice.ts at the root.
| File Type | Naming Pattern | Example |
|---|---|---|
| Store slice | store/slice.ts |
dreamnode/store/slice.ts |
| Service | *-service.ts |
git-dreamnode-service.ts |
| Utility | *-utils.ts or descriptive |
git-utils.ts, vault-scanner.ts |
| Component | PascalCase.tsx |
DreamNode3D.tsx |
| Types | *.ts (descriptive) |
dreamnode.ts |
| Commands | commands.ts |
commands.ts |
| Barrel | index.ts |
index.ts |
Services (in services/):
- Have state or manage side effects
- Orchestrate multiple operations
- May hold references (singletons, caches)
- Example:
GitDreamNodeService- manages node CRUD with store updates
Utilities (in utils/):
- Pure functions, stateless
- Single-purpose operations
- Easily testable in isolation
- Example:
gitUtils.getGitStatus(repoPath)- runs git command, returns result
Features own their settings panel sections through settings-section.ts:
// features/my-feature/settings-section.ts
// Status check - called by settings aggregator
export async function checkMyFeatureStatus(): Promise<FeatureStatus> {
// Feature-specific status logic
}
// Settings UI - rendered in settings panel
export function createMyFeatureSettingsSection(
containerEl: HTMLElement,
plugin: InterBrainPlugin,
status: FeatureStatus | undefined,
refreshDisplay: () => Promise<void>
): void {
// Feature-specific settings UI
}The settings feature is a thin orchestrator that:
- Owns global settings (AI Integration, Keyboard Shortcuts, Advanced)
- Delegates feature sections to
create*SettingsSection()functions - Aggregates status via
check*Status()functions
This pattern ensures features own their configuration UI and status checking logic.
Every feature has an index.ts that exports its public API:
// features/dreamnode/index.ts
// Store (state management)
export * from './store/slice';
// Types
export * from './types/dreamnode';
// Services (orchestrators)
export { GitDreamNodeService } from './services/git-dreamnode-service';
// Utilities (namespaced to avoid collisions)
export * as gitUtils from './utils/git-utils';
export * as vaultScanner from './utils/vault-scanner';
// Components
export { default as DreamNode3D } from './components/DreamNode3D';
// Commands
export { registerDreamNodeCommands } from './commands';Namespace exports (export * as gitUtils) prevent naming collisions between features.
| Feature | Purpose | Complexity |
|---|---|---|
| DreamNode Family | ||
| dreamnode | Core: types, services, git operations, 3D visualization | High |
| dreamnode-creator | Creation workflow UI (builds on dreamnode) | Medium |
| dreamnode-editor | Editing workflow UI (builds on dreamnode) | Medium |
| Layout & Navigation | ||
| constellation-layout | Fibonacci sphere layout + node filtering for scalability (ephemeral loading) | High |
| liminal-web-layout | Focused node with related nodes in rings | Medium |
| songline | Songline navigation feature | Low |
| Content & Canvas | ||
| dreamweaving | Canvas parsing, submodules, DreamSong playback | High |
| drag-and-drop | File and URL drop handling | Medium |
| web-link-analyzer | AI-powered URL content analysis | Low |
| Search & AI | ||
| search | Search overlay and result display | Low |
| semantic-search | Vector embeddings and similarity search | High |
| conversational-copilot | AI conversation mode with node invocation | Medium |
| Collaboration | ||
| social-resonance-filter | Radicle P2P integration & commit propagation | Medium |
| coherence-beacon | Node synchronization beacons | Medium |
| github-publishing | GitHub sharing + Pages broadcast | Medium |
| video-calling | Video call initiation (FaceTime, future: more) | Low |
| UI & System | ||
| action-buttons | Action menu around nodes | Low |
| realtime-transcription | Voice transcription via Python backend | Medium |
| settings | Plugin settings tab (thin orchestrator) | Low |
| dreamnode-updater | DreamNode update workflow (preview, apply) | Low |
| uri-handler | interbrain:// protocol handling | Low |
| feedback | Bug reporting and feedback system | Low |
| tutorial | Onboarding with Manim-style text animations | Low |
-
Create the directory:
src/features/my-feature/ -
Add README.md with:
- Purpose (1-2 sentences)
- Key files description
- Main exports
- Architecture notes (if complex)
-
Add index.ts barrel export
-
Choose structure based on complexity:
- Simple (1-3 files): Flat structure
- Medium (4-8 files): Add subdirectories as needed
- Complex (9+ files): Full subdirectory structure
-
Register with core (if needed):
- Add slice to
core/store/interbrain-store.ts - Add to core README feature table
- Add to this README feature catalog
- Add slice to
When working in features:
- Read the feature README first - understand the domain before making changes
- Follow existing patterns - if the feature uses
services/, add services there - Use barrel exports - import from
features/Xnotfeatures/X/services/thing - Keep features isolated - features should not import from each other (use core as intermediary)
- Services orchestrate, utils compute - put stateful logic in services, pure functions in utils