Purpose: Core DreamNode management - the fundamental unit of InterBrain's spatial knowledge representation.
DreamNodes are git-backed repositories representing either ideas (Dreams) or people (Dreamers). This feature owns their complete lifecycle: types, state, persistence, git operations, and 3D visualization.
Derivative features build on this foundation:
dreamnode-creator/- Creation workflow UIdreamnode-editor/- Editing workflow UI
dreamnode/
├── store/
│ └── slice.ts # Zustand state (dreamNodes Map, flip state)
├── types/
│ └── dreamnode.ts # Core interfaces (DreamNode, UDDFile, GitStatus, etc.)
├── services/
│ ├── git-dreamnode-service.ts # CRUD orchestrator with git + store sync
│ ├── udd-service.ts # .udd file read/write
│ └── dreamnode-conversion-service.ts # Convert existing folders to DreamNodes
├── utils/
│ ├── git-utils.ts # Stateless git commands (status, stash, commit)
│ ├── vault-scanner.ts # Filesystem discovery (scan, validate, read)
│ ├── repo-initializer.ts # Repository creation (init, template, commit)
│ ├── title-sanitization.ts # Title → PascalCase folder name
│ └── git-operations.ts # Legacy class (deprecated)
├── components/
│ ├── DreamNode3D.tsx # Main 3D component with flip animations
│ ├── DreamTalkSide.tsx # Front face HTML (selected node, buttons)
│ ├── DreamTalkSprite.tsx # Front face WebGL (non-selected nodes)
│ ├── DreamTalkMesh.tsx # Legacy mesh-based WebGL approach
│ ├── DreamSongSide.tsx # Back face (canvas content)
│ └── PDFPreview.tsx # PDF rendering
├── hooks/
│ ├── useContentTexture.ts # Load media into THREE.Texture via getResourcePath
│ └── useMediaTexture.ts # Legacy base64-based texture loading
├── shaders/
│ ├── circularClipShader.ts # Circular clip with border and vignette
│ └── radialGradient.ts # Radial fade-to-black shader
├── styles/
│ ├── dreamNodeStyles.ts # Colors, dimensions, glows
│ └── dreamNodeAnimations.css
├── DreamNode-template/ # Git template for new DreamNode repos
│ ├── hooks/ # Git hooks (pre-commit, post-commit)
│ ├── udd # Template .udd file
│ ├── LICENSE # AGPL license
│ └── README.md # Template README
├── commands.ts # Obsidian command palette (flip, fullscreen)
├── test-utils.ts # Mock factories for testing
├── index.ts # Barrel export
└── README.md
// Store (state management)
export * from './store/slice';
// → DreamNodeSlice, DreamNodeData, createDreamNodeSlice
// Types
export * from './types/dreamnode';
// → DreamNode, UDDFile, MediaFile, CanvasFile, GitStatus
// Services
export { GitDreamNodeService } from './services/git-dreamnode-service';
export { UDDService } from './services/udd-service';
// Utilities (namespaced)
export * as gitUtils from './utils/git-utils';
export * as vaultScanner from './utils/vault-scanner';
export * as repoInitializer from './utils/repo-initializer';
export { sanitizeTitleToPascalCase } from './utils/title-sanitization';
// Components
export { default as DreamNode3D } from './components/DreamNode3D';
export type { DreamNode3DRef } from './components/DreamNode3D';
export { DreamTalkSide } from './components/DreamTalkSide';
export { DreamTalkSprite } from './components/DreamTalkSprite';
export { DreamSongSide } from './components/DreamSongSide';
// Hooks
export { useContentTexture } from './hooks/useContentTexture';
// Shaders
export * from './shaders/circularClipShader';
// Commands
export { registerDreamNodeCommands } from './commands';| Command | Hotkey | Description |
|---|---|---|
| Flip Selected DreamNode | Ctrl+J |
Toggle between DreamTalk and DreamSong |
| Flip DreamNode to Front | - | Show DreamTalk side |
| Flip DreamNode to Back | - | Show DreamSong side |
| Open DreamTalk Full-Screen | - | Full-screen DreamTalk media |
| Open DreamSong Full-Screen | - | Open DreamSong in Obsidian tab |
| Reveal Containing DreamNode | - | Focus DreamNode containing current file |
| Convert Folder to DreamNode | - | Initialize folder as DreamNode repository |
| Layer | Type | Purpose |
|---|---|---|
| Disk | UDDFile |
JSON persisted in .udd file |
| Runtime | DreamNode |
Includes resolved media, position, connections |
Services (stateful orchestrators):
GitDreamNodeService- Coordinates git operations + store updates
Utilities (stateless functions):
gitUtils.*- Pure git command wrappersvaultScanner.*- Pure filesystem discoveryrepoInitializer.*- Pure repo creation steps
- Each DreamNode = git repository in vault root
.uddfile = single JSON with all metadata (UUID, title, type, relationships)DreamNode-template/provides hooks for bidirectional relationship tracking- Git hooks maintain
submodules↔supermodulesconsistency
| Node Type | Storage | Reason |
|---|---|---|
| Dreamer | liminal-web.json (gitignored) |
Private social connections |
| Dream | Discovered via git submodules | Bidirectional during vault scan |
| Glow | Meaning |
|---|---|
| Red | Uncommitted or stashed (work-in-progress) |
| Blue | Committed but unpushed (ready to share) |
| None | Clean and synchronized |
- Media loading: Handled directly by
useContentTexturehook (simplified in v0.14.0) - Radicle failures: Don't block node creation (graceful degradation)
- Legacy
git-operations.ts: Deprecated, usegitUtilsnamespace ⚠️ Creator Mode: DEPRECATED - ThecreatorModestate in the store slice is leftover from an early UX experiment and will be removed in a future update. Do not build new features on this pattern.
The DreamTalk visualization uses a dual-mode rendering strategy:
| Mode | Component | When Used |
|---|---|---|
| WebGL Sprite | DreamTalkSprite |
Non-selected nodes (performance) |
| HTML Overlay | DreamTalkSide |
Selected node (buttons, interactions) |
Media File → getResourcePath() → THREE.Texture → Circular Clip Shader → Screen
-
useContentTexture: Loads media via Obsidian'sgetResourcePath()API- Bypasses Electron
file://restrictions - No base64 encoding (better performance, no storage quota issues)
- Supports images, videos, PDFs
- Bypasses Electron
-
circularClipShader: WebGL shader for DreamTalk appearance- Circular clipping with soft edges
- Type-colored border ring (blue=Dream, red=Dreamer)
- Radial vignette fade-to-black
- Aspect ratio correction (cover fit)
- WebGL sprites are GPU-native and scale to hundreds of nodes
- HTML overlays provide DOM interactivity (flip button, fullscreen)
- Selected node transitions from sprite to HTML when animation completes
- Prevents visual artifacts on high-DPI displays from sprite/HTML mismatch