This commit is contained in:
Jason
2026-04-11 00:04:09 -05:00
commit 7a2fffd62e
110 changed files with 51809 additions and 0 deletions
+239
View File
@@ -0,0 +1,239 @@
# Product Encoding System
## Overview
This document describes the hex-based encoding system for creating stable, bookmarkable URLs for product configurations. The system uses bit-packing to create compact strings that encode product type, color, material, and hardware options.
## Design Goals
1. **Stable URLs**: Old bookmarks continue to work even as new options are added
2. **Compact**: Keep URLs under 32-64 characters
3. **Extensible**: Reserve space for future expansion
4. **Reversible**: Each encoded string can be uniquely decoded back to its components
5. **Version-aware**: Support future format changes without breaking old URLs
## Encoding Format
```
Format: v-T-C-M-HHHH-HHHH-HHHH
│ │ │ │ │ │ └── Hardware 3 (optional)
│ │ │ │ │ └─────── Hardware 2 (optional)
│ │ │ │ └──────────── Hardware 1
│ │ │ └────────────── Material (1 hex char, 0-F)
│ │ └──────────────── Color (1 hex char, 0-F)
│ └────────────────── Type (1 hex char, 0-F)
└──────────────────── Version (1 hex char, 0-F)
Example: "0-1-4-1-0D94"
- Version: 0 (using 5-bit encoding per field)
- Type: 1 (Patio Door)
- Color: 4 (White)
- Material: 1 (Aluminum)
- Hardware 1: 0D94 (Lever, Standard, Brass)
Max Length: ~24 characters (with 3 hardware items)
```
## Version 0 Encoding (Current)
### Main Product Attributes (Single Hex Character Each)
Each main attribute uses a single hex character (0-F = 0-15):
#### Type Values (1 hex char)
```
1 = Patio Door
2 = Reserved
3 = Storm Door
4 = Reserved
5 = Storm Window
6 = Reserved
7 = Primary Window
8-F = Reserved (8 slots for future door/window types)
```
#### Color Values (1 hex char)
```
1 = Black
2 = Bronze
3 = Sandstone
4 = White
5 = Tan
6 = Mill
7-F = Reserved (9 slots for future colors)
```
#### Material Values (1 hex char)
```
1 = Aluminum
2 = Vinyl
3-F = Reserved (13 slots for future materials)
```
### Hardware Encoding (4 Hex Characters = FFFF)
Each hardware item uses **4 hex characters** (16 bits) split into fields using **5 bits per field**:
```
16 bits total:
- Bits 10-14: Type (5 bits, 0-31 values)
- Bits 5-9: Style (5 bits, 0-31 values)
- Bits 0-4: Color (5 bits, 0-31 values)
- Bit 15: Reserved (1 bit)
```
#### Hardware Type Values (5 bits = 0-31)
```
0 = None/Not Set
1 = Lever
2 = Pull
3 = Pull Handle
4 = Deadbolt
5 = Hinge
6-31 = Reserved (26 slots)
```
#### Hardware Style Values (5 bits = 0-31)
```
0 = None/Not Set
1 = Standard
2 = Push
3 = Alternative
4 = Contemporary
5 = Traditional
6-31 = Reserved (26 slots)
```
#### Hardware Color Values (5 bits = 0-31)
```
0 = None/Not Set
1 = Brass
2 = White
3 = Black
4 = Satin
5 = Nickel
6 = Bronze
7-31 = Reserved (25 slots)
```
## Bit Math Examples
### Encoding Hardware
```
Example: Lever, Standard, Brass
- Type: 1 (Lever)
- Style: 1 (Standard)
- Color: 1 (Brass)
Binary calculation:
Type (1) = 00001 (bits 10-14)
Style (1) = 00001 (bits 5-9)
Color (1) = 00001 (bits 0-4)
Combined: 0000010000100001 = 0x0421
Hex: "0421"
```
```
Example: Pull Handle, Alternative, Satin
- Type: 3 (Pull Handle)
- Style: 3 (Alternative)
- Color: 4 (Satin)
Binary calculation:
Type (3) = 00011 (bits 10-14)
Style (3) = 00011 (bits 5-9)
Color (4) = 00100 (bits 0-4)
Combined: 0000110001100100 = 0x0C64
Hex: "0C64"
```
### Decoding Hardware
```
Given hex: "0D94"
Binary: 0000110110010100
Extract fields:
Type = bits 10-14 = 00011 = 3 (Pull Handle)
Style = bits 5-9 = 01100 = 12
Color = bits 0-4 = 10100 = 20
```
## URL Examples
### Simple Products (No Hardware)
```
"0-1-4-1" = Patio Door, White, Aluminum
"0-3-4-1" = Storm Door, White, Aluminum
"0-7-1-1" = Primary Window, Black, Aluminum
"0-5-2-2" = Storm Window, Bronze, Vinyl
```
### Products with Hardware
```
"0-3-4-1-0421" = Storm Door, White, Aluminum, Lever-Standard-Brass
"0-3-1-1-0421-0C64" = Storm Door, Black, Aluminum,
Hardware1: Lever-Standard-Brass,
Hardware2: Pull Handle-Alternative-Satin
```
## Expansion Strategy
### Adding New Options (Compatible)
When adding new options within existing capacity (0-15 for main attributes, 0-31 for hardware fields):
```
Old system: Color 1-6 defined, 7-15 reserved
New system: Add Color 7 = Charcoal
Old URLs still work: "0-1-4-1" still means Patio Door, White, Aluminum
New URLs use new values: "0-1-7-1" means Patio Door, Charcoal, Aluminum
```
### Version 1 (Future Expansion)
If we exceed 16 main attribute values or 32 hardware field values:
```
Version 1: Use 6 bits per hardware field (64 values each)
Format: "1-TT-CC-MM-HHHHH-HHHHH"
Changes:
- Main attributes expand to 2 hex chars each (256 values)
- Hardware expands to 5 hex chars each (18 bits = 6 bits per field)
```
## Compatibility Rules
1. **Never reuse reserved values** until a new version is released
2. **Never change existing value meanings** (e.g., don't make "1" mean something else)
3. **Always decode based on version character**
4. **Maintain lookup tables** for each version
## Implementation Notes
- Use bit-shifting operators (`<<`, `>>`) for performance
- Use bitwise AND (`&`) with masks to extract fields
- Pad hex strings with leading zeros to fixed width
- Validate decoded values against valid ranges
- Return error for unknown version codes
## Benefits
**Stable**: Values 0-15 remain the same even if we expand to 0-31
**Compact**: 13-24 characters for most products
**Readable**: Hex is human-debuggable
**Efficient**: Single parse operation, no string splitting
**Extensible**: Version prefix allows future format changes
**Reliable**: Bit operations are deterministic and reversible
---
**Last Updated**: March 26, 2026
**Current Version**: 0 (5-bit hardware encoding)
+505
View File
@@ -0,0 +1,505 @@
# Encoding Table Generation System
## Problem Statement
Currently, encoding lookup tables require manual maintenance of both forward and reverse mappings:
```javascript
// Must maintain both of these manually
const PRODUCT_COLOR = {
'BLACK': 1,
'BRONZE': 2,
// ... add new color here
};
const PRODUCT_COLOR_REVERSE = {
1: 'BLACK',
2: 'BRONZE',
// ... and remember to add it here too!
};
```
**Issues:**
- ❌ Prone to human error (forgetting reverse mapping)
- ❌ Risk of mismatches between forward/reverse
- ❌ No validation for duplicate values
- ❌ No documentation of available slots
- ❌ Difficult for non-technical users to add values
## Proposed Solution: Python-Generated Tables
### Architecture
```
User edits simple source file
Python validation script
Generate JavaScript + Python constants
Auto-served by Flask (or manual build step)
```
### File Structure
```
app/
data/
encoding_values.json (or .yaml) ← USER EDITS THIS
js/
encoding_tables.js ← AUTO-GENERATED
generate_encoding_tables.py ← GENERATOR SCRIPT
```
## Source File Format
### Option 1: JSON with Comments Support
**`app/data/encoding_values.json`**
```json
{
"metadata": {
"version": 0,
"description": "Product encoding value definitions"
},
"tables": {
"product_type": {
"max_value": 15,
"bit_size": 4,
"values": [
{"name": "PATIO_DOOR", "value": 1, "display": "Patio Door"},
{"name": "STORM_DOOR", "value": 3, "display": "Storm Door"},
{"name": "STORM_WINDOW", "value": 5, "display": "Storm Window"},
{"name": "PRIMARY_WINDOW", "value": 7, "display": "Primary Window"}
]
},
"product_color": {
"max_value": 15,
"bit_size": 4,
"values": [
{"name": "BLACK", "value": 1, "display": "Black"},
{"name": "BRONZE", "value": 2, "display": "Bronze"},
{"name": "SANDSTONE", "value": 3, "display": "Sandstone"},
{"name": "WHITE", "value": 4, "display": "White"},
{"name": "TAN", "value": 5, "display": "Tan"},
{"name": "MILL", "value": 6, "display": "Mill"}
]
},
"product_material": {
"max_value": 15,
"bit_size": 4,
"values": [
{"name": "ALUMINUM", "value": 1, "display": "Aluminum"},
{"name": "VINYL", "value": 2, "display": "Vinyl"}
]
},
"hardware_type": {
"max_value": 31,
"bit_size": 5,
"values": [
{"name": "NONE", "value": 0, "display": "None"},
{"name": "LEVER", "value": 1, "display": "Lever"},
{"name": "PULL", "value": 2, "display": "Pull"},
{"name": "PULL_HANDLE", "value": 3, "display": "Pull Handle"},
{"name": "DEADBOLT", "value": 4, "display": "Deadbolt"},
{"name": "HINGE", "value": 5, "display": "Hinge"}
]
},
"hardware_style": {
"max_value": 31,
"bit_size": 5,
"values": [
{"name": "NONE", "value": 0, "display": "None"},
{"name": "STANDARD", "value": 1, "display": "Standard"},
{"name": "PUSH", "value": 2, "display": "Push"},
{"name": "ALTERNATIVE", "value": 3, "display": "Alternative"},
{"name": "CONTEMPORARY", "value": 4, "display": "Contemporary"},
{"name": "TRADITIONAL", "value": 5, "display": "Traditional"}
]
},
"hardware_color": {
"max_value": 31,
"bit_size": 5,
"values": [
{"name": "NONE", "value": 0, "display": "None"},
{"name": "BRASS", "value": 1, "display": "Brass"},
{"name": "WHITE", "value": 2, "display": "White"},
{"name": "BLACK", "value": 3, "display": "Black"},
{"name": "SATIN", "value": 4, "display": "Satin"},
{"name": "NICKEL", "value": 5, "display": "Nickel"},
{"name": "BRONZE", "value": 6, "display": "Bronze"}
]
}
}
}
```
### Option 2: YAML (Better for Comments)
**`app/data/encoding_values.yaml`**
```yaml
version: 0
description: Product encoding value definitions
tables:
product_type:
max_value: 15
bit_size: 4
values:
- name: PATIO_DOOR
value: 1
display: Patio Door
- name: STORM_DOOR
value: 3
display: Storm Door
# Reserved: 2, 4, 6, 8-15
product_color:
max_value: 15
bit_size: 4
values:
- name: BLACK
value: 1
display: Black
- name: BRONZE
value: 2
display: Bronze
# ... etc
# Reserved: 7-15 (9 slots available)
```
## User Workflow
### Adding a New Color
**Before (Manual):**
1. Open `encoding_helper.js`
2. Find `PRODUCT_COLOR` object
3. Add new entry with unused value
4. Find `PRODUCT_COLOR_REVERSE` object
5. Add matching reverse entry
6. Hope you didn't make a mistake
**After (Generated):**
1. Open `encoding_values.json`
2. Add one line: `{"name": "CHARCOAL", "value": 7, "display": "Charcoal"}`
3. Run `python generate_encoding_tables.py` (or auto-regenerated by Flask)
4. Done! JavaScript and Python constants updated
## Generator Script
**`app/generate_encoding_tables.py`**
```python
#!/usr/bin/env python3
"""
Generate JavaScript and Python encoding tables from source JSON/YAML.
Usage:
python generate_encoding_tables.py
Or add to Flask app for auto-generation on file change.
"""
import json
import os
from datetime import datetime
from pathlib import Path
def load_source_file(filepath):
"""Load encoding values from JSON or YAML."""
with open(filepath, 'r') as f:
if filepath.endswith('.yaml') or filepath.endswith('.yml'):
import yaml
return yaml.safe_load(f)
else:
return json.load(f)
def validate_table(table_name, table_data):
"""Validate a single table for errors."""
errors = []
max_value = table_data['max_value']
values = table_data['values']
used_values = set()
used_names = set()
for item in values:
name = item['name']
value = item['value']
# Check for duplicate values
if value in used_values:
errors.append(f"{table_name}: Duplicate value {value}")
used_values.add(value)
# Check for duplicate names
if name in used_names:
errors.append(f"{table_name}: Duplicate name '{name}'")
used_names.add(name)
# Check value range
if value < 0 or value > max_value:
errors.append(f"{table_name}: Value {value} out of range (0-{max_value})")
# Validate naming convention (uppercase with underscores)
if not name.isupper() or not name.replace('_', '').isalpha():
errors.append(f"{table_name}: Invalid name format '{name}' (use UPPERCASE_WITH_UNDERSCORES)")
# Report available slots
available = sorted(set(range(max_value + 1)) - used_values)
info = f"{table_name}: {len(used_values)}/{max_value + 1} slots used, {len(available)} available"
if available and len(available) <= 10:
info += f" {available}"
return errors, info
def generate_javascript(data, output_path):
"""Generate JavaScript constants file."""
lines = [
"// AUTO-GENERATED FILE - DO NOT EDIT MANUALLY",
"// Generated from: app/data/encoding_values.json",
f"// Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
"//",
"// To add new values:",
"// 1. Edit app/data/encoding_values.json",
"// 2. Run: python app/generate_encoding_tables.py",
"// 3. Restart Flask server (or it auto-reloads)",
"",
"// ============================================================================",
"// ENCODING CONSTANTS",
"// ============================================================================",
"",
f"const ENCODING_VERSION = {data['metadata']['version']};",
""
]
for table_name, table_data in data['tables'].items():
const_name = table_name.upper()
# Generate forward mapping
lines.append(f"// {const_name} (max: {table_data['max_value']}, bits: {table_data['bit_size']})")
lines.append(f"const {const_name} = {{")
for item in table_data['values']:
lines.append(f" '{item['name']}': {item['value']},")
lines.append("};")
lines.append("")
# Generate reverse mapping
lines.append(f"const {const_name}_REVERSE = {{")
for item in table_data['values']:
lines.append(f" {item['value']}: '{item['name']}',")
lines.append("};")
lines.append("")
# Generate display mapping
lines.append(f"const {const_name}_DISPLAY = {{")
for item in table_data['values']:
lines.append(f" '{item['name']}': '{item['display']}',")
lines.append("};")
lines.append("")
# Write file
with open(output_path, 'w') as f:
f.write('\n'.join(lines))
print(f"✓ Generated: {output_path}")
def generate_python(data, output_path):
"""Generate Python constants file (optional)."""
lines = [
'"""',
"AUTO-GENERATED FILE - DO NOT EDIT MANUALLY",
"Generated from: app/data/encoding_values.json",
f"Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
'"""',
"",
f"ENCODING_VERSION = {data['metadata']['version']}",
""
]
for table_name, table_data in data['tables'].items():
const_name = table_name.upper()
lines.append(f"# {const_name} (max: {table_data['max_value']}, bits: {table_data['bit_size']})")
lines.append(f"{const_name} = {{")
for item in table_data['values']:
lines.append(f" '{item['name']}': {item['value']},")
lines.append("}")
lines.append("")
lines.append(f"{const_name}_REVERSE = {{")
for item in table_data['values']:
lines.append(f" {item['value']}: '{item['name']}',")
lines.append("}")
lines.append("")
with open(output_path, 'w') as f:
f.write('\n'.join(lines))
print(f"✓ Generated: {output_path}")
def generate_documentation(data, output_path):
"""Generate markdown documentation."""
lines = [
"# Encoding Values Reference",
"",
f"**Version:** {data['metadata']['version']} ",
f"**Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} ",
"",
"## Overview",
"",
"This document lists all currently defined encoding values.",
"",
"## Quick Reference",
""
]
for table_name, table_data in data['tables'].items():
lines.append(f"### {table_name.replace('_', ' ').title()}")
lines.append("")
lines.append(f"**Capacity:** {len(table_data['values'])}/{table_data['max_value'] + 1} slots used ")
lines.append(f"**Bit Size:** {table_data['bit_size']} bits ")
lines.append("")
lines.append("| Value | Name | Display |")
lines.append("|-------|------|---------|")
for item in sorted(table_data['values'], key=lambda x: x['value']):
lines.append(f"| {item['value']} | `{item['name']}` | {item['display']} |")
lines.append("")
with open(output_path, 'w') as f:
f.write('\n'.join(lines))
print(f"✓ Generated: {output_path}")
def main():
"""Main generation function."""
base_dir = Path(__file__).parent
source_file = base_dir / 'data' / 'encoding_values.json'
# Load source data
print(f"Loading: {source_file}")
data = load_source_file(source_file)
# Validate all tables
print("\nValidating tables...")
all_errors = []
for table_name, table_data in data['tables'].items():
errors, info = validate_table(table_name, table_data)
print(f" {info}")
all_errors.extend(errors)
if all_errors:
print("\n❌ VALIDATION ERRORS:")
for error in all_errors:
print(f" - {error}")
return 1
print("\n✓ All tables valid")
# Generate files
print("\nGenerating files...")
generate_javascript(data, base_dir / 'js' / 'encoding_tables.js')
generate_python(data, base_dir / 'encoding_tables_constants.py')
generate_documentation(data, base_dir.parent / 'planning' / 'ENCODING_VALUES_REFERENCE.md')
print("\n✓ Generation complete!")
return 0
if __name__ == '__main__':
exit(main())
```
## Flask Integration (Auto-Generation)
Add to `app.py`:
```python
import os
from datetime import datetime
@app.before_request
def check_encoding_tables():
"""Auto-regenerate encoding tables if source has changed."""
source_file = 'data/encoding_values.json'
output_file = 'js/encoding_tables.js'
# Check if regeneration needed
if not os.path.exists(output_file):
print("Encoding tables not found, generating...")
os.system('python generate_encoding_tables.py')
else:
source_mtime = os.path.getmtime(source_file)
output_mtime = os.path.getmtime(output_file)
if source_mtime > output_mtime:
print("Encoding values changed, regenerating tables...")
os.system('python generate_encoding_tables.py')
```
## Benefits
### For Non-Technical Users
- ✅ Edit simple JSON file (no JavaScript knowledge needed)
- ✅ Clear structure with examples
- ✅ Automatic validation catches errors
- ✅ Can't create mismatches between forward/reverse
### For Developers
- ✅ Single source of truth
- ✅ Auto-generated documentation
- ✅ Validation prevents bugs
- ✅ Easy to add new tables
- ✅ Can generate for multiple targets (JS, Python, docs)
### For Maintenance
- ✅ Version control friendly (one file to track)
- ✅ Easy to review changes (just JSON diff)
- ✅ Reports available slots automatically
- ✅ Enforces naming conventions
## Migration Path
### Phase 1: Create Source File
1. Extract existing values to `encoding_values.json`
2. Test generator script
3. Verify output matches current `encoding_helper.js`
### Phase 2: Integrate Generator
1. Add generator script to project
2. Update build process / Flask app
3. Test auto-generation
### Phase 3: Switch to Generated Tables
1. Update `encoding_helper.js` to import generated file
2. Remove manual mappings
3. Update documentation
### Phase 4: User Documentation
1. Create guide for adding new values
2. Document validation rules
3. Add examples
## Future Enhancements
- Web UI for editing values (no need to edit JSON directly)
- Export to CSV for client review
- Import from Excel/CSV
- Visual capacity indicators
- Conflict detection across tables
- Automatic value assignment (find next available slot)
## Related Files
- [ENCODING_SYSTEM.md](ENCODING_SYSTEM.md) - Technical specification
- `app/js/encoding_helper.js` - Current manual implementation
- `app/js/encoding_tables.js` - Future generated file
---
**Status:** Planning
**Priority:** Medium
**Effort:** ~4-6 hours implementation + testing
**Dependencies:** None
File diff suppressed because it is too large Load Diff
+208
View File
@@ -0,0 +1,208 @@
# Product Finder - Project Features Summary
**Date:** March 25, 2026
**Project:** Product Finder Application for Columbia Metals
**Participants:** Jesse Salmon, Jason Soltys, Darlene Lampe
---
## Core Application Features
### 1. Product Selection Workflow
- **Multi-step navigation system** using button-based interface
- **Goal:** Minimize text entry - "tap, tap, tap" workflow
- **JSON-driven configuration** for flexible navigation without code changes
- Sequential selection process: Color → Size → Model/Type → Accessories
### 2. Color Selection
- **Visual color buttons** (similar to current implementation showing Black, Bronze, Mill, etc.)
- Filters available products based on color selection
- **Mill finish to be removed** (not available for any door)
- Default hardware colors match door colors (e.g., bronze door = black pull, white door = white pull)
### 3. Size Selection System
#### Standard Sizes
- **Three standard sizes for storm doors:**
- 2668 (26" x 68")
- 2868 (28" x 68")
- 3068 (36" x 81")
- Display both nominal size (e.g., "3068") and actual dimensions (e.g., "36 x 81")
- **Button-based interface** (similar to color selection)
- Standard sizes auto-populate width and height fields (grayed out/non-editable)
#### Custom Sizes
- **Custom option button** reveals width/height input fields
- **Storm doors:** Opening size ONLY (no tip-to-tip)
- Display warning in RED: "Opening size only - not tip to tip"
- **Patio doors:** Either opening size or tip-to-tip allowed
- Toggle between standard size buttons and custom input
### 4. Product Categories
#### Storm Doors
- **Models:** Cobra, King, King Dual Vent
- Category filtering based on selected criteria
- Product images for each model
- **Measurement requirement:** Opening size only for custom orders
#### Patio Doors
- Standard size: 5069
- Can use opening size or tip-to-tip for custom
#### Products to Exclude
- Parts (Z-bars, inserts)
- Discontinued items (marked in database)
- M1200 patio storm door
- Storm door inserts
### 5. Hardware & Accessories
#### Hardware Selection
- **Types:** Brass lever, Satin silver, Black pull, White pull
- Labeled as "Hardware" in CGW system
- Default hardware based on door color
- Optional customization via dropdown
#### Hinge Side Selection
- **Required field** - no default setting
- Options: Left hand or Right hand
- **Measurement instruction:** "Facing the door from the outside, which side are the hinges on?"
- Visual prompt/popup to ensure customer understands measurement perspective
### 6. Visual Elements
#### Product Images
- Display product photos for each door model
- **Door image flipping:** Mirror image based on hinge side selection (JavaScript/CSS)
- Images sourced from website and database
#### Outside View Indicator
- **Proposed design:** Doghouse illustration with:
- Small roof/overhang
- Plant or bush beside door
- Wall indication
- Purpose: Help customers understand they're viewing from outside
- Simple, rough design acceptable
#### Navigation Elements
- Button-based interface throughout
- Visual color swatches
- Product thumbnails
- Continue/Next buttons
### 7. Data Management
#### Database Integration
- **Source:** CGW (Columbia Gateway Windows) database
- **Locations:** Iola, Kansas City, Lindsberg
- Google Sheets for product data management
- Product codes exported from CGW
#### Data Filtering
- Filter discontinued items (marked in spreadsheet)
- Remove accessories from main product list
- **Column H (Door Type/Subtype):** Delete to remove from product list
- **Columns J & K:** Accessory/hardware flags
#### Product Naming Consistency
- Challenge: Same products have different model numbers across locations
- **Solution:** Use catalog names (customer-facing)
- Internal CGW names vary by plant
- Need standardization project for matching products across locations
### 8. User Experience Features
#### Add to Cart/Order
- Button to add selected product to sales order
- Appears after all selections made
- Label: "Add to [cart/sales order/hardware]"
#### Measurement Instructions
- **Link to PDF** with measurement guidelines
- Accessible from size selection screen
- Shows how to determine hinge side, measure openings, etc.
#### Validation & Warnings
- Opening size requirement for custom storm doors (highlighted in red)
- Required field indicators (hinge side selection)
- Visual cues for defaults vs. custom selections
### 9. Architecture & Technical Approach
#### Navigation System
- JSON file manages all navigation flow
- Changes made via JSON manipulation (no code changes needed)
- Flexible architecture to support iteration
- **Current limitation:** Toggle functionality requires code changes
#### Development Philosophy
- Hard-code initial features for rapid iteration
- Avoid premature optimization
- Build architecture after understanding full requirements
- Keep front-end decoupled from back-end structure
### 10. Future Considerations
#### Windows
- Primary windows and storm windows have different measurement rules
- "Whole different ball game" - to be addressed later
#### Parts/Accessories Integration
- Parts sheet for storm door inserts
- Separate handling from complete products
- Discontinued items may need parts availability
#### Multi-Location Support
- Consolidate product naming across plants
- Maintain location-specific inventory
- Unified catalog names for customers
---
## Key Business Rules
1. **Storm doors (custom):** Opening size only
2. **Patio doors (custom):** Opening size OR tip-to-tip
3. **Standard sizes:** Auto-populate dimensions (read-only)
4. **Hinge side:** Required selection with instructional prompt
5. **Hardware:** Defaults based on color, optional customization
6. **Discontinued items:** Filter from product display
7. **Parts/accessories:** Exclude from main product categories
---
## Implementation Priorities
### High Priority
1. Size selection with standard sizes as buttons
2. Remove discontinued items from display
3. Hinge side selection with flip image functionality
4. Hardware dropdown with defaults
5. Custom size with opening-size-only warning for storm doors
### Medium Priority
1. Outside view visual indicator (doghouse design)
2. Link to measurement instructions PDF
3. Add to cart/order button
4. Product naming standardization across locations
### Low Priority (Future)
1. Windows integration
2. Parts/accessories handling
3. Advanced filtering options
4. Multi-location inventory management
---
## Quality & Accuracy Concerns
- **Arnie's primary concern:** Accuracy of the system
- Emphasis on preventing measurement errors
- Visual aids to reduce confusion
- Clear labeling and validation messages
- "It's too complicated" - need to prove simplicity through good UX
---
*This summary was generated from the March 25, 2026 project planning meeting transcript.*
Binary file not shown.