Feature Spec: The Digital Twin (Doc 06)
Product and implementation specification for Homey's flexible location hierarchy, items, optional grids, and inventory workflows.
|
Version 2.0 Update: This spec has been updated to reflect the implemented Location/Item + Optional Grid architecture, which replaces the original rigid Zone→Unit→Cell (2x2) design. The new approach provides more flexibility for real-world home organization. Version 2.1 Update: Added domain extensibility notes. While MVP 1.0 focuses on Kitchen/Grocery items, the Location and Item architecture supports multiple domains (Wardrobe, Toolbox, etc.) in future phases. |
Domain Extensibility
The Digital Twin architecture is domain-agnostic:
-
Locations can represent any physical space (Kitchen, Bedroom, Garage)
-
Items use a sealed class hierarchy supporting domain-specific extensions:
-
GroceryItem(MVP 1.0) - expiry dates, categories, quantities -
ClothingItem(Future) - size, color, material -
ToolItem(Future) - brand, condition
-
Locations are not restricted to a single domain. A "Garage" location can contain both ToolItem (tools) and GroceryItem (overflow pantry storage).
1. User Goal
To provide a spatial and categorical view of household items, allowing users to: * Quickly locate items using search or filters * Optionally map items spatially using flexible grid layouts * Group items by category regardless of physical location * Track expiry dates and consumption patterns
2. Architecture Overview
Flexible Hierarchy (Updated Design)
Concept: Locations form a flexible tree structure with optional spatial organization.
Structure: * Location (e.g., Kitchen → Pantry → Top Shelf) - Hierarchical: Can have parent and children - Flexible depth: As many levels as needed - Optional grid: Each location can enable grid view independently
-
Items (e.g., Organic Walnuts, Blue Rice Container)
-
Belong to one location
-
May have grid position (row, column) or be unassigned
-
Categorized for list view grouping
-
Key Change from v1.0: * ❌ Removed rigid Zone→Unit→Cell (2x2) structure * ✅ Added flexible Location hierarchy with optional variable grids (2x2 to 6x6)
3. Data Model (Implemented)
Location Entity
Location {
id: UUID
name: String
parentId: UUID? (null for root locations)
gridConfig: GridConfig? (null if grid disabled)
createdAt: Date
}
GridConfig {
rows: Int (2-6)
columns: Int (2-6)
enabled: Boolean
}
Examples: * Kitchen (parent=null, grid=null) → Pantry (parent=Kitchen, grid={3x3, enabled}) → Top Shelf (parent=Pantry, grid={2x4, enabled}) → Fridge (parent=Kitchen, grid={4x3, enabled}) * Garage (parent=null, grid=null) → Tool Rack (parent=Garage, grid={2x5, enabled})
Item Entity
Item {
id: UUID
name: String
locationId: UUID
gridPosition: GridPosition? (null if unassigned)
sortOrder: Int
photoUri: String?
createdAt: Date
}
GridPosition {
row: Int
column: Int
}
GroceryItem extends Item {
brand: String?
category: ItemCategory
expiryDate: Date?
}
ItemCategory enum {
DAIRY, PRODUCE, MEAT, FROZEN,
BEVERAGES, SNACKS, PANTRY, GENERAL
}
Key Properties: * Nullable gridPosition → Items exist without spatial assignment * Hierarchy lives in Location, not Item * GroceryItem extends Item (joined-table inheritance)
4. User Interface & Workflows
4.1 Location Navigation (Accordion View)
Screen: LocationScreen
Visual: Vertical scrollable list with expandable location headers.
Interaction: 1. User sees root locations collapsed: [ > Kitchen ] [ > Garage ] 2. Tapping "Kitchen" expands to show children: Pantry, Fridge, Freezer 3. Tapping "Pantry" navigates to ItemScreen for that location
Features: * Grid badge indicator: Shows 📊 icon if location has grid enabled * Smooth expand/collapse animations * Persistent expansion state (preserved across app restarts) * FAB (+) button to add new locations
4.2 Item View (Dual-Mode Display)
Screen: ItemScreen
Two View Modes:
A. Grid View (When grid enabled)
Trigger: Location has grid configuration enabled
Visual: NxM grid based on location’s grid config (e.g., 3x3, 4x4)
Interaction: * Empty cells show "+" icon (tap to quick-assign) * Filled cells show item count badge if multiple items * Tapping cell opens item list for that position * Tapping specific item shows item details
Layout:
+-------+-------+-------+
| 🥛 | ☕×3 | + | Row 1
+-------+-------+-------+
| 🍞 | + | 🧀×2 | Row 2
+-------+-------+-------+
| + | 🥜 | + | Row 3
+-------+-------+-------+
Col 1 Col 2 Col 3
B. List View (Default or when grid disabled)
Visual: Category-grouped list with section headers
Grouping: Items grouped by ItemCategory * Section header shows category icon + name * Items within category sorted by expiry date (urgent first) * Empty categories hidden
Layout:
📦 DAIRY (3 items)
🥛 Milk - Expires in 2 days
🧀 Cheddar Cheese - Jan 20
🧈 Butter - Jan 25
🥬 PRODUCE (1 item)
🥕 Carrots - Expires today
☕ BEVERAGES (2 items)
...
4.3 View Mode Toggle
Location: Top app bar (right side)
Behavior: * Only visible when location has grid enabled * Icon: 📋 (List) or 📊 (Grid) * Tapping toggles between Grid and List view * View preference saved per-location
4.4 Search & Filter
Location: Below top app bar
Components: 1. Search Field: Text input with clear button 2. Category Chips: Horizontal scrollable row - All categories shown as chips - Tappable to filter by category - Multi-select supported
Behavior: * Search filters by item name (real-time) * Category filters are additive (OR logic) * Filters apply to both Grid and List views * In Grid view, filtered items remain in their grid positions (non-matching cells fade)
4.5 Unassigned Items Bar
Location: Bottom of screen (always visible if items exist)
Purpose: Surface items without grid positions
Visual: * Floating card with secondary color * Horizontal scrollable chip list * Badge shows total count
Interaction: * Tap item chip → Quick assign dialog (select grid cell) * Long-press chip → Starts drag-to-assign mode (future)
Layout:
┌─────────────────────────────────────┐
│ Unassigned Items [3]│
│ ┌─────┐ ┌────────┐ ┌──────┐ │
│ │Flour│ │Walnuts │ │Coffee│ ··· │
│ └─────┘ └────────┘ └──────┘ │
└─────────────────────────────────────┘
4.6 Grid Configuration
Access: Settings icon in ItemScreen top bar
Dialog Fields: 1. Enable Grid Layout (toggle switch) 2. Rows (slider: 2-6, only if enabled) 3. Columns (slider: 2-6, only if enabled) 4. Preview (live grid preview showing selected dimensions)
Behavior: * Turning off grid → Items keep gridPosition (not deleted) * View switches to List mode automatically * Turning on grid → Items with positions appear in grid * Changing dimensions → Items outside new bounds become unassigned
5. Logic Rules & Edge Cases
| Scenario | Behavior |
|---|---|
Adding new item |
Appears in Unassigned Items Bar (gridPosition = null) |
Assigning to grid cell |
Quick assign dialog shows grid, tap cell to assign |
Cell with multiple items |
Grid cell shows item count badge (e.g., "×3") |
Moving item |
Long-press item → Select new cell from grid overlay |
Deleting location |
All child locations and items CASCADE delete (user warned) |
Grid disabled |
Items retain gridPosition but view shows List mode only |
Search while in Grid |
Grid cells fade if no matching items in that position |
Empty location |
Shows empty state with "Add Item" CTA |
Expiry warnings |
Item cards show red background if expiring within 7 days |
6. Component Architecture (Implemented)
Reusable UI Components
All components built with Jetpack Compose + Material 3:
-
LocationAccordion (
location/components/LocationAccordion.kt)-
Recursive expandable location hierarchy
-
Grid badge indicator
-
Animated expand/collapse
-
-
FlexibleGrid (
location/components/FlexibleGrid.kt)-
Dynamic rows × columns layout
-
Empty cell "+" indicators
-
Multi-item cell support
-
Cell and item click handlers
-
-
ItemCard (
item/components/ItemCard.kt)-
Compact mode (grid cells)
-
Expanded mode (list view)
-
Expiry warning colors
-
Brand, category, position display
-
-
CategoryGroupList (
item/components/CategoryGroupList.kt)-
Category section headers
-
Sorted by expiry within category
-
Lazy loading for performance
-
-
UnassignedItemsBar (
item/components/UnassignedItemsBar.kt)-
Horizontal scrollable chips
-
Item count badge
-
Tap/long-press handlers
-
-
ItemSearchBar (
item/components/ItemSearchBar.kt)-
Text search with clear button
-
Category filter chips
-
Multi-select support
-
7. Future Enhancements
7.1 Drag-and-Drop Assignment
-
Long-press unassigned item chip
-
Drag over grid cells
-
Drop to assign position
-
Visual feedback during drag
7.2 3D Shelf View
-
Support for multiple shelf levels within same unit
-
Swipe gesture to "flip" between shelves
-
Maintains same grid dimensions across shelves
7.3 Bulk Operations
-
Multi-select mode (long-press to activate)
-
Batch move items
-
Batch delete
-
Bulk category assignment
8. Technical Considerations
Performance
-
Large item counts: Use LazyColumn/LazyRow for virtualization
-
Grid rendering: Compose efficiently handles up to 6×6 (36 cells)
-
Search filtering: Debounced search (300ms) to reduce recompositions
-
Image loading: Coil library for efficient photo loading (future)
9. Migration from v1.0 Spec
For teams referencing the original spec:
| Old Concept | New Concept | Notes |
|---|---|---|
Zone |
Location (root) |
Top-level locations (Kitchen, Garage) |
Unit |
Location (child) |
Nested locations (Pantry, Fridge) |
Cell (2x2 fixed) |
GridPosition (flexible) |
Variable grid sizes, optional |
Rigid hierarchy |
Flexible tree |
Any depth, any branching |
Always spatial |
Dual-mode view |
Grid OR List based on preference |
N/A |
Unassigned items |
Items without grid position |
N/A |
Category grouping |
List view groups by ItemCategory |
10. Spec Status
✅ Database schema: Implemented (Room v2) ✅ Domain models: Implemented (Location, Item, GroceryItem) ✅ UI components: Implemented (6 components) ✅ Screens: Implemented (LocationScreen, ItemScreen) ⬜ Item details dialog: TODO ⬜ Drag-and-drop: TODO ⬜ Quick assign dialog: TODO ⬜ Location editing: TODO
Last updated: 2026-01-14 Implemented by: Development Team Original concept: Project Lead Architecture update: Development Team (Jan 2026)