|
1 | | -# Mood Palette Generator |
| 1 | +# R1 Creations Static Website - Implementation Plan |
2 | 2 |
|
3 | | -A creative tool for the R1 device that captures images, analyzes their colors, and generates harmonious color palettes using AI. |
| 3 | +## Project Overview |
| 4 | +A static website designed for a 240x282 browser window with interactive features for testing R1 Creations plugin capabilities using the Creations SDK. This test app demonstrates major SDK features including hardware events, LLM integration, and sensor data. |
4 | 5 |
|
5 | | -## Features |
| 6 | +## Technical Specifications |
| 7 | +- **Browser Size**: 240x282 pixels (fixed) |
| 8 | +- **Type**: Static HTML/CSS/JavaScript |
| 9 | +- **API**: R1 Creations SDK only (no direct WebSocket usage) |
| 10 | +- **Features**: Hardware controls, LLM integration, sensor data |
6 | 11 |
|
7 | | -- **Camera Integration**: Use the R1's camera to capture images |
8 | | -- **AI Color Analysis**: Leverage the LLM to analyze and interpret colors |
9 | | -- **Palette Generation**: Create beautiful color palettes from captured images |
10 | | -- **Email Sharing**: Send your favorite palettes directly to your email |
11 | | -- **Secure Storage**: Save favorite palettes to the device's secure storage |
12 | | -- **QR Code Sharing**: Generate QR codes for easy sharing of your palettes |
| 12 | +## Architecture |
13 | 13 |
|
14 | | -## How to Use |
| 14 | +### File Structure |
| 15 | +``` |
| 16 | +/ |
| 17 | +├── index.html # Main SPA with menu navigation |
| 18 | +├── css/ |
| 19 | +│ └── styles.css # Shared styles (240x282 optimized) |
| 20 | +├── js/ |
| 21 | +│ ├── app.js # Main application logic & navigation |
| 22 | +│ ├── hardware.js # Hardware page - button events & accelerometer |
| 23 | +│ ├── data.js # Data page - LLM interactions & dynamic theming |
| 24 | +│ └── speak.js # Speak page - TTS |
| 25 | +└── reference/ |
| 26 | + └── creation-triggers.md # SDK documentation |
| 27 | +``` |
15 | 28 |
|
16 | | -1. Navigate to the "Mood Palette" section in the R1 Creations SDK demo |
17 | | -2. Point the camera at an object or scene that inspires you |
18 | | -3. Click "Capture Image" to take a snapshot |
19 | | -4. Click "Analyze Colors" to process the image |
20 | | -5. Click "Generate Palette" to create a color palette |
21 | | -6. Enter your email and click "Email Palette" to send it to yourself |
22 | | -7. Click "Save to Favorites" to store the palette in secure storage |
| 29 | +## Implementation Plan |
| 30 | + |
| 31 | +## Current Implementation Status |
| 32 | + |
| 33 | +### ✅ Completed Features |
| 34 | + |
| 35 | +1. **Navigation System** |
| 36 | + - Hamburger menu (top-right) with slide-in drawer |
| 37 | + - Three pages: Hardware, Data, Speak |
| 38 | + - Dynamic page loading without refresh |
| 39 | + - Active page highlighting |
| 40 | + |
| 41 | +2. **Hardware Page** |
| 42 | + - UP/DOWN/PTT buttons with LED blink animations |
| 43 | + - Real-time accelerometer display (X, Y, Z axes) |
| 44 | + - Start/Stop accelerometer toggle |
| 45 | + - Hardware event listeners for scroll wheel and side button |
| 46 | + |
| 47 | +3. **Data Page** |
| 48 | + - Compact horizontal button layout |
| 49 | + - Chat window with scrollable history |
| 50 | + - Cat Facts: Requests and parses JSON array of facts |
| 51 | + - Dinos: Simple text responses |
| 52 | + - Paint toggle: Changes app border color dynamically |
| 53 | + - Clear chat functionality |
| 54 | + |
| 55 | +4. **Speak Page** |
| 56 | + - Text area for message input |
| 57 | + - R1 speaker output option |
| 58 | + - Status indicator |
| 59 | + |
| 60 | + |
| 61 | +### Phase 1: Foundation Setup |
| 62 | +1. **Base HTML Structure** |
| 63 | + - Create index.html with responsive layout for 240x282px |
| 64 | + - Implement menu button (top-right hamburger icon) |
| 65 | + - Set up navigation drawer with 3 menu items |
| 66 | + - Configure viewport meta tags for fixed sizing |
| 67 | + |
| 68 | +2. **Navigation System** |
| 69 | + - Single-page application with dynamic content loading |
| 70 | + - Menu slides in from right side |
| 71 | + - Smooth transitions between pages |
| 72 | + - Active page highlighting |
| 73 | + |
| 74 | +3. **Core Styling** |
| 75 | + - CSS Grid/Flexbox for 240x282 constraint |
| 76 | + - Dark theme with high contrast for small screen |
| 77 | + - Touch-friendly button sizes (min 44x44px) |
| 78 | + - Consistent 5px border for dynamic coloring |
| 79 | + |
| 80 | +## Usage Examples |
| 81 | + |
| 82 | +### Running the App |
| 83 | +1. Deploy as an R1 Creation plugin |
| 84 | +2. Open the app on your R1 device |
| 85 | +3. Use the hamburger menu to navigate between pages |
| 86 | + |
| 87 | +### Hardware Page Testing |
| 88 | +```javascript |
| 89 | +// Scroll wheel events trigger LED blinks |
| 90 | +// UP scroll → UP LED blinks green |
| 91 | +// DOWN scroll → DOWN LED blinks green |
| 92 | +// PTT click → PTT LED blinks green |
| 93 | + |
| 94 | +// Accelerometer shows real-time values |
| 95 | +// X: -1.00 to 1.00 (left/right tilt) |
| 96 | +// Y: -1.00 to 1.00 (forward/back tilt) |
| 97 | +// Z: -1.00 to 1.00 (face up/down) |
| 98 | +``` |
| 99 | + |
| 100 | +### Data Page Examples |
| 101 | + |
| 102 | +```javascript |
| 103 | +// Cat Facts Button |
| 104 | +PluginMessageHandler.postMessage(JSON.stringify({ |
| 105 | + message: 'Tell me 5 facts about cats. Respond ONLY with valid JSON in this exact format: {"facts":["fact1","fact2","fact3","fact4","fact5"]}', |
| 106 | + useLLM: true |
| 107 | +})); |
| 108 | + |
| 109 | +// Expected Response (in data.data or data.message): |
| 110 | +{ |
| 111 | + "facts": [ |
| 112 | + "Cats have 32 muscles in each ear", |
| 113 | + "A group of cats is called a clowder", |
| 114 | + "Cats sleep for 13-14 hours a day", |
| 115 | + "A cat's nose print is unique", |
| 116 | + "Cats can rotate their ears 180 degrees" |
| 117 | + ] |
| 118 | +} |
| 119 | + |
| 120 | +// Display in chat: |
| 121 | +// Fact 1: Cats have 32 muscles in each ear |
| 122 | +// Fact 2: A group of cats is called a clowder |
| 123 | +// ... |
| 124 | + |
| 125 | +// Paint Color Button |
| 126 | +PluginMessageHandler.postMessage(JSON.stringify({ |
| 127 | + message: 'Give me the hex color code for red. Return ONLY valid JSON in this exact format: {"paint":"#hexcode"}', |
| 128 | + useLLM: true |
| 129 | +})); |
| 130 | + |
| 131 | +// Expected Response: |
| 132 | +{"paint": "#ff0000"} |
| 133 | +// Result: App border changes to red |
| 134 | +``` |
| 135 | + |
| 136 | +### Speak Page Examples |
| 137 | + |
| 138 | +```javascript |
| 139 | +// Speak with R1 voice output |
| 140 | +PluginMessageHandler.postMessage(JSON.stringify({ |
| 141 | + message: "Hello, this is a test message", |
| 142 | + useLLM: true, |
| 143 | + wantsR1Response: true // Speaks through R1 speaker |
| 144 | +})); |
| 145 | + |
| 146 | +// Silent processing (no voice) |
| 147 | +PluginMessageHandler.postMessage(JSON.stringify({ |
| 148 | + message: "Process this silently", |
| 149 | + useLLM: true, |
| 150 | + wantsR1Response: false |
| 151 | +})); |
| 152 | +``` |
23 | 153 |
|
24 | 154 | ## Technical Details |
25 | 155 |
|
26 | | -This plugin demonstrates several key capabilities of the R1 platform: |
| 156 | +### Message Handling Flow |
| 157 | + |
| 158 | +```javascript |
| 159 | +// Plugin sends message |
| 160 | +PluginMessageHandler.postMessage(JSON.stringify(payload)); |
| 161 | + |
| 162 | +// App receives response |
| 163 | +window.onPluginMessage = function(data) { |
| 164 | + // Response can be in data.data (JSON string) or data.message (text) |
| 165 | + if (data.data) { |
| 166 | + const parsed = JSON.parse(data.data); |
| 167 | + // Handle structured data |
| 168 | + } |
| 169 | + if (data.message) { |
| 170 | + // Handle text message |
| 171 | + } |
| 172 | +}; |
| 173 | +``` |
| 174 | + |
| 175 | +### Storage API Usage |
| 176 | + |
| 177 | +```javascript |
| 178 | +// Save to persistent storage |
| 179 | +await window.creationStorage.plain.setItem( |
| 180 | + 'app_settings', |
| 181 | + btoa(JSON.stringify(settings)) |
| 182 | +); |
| 183 | + |
| 184 | +// Load from storage |
| 185 | +const stored = await window.creationStorage.plain.getItem('app_settings'); |
| 186 | +const settings = JSON.parse(atob(stored)); |
| 187 | +``` |
| 188 | + |
| 189 | +### Hardware Event Registration |
| 190 | + |
| 191 | +```javascript |
| 192 | +// Scroll wheel |
| 193 | +window.addEventListener('scrollUp', handleScrollUp); |
| 194 | +window.addEventListener('scrollDown', handleScrollDown); |
| 195 | + |
| 196 | +// Side button (PTT) |
| 197 | +window.addEventListener('sideClick', handleClick); |
| 198 | +window.addEventListener('longPressStart', handleLongPressStart); |
| 199 | +window.addEventListener('longPressEnd', handleLongPressEnd); |
| 200 | + |
| 201 | +// Accelerometer |
| 202 | +window.creationSensors.accelerometer.start((data) => { |
| 203 | + // data = { x: 0.1, y: -0.2, z: 0.98 } |
| 204 | +}, { frequency: 60 }); |
| 205 | +``` |
| 206 | + |
| 207 | +## Testing Guide |
| 208 | + |
| 209 | +### Quick Test Checklist |
| 210 | + |
| 211 | +1. **Menu Navigation** |
| 212 | + - [ ] Hamburger button opens menu |
| 213 | + - [ ] All 3 pages load correctly |
| 214 | + - [ ] Menu closes after selection |
| 215 | + |
| 216 | +2. **Hardware Page** |
| 217 | + - [ ] Scroll up → UP LED blinks |
| 218 | + - [ ] Scroll down → DOWN LED blinks |
| 219 | + - [ ] PTT click → PTT LED blinks |
| 220 | + - [ ] Accelerometer shows live data |
| 221 | + |
| 222 | +3. **Data Page** |
| 223 | + - [ ] Cat Facts returns 5 facts |
| 224 | + - [ ] Dino button returns text |
| 225 | + - [ ] Paint button changes border color |
| 226 | + - [ ] Chat window scrolls properly |
| 227 | + |
| 228 | +4. **Speak Page** |
| 229 | + - [ ] R1 speaks the text |
| 230 | + - [ ] Status updates show |
| 231 | + |
| 232 | +## Troubleshooting |
| 233 | + |
| 234 | +### Common Issues |
| 235 | + |
| 236 | +**Accelerometer not working:** |
| 237 | +- Check if `window.creationSensors` is available |
| 238 | +- Verify device has accelerometer support |
| 239 | +- Check console for permission errors |
| 240 | + |
| 241 | +**LLM responses not parsing:** |
| 242 | +- Check console for response format |
| 243 | +- Verify JSON is valid (double quotes, not single) |
| 244 | +- Check both `data.data` and `data.message` fields |
27 | 245 |
|
28 | | -- Camera access using WebRTC APIs |
29 | | -- Image processing and color extraction |
30 | | -- AI integration through the PluginMessageHandler |
31 | | -- Secure data storage using creationStorage.secure |
32 | | -- Email functionality through LLM integration |
| 246 | +**Border color not changing:** |
| 247 | +- Ensure hex code is valid format (#RRGGBB) |
| 248 | +- Check if `updateAppBorderColor()` is called |
| 249 | +- Verify CSS border property on #app element |
33 | 250 |
|
34 | | -## Future Enhancements |
| 251 | +## Important Notes |
35 | 252 |
|
36 | | -- More sophisticated color analysis algorithms |
37 | | -- Palette naming using AI |
38 | | -- Social sharing features |
39 | | -- Export to design tools |
40 | | -- Advanced palette manipulation tools |
| 253 | +- **No WebSocket Usage**: All communication happens through the R1 Creations SDK JavaScript channels (PluginMessageHandler, CreationStorageHandler, etc.) |
| 254 | +- The 240x282px constraint requires careful UI design |
| 255 | +- Prioritize essential features for small screen |
| 256 | +- Use progressive enhancement for advanced features |
| 257 | +- Consider battery impact of continuous sensor polling |
| 258 | +- All plugin messages are handled via `window.onPluginMessage` callback |
| 259 | +- Hardware events use native window event listeners provided by the SDK |
0 commit comments