README.md
1 # DreamNode Feature 2 3 **Purpose**: Core DreamNode management - the fundamental unit of InterBrain's spatial knowledge representation. 4 5 ## Overview 6 7 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. 8 9 **Derivative features** build on this foundation: 10 - `dreamnode-creator/` - Creation workflow UI 11 - `dreamnode-editor/` - Editing workflow UI 12 13 ## Directory Structure 14 15 ``` 16 dreamnode/ 17 ├── store/ 18 │ └── slice.ts # Zustand state (dreamNodes Map, flip state) 19 ├── types/ 20 │ └── dreamnode.ts # Core interfaces (DreamNode, UDDFile, GitStatus, etc.) 21 ├── services/ 22 │ ├── git-dreamnode-service.ts # CRUD orchestrator with git + store sync 23 │ ├── udd-service.ts # .udd file read/write 24 │ └── dreamnode-conversion-service.ts # Convert existing folders to DreamNodes 25 ├── utils/ 26 │ ├── git-utils.ts # Stateless git commands (status, stash, commit) 27 │ ├── vault-scanner.ts # Filesystem discovery (scan, validate, read) 28 │ ├── repo-initializer.ts # Repository creation (init, template, commit) 29 │ ├── title-sanitization.ts # Title → PascalCase folder name 30 │ └── git-operations.ts # Legacy class (deprecated) 31 ├── components/ 32 │ ├── DreamNode3D.tsx # Main 3D component with flip animations 33 │ ├── DreamTalkSide.tsx # Front face HTML (selected node, buttons) 34 │ ├── DreamTalkSprite.tsx # Front face WebGL (non-selected nodes) 35 │ ├── DreamTalkMesh.tsx # Legacy mesh-based WebGL approach 36 │ ├── DreamSongSide.tsx # Back face (canvas content) 37 │ └── PDFPreview.tsx # PDF rendering 38 ├── hooks/ 39 │ ├── useContentTexture.ts # Load media into THREE.Texture via getResourcePath 40 │ └── useMediaTexture.ts # Legacy base64-based texture loading 41 ├── shaders/ 42 │ ├── circularClipShader.ts # Circular clip with border and vignette 43 │ └── radialGradient.ts # Radial fade-to-black shader 44 ├── styles/ 45 │ ├── dreamNodeStyles.ts # Colors, dimensions, glows 46 │ └── dreamNodeAnimations.css 47 ├── DreamNode-template/ # Git template for new DreamNode repos 48 │ ├── hooks/ # Git hooks (pre-commit, post-commit) 49 │ ├── udd # Template .udd file 50 │ ├── LICENSE # AGPL license 51 │ └── README.md # Template README 52 ├── commands.ts # Obsidian command palette (flip, fullscreen) 53 ├── test-utils.ts # Mock factories for testing 54 ├── index.ts # Barrel export 55 └── README.md 56 ``` 57 58 ## Main Exports 59 60 ```typescript 61 // Store (state management) 62 export * from './store/slice'; 63 // → DreamNodeSlice, DreamNodeData, createDreamNodeSlice 64 65 // Types 66 export * from './types/dreamnode'; 67 // → DreamNode, UDDFile, MediaFile, CanvasFile, GitStatus 68 69 // Services 70 export { GitDreamNodeService } from './services/git-dreamnode-service'; 71 export { UDDService } from './services/udd-service'; 72 73 // Utilities (namespaced) 74 export * as gitUtils from './utils/git-utils'; 75 export * as vaultScanner from './utils/vault-scanner'; 76 export * as repoInitializer from './utils/repo-initializer'; 77 export { sanitizeTitleToPascalCase } from './utils/title-sanitization'; 78 79 // Components 80 export { default as DreamNode3D } from './components/DreamNode3D'; 81 export type { DreamNode3DRef } from './components/DreamNode3D'; 82 export { DreamTalkSide } from './components/DreamTalkSide'; 83 export { DreamTalkSprite } from './components/DreamTalkSprite'; 84 export { DreamSongSide } from './components/DreamSongSide'; 85 86 // Hooks 87 export { useContentTexture } from './hooks/useContentTexture'; 88 89 // Shaders 90 export * from './shaders/circularClipShader'; 91 92 // Commands 93 export { registerDreamNodeCommands } from './commands'; 94 ``` 95 96 ## Commands 97 98 | Command | Hotkey | Description | 99 |---------|--------|-------------| 100 | Flip Selected DreamNode | `Ctrl+J` | Toggle between DreamTalk and DreamSong | 101 | Flip DreamNode to Front | - | Show DreamTalk side | 102 | Flip DreamNode to Back | - | Show DreamSong side | 103 | Open DreamTalk Full-Screen | - | Full-screen DreamTalk media | 104 | Open DreamSong Full-Screen | - | Open DreamSong in Obsidian tab | 105 | Reveal Containing DreamNode | - | Focus DreamNode containing current file | 106 | Convert Folder to DreamNode | - | Initialize folder as DreamNode repository | 107 108 ## Architecture 109 110 ### Two-Tier Type System 111 112 | Layer | Type | Purpose | 113 |-------|------|---------| 114 | Disk | `UDDFile` | JSON persisted in `.udd` file | 115 | Runtime | `DreamNode` | Includes resolved media, position, connections | 116 117 ### Service vs Utility Pattern 118 119 **Services** (stateful orchestrators): 120 - `GitDreamNodeService` - Coordinates git operations + store updates 121 122 **Utilities** (stateless functions): 123 - `gitUtils.*` - Pure git command wrappers 124 - `vaultScanner.*` - Pure filesystem discovery 125 - `repoInitializer.*` - Pure repo creation steps 126 127 ### Git-Native Storage 128 129 - Each DreamNode = git repository in vault root 130 - `.udd` file = single JSON with all metadata (UUID, title, type, relationships) 131 - `DreamNode-template/` provides hooks for bidirectional relationship tracking 132 - Git hooks maintain `submodules` ↔ `supermodules` consistency 133 134 ### Relationship Storage 135 136 | Node Type | Storage | Reason | 137 |-----------|---------|--------| 138 | Dreamer | `liminal-web.json` (gitignored) | Private social connections | 139 | Dream | Discovered via git submodules | Bidirectional during vault scan | 140 141 ### Visual Git State 142 143 | Glow | Meaning | 144 |------|---------| 145 | Red | Uncommitted or stashed (work-in-progress) | 146 | Blue | Committed but unpushed (ready to share) | 147 | None | Clean and synchronized | 148 149 ## Notes 150 151 - **Media loading**: Handled directly by `useContentTexture` hook (simplified in v0.14.0) 152 - **Radicle failures**: Don't block node creation (graceful degradation) 153 - **Legacy `git-operations.ts`**: Deprecated, use `gitUtils` namespace 154 - **⚠️ Creator Mode**: DEPRECATED - The `creatorMode` state 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. 155 156 ## WebGL Rendering Architecture 157 158 The DreamTalk visualization uses a dual-mode rendering strategy: 159 160 ### Rendering Modes 161 162 | Mode | Component | When Used | 163 |------|-----------|-----------| 164 | WebGL Sprite | `DreamTalkSprite` | Non-selected nodes (performance) | 165 | HTML Overlay | `DreamTalkSide` | Selected node (buttons, interactions) | 166 167 ### Texture Pipeline 168 169 ``` 170 Media File → getResourcePath() → THREE.Texture → Circular Clip Shader → Screen 171 ``` 172 173 1. **`useContentTexture`**: Loads media via Obsidian's `getResourcePath()` API 174 - Bypasses Electron `file://` restrictions 175 - No base64 encoding (better performance, no storage quota issues) 176 - Supports images, videos, PDFs 177 178 2. **`circularClipShader`**: WebGL shader for DreamTalk appearance 179 - Circular clipping with soft edges 180 - Type-colored border ring (blue=Dream, red=Dreamer) 181 - Radial vignette fade-to-black 182 - Aspect ratio correction (cover fit) 183 184 ### Why Dual Rendering? 185 186 - **WebGL sprites** are GPU-native and scale to hundreds of nodes 187 - **HTML overlays** provide DOM interactivity (flip button, fullscreen) 188 - Selected node transitions from sprite to HTML when animation completes 189 - Prevents visual artifacts on high-DPI displays from sprite/HTML mismatch