Skip to content

Commit 8d9c367

Browse files
committed
Refactor countdown monetization system to enhance user experience and performance. Implemented a premium licensing model with countdown gates for unlicensed users, ensuring instant execution for licensed users. Centralized storage utility introduced for improved error tracking and data management. Updated technical architecture to streamline data flow and component responsibilities, while enhancing error handling and memory efficiency. Comprehensive testing and future enhancement strategies outlined for ongoing development.
1 parent b90ab59 commit 8d9c367

1 file changed

Lines changed: 249 additions & 67 deletions

File tree

features/countdown.md

Lines changed: 249 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
### Countdown Monetization Plan (Gumroad One‑Time License, Client‑Only)
1+
### Super Tidy Pro: Countdown Monetization System
22

3-
#### Goal
4-
- Introduce a countdown gate (random 6–15s) before executing any command for unlicensed users, with an in-UI option to purchase and skip the delay.
5-
- Licensed customers experience zero delay.
6-
- Payments handled via a Gumroad product (one-time); license activation is client-only via Gumroad License Verification API with Netlify Function proxy for secure API operations.
3+
#### Overview
4+
Implement a premium licensing system with countdown gates for free users and instant execution for licensed users. The system uses Gumroad for payments and license management, with a client-side verification approach optimized for performance and user experience.
5+
6+
#### Product Goals
7+
- **Premium Experience**: Licensed users get instant command execution with zero friction
8+
- **Conversion Optimization**: Free users experience 6-15 second countdown with seamless upgrade path
9+
- **Reliable Architecture**: Robust data flow with comprehensive error tracking and observability
10+
- **Scalable Foundation**: Clean separation of concerns and reusable architectural patterns
711

812
---
913

@@ -36,13 +40,14 @@
3640

3741
---
3842

39-
### Technical Architecture (Final Implementation)
43+
### Technical Architecture
4044

41-
#### **Core Architecture Principles**
42-
- **Embedded Countdown**: Countdown is a state within FormView.js, not a separate route
43-
- **Clean Separation**: UI logic in UI layer, Figma APIs in Core.js
44-
- **Direct Communication**: UI components use direct method calls, postMessage only for Core.js communication
45-
- **License Caching**: License status cached in memory for fast gate decisions
45+
#### **Design Principles**
46+
- **Unidirectional Data Flow**: Data flows from Core → App → Components via props
47+
- **Separation of Concerns**: Core.js handles Figma APIs, UI handles presentation logic
48+
- **Centralized Storage**: Single utility manages all clientStorage operations with validation
49+
- **Observability First**: Comprehensive error tracking and analytics integration
50+
- **Memory Efficiency**: Proper cleanup patterns and singleton utilities
4651

4752
#### **Component Responsibilities**
4853

@@ -54,49 +59,112 @@
5459
- Supports both UI-initiated and direct (menu) countdowns via callback parameter
5560
- Imports and displays AnalogChronometer component
5661

57-
**Core.js** (Pure Figma APIs):
58-
- Handles Figma Canvas and Storage APIs only
59-
- Manages license storage in `figma.clientStorage` (`LICENSE_V1` key)
60-
- Wraps menu commands with `ensureDirectCommandGate` for gating
61-
- Sends `start-direct-countdown` messages to UI for menu-initiated commands
62-
- Processes license-related messages: `get-license`, `activate-license`, `remove-license`
63-
64-
**App.js** (Minimal orchestrator):
65-
- Handles Core.js messages and initializes views
66-
- `handleDirectCountdown` navigates to FormView and calls startCountdown directly
67-
- Router setup excludes countdown route (no longer needed)
68-
- Removed CountdownView import and rendering from App.js
69-
- Direct integration with FormView's embedded countdown functionality
70-
71-
**LicenseView.js** (License management):
72-
- Dual-state rendering: unlicensed form vs licensed info display
73-
- Gumroad API integration via Netlify Function proxy
74-
- 2-device usage limit enforcement
75-
- License validation, activation, and unlinking
76-
- Device usage tracking and display
62+
**Core.js** (Figma API Layer):
63+
- Manages all Figma Canvas and Storage APIs exclusively
64+
- Handles license storage using centralized Storage utility
65+
- Implements command gating with `ensureDirectCommandGate`
66+
- Includes license data in all initialization messages
67+
- Processes license activation/removal via postMessage
68+
69+
**App.js** (Data Orchestration):
70+
- Receives initialization data from Core.js including license status
71+
- Stores license and preferences in component state
72+
- Passes data to child components via HTML attributes
73+
- Handles direct countdown coordination for menu commands
74+
- Manages view routing and component lifecycle
75+
76+
**FormView.js** (Primary UI & Gating):
77+
- Embedded countdown state within main form interface
78+
- Receives license data via props from App.js
79+
- Manages countdown timer and analog chronometer display
80+
- Handles both UI-initiated and menu-triggered countdowns
81+
- Updates license cache directly from props
82+
83+
**LicenseView.js** (License Management):
84+
- Dual-state rendering: activation form vs license info display
85+
- Receives current license data via props from App.js
86+
- Integrates with Gumroad API for license verification
87+
- Manages license activation and device unlinking
88+
- Provides user support and troubleshooting access
7789

7890
**AnalogChronometer.js** (Visual countdown):
7991
- Animated analog clock with red needle
8092
- Dynamic tick generation based on total seconds
8193
- Attribute-based updates (`total-seconds`, `current-seconds`)
8294
- Clean white circle design with red accents
8395

84-
#### **Gating Flow**
85-
1. User triggers command (UI form or menu)
86-
2. Check cached license status via `shouldShowCountdown()`
87-
3. **If licensed**: Execute command immediately
88-
4. **If unlicensed**:
89-
- FormView shows countdown state (embedded, not separate route)
90-
- User stays on "Actions" tab throughout countdown
91-
- After countdown: "Run Now" button enables
92-
- User clicks "Run Now" to execute command
93-
94-
#### **Menu Command Gating**
95-
- Core.js wraps menu commands with `ensureDirectCommandGate`
96-
- Shows UI and sends `start-direct-countdown` message
97-
- App.js calls FormView.startCountdown with callback
98-
- Callback sends `direct-countdown-complete` message back to Core.js
99-
- Licensed users get `figma.closePlugin()` immediately
96+
#### **Storage Architecture**
97+
98+
**Centralized Storage Utility** (`src/utils/Storage.js`):
99+
- Constructor-based singleton pattern initialized from Core.js
100+
- Map-based key validation prevents runtime errors
101+
- Automatic error tracking for all storage operations
102+
- Promise-based API using then/catch for compatibility
103+
- Batch operations (getMultiple/setMultiple) for efficiency
104+
105+
**Storage Key Management**:
106+
```javascript
107+
// Defined in Core.js
108+
const STORAGE_KEYS = {
109+
UUID: 'UUID',
110+
PREFERENCES: 'preferences',
111+
LICENSE_V1: 'LICENSE_V1',
112+
AD_LAST_SHOWN_DATE: 'AD_LAST_SHOWN_DATE',
113+
AD_LAST_SHOWN_IMPRESSION: 'AD_LAST_SHOWN_IMPRESSION'
114+
}
115+
116+
// Usage throughout application
117+
Storage.get(Storage.getKey('LICENSE_V1'))
118+
Storage.set(Storage.getKey('UUID'), value)
119+
```
120+
121+
**Error Tracking Integration**:
122+
All storage failures automatically emit tracking events:
123+
```javascript
124+
{
125+
type: 'tracking-event',
126+
event: 'storage-operation-failed',
127+
properties: {
128+
operation: 'get|set|remove',
129+
key: 'LICENSE_V1',
130+
error: 'Detailed error message',
131+
timestamp: Date.now()
132+
}
133+
}
134+
```
135+
136+
#### **Data Flow Architecture**
137+
138+
**Initialization Flow**:
139+
```
140+
Core.js → Storage.getMultiple() → Include in init messages → App.js → Props → Components
141+
```
142+
143+
**License Activation Flow**:
144+
```
145+
LicenseView → Gumroad API → activateLicense() → Core.js → Storage.set() → Cache Update
146+
```
147+
148+
**Command Execution Flow**:
149+
```
150+
User Action → Gate Check → [Licensed: Execute] | [Unlicensed: Countdown → Manual Execute]
151+
```
152+
153+
#### **Gating Implementation**
154+
1. **User triggers command** (UI form or menu)
155+
2. **License check** via cached status in `shouldShowCountdown()`
156+
3. **Licensed path**: Execute command immediately
157+
4. **Unlicensed path**:
158+
- FormView shows countdown state (embedded in current view)
159+
- User remains on current tab throughout countdown
160+
- After countdown completion: "Run Now" button enables
161+
- Manual execution trigger required
162+
163+
#### **Menu Command Integration**
164+
- Core.js wraps all menu commands with `ensureDirectCommandGate`
165+
- Shows UI and includes license data in `init-direct` message
166+
- App.js coordinates FormView countdown with execution callback
167+
- Licensed users bypass countdown entirely with immediate execution
100168

101169
---
102170

@@ -207,7 +275,9 @@
207275
1. **Race Conditions**: FormView event listeners were accumulating without cleanup
208276
2. **Data Consistency**: Usage count not properly stored during license activation
209277
3. **Silent Failures**: Storage operations lacked error handling and user feedback
210-
4. **Solution**: Implemented proper event listener cleanup, comprehensive error handling, and consistent data format
278+
4. **Complex Timeout Patterns**: Duplicated postMessage request/response cycles with timeout cleanup
279+
5. **Memory Leaks**: Event listeners not properly cleaned up in license retrieval
280+
6. **Solution**: Implemented proper event listener cleanup, comprehensive error handling, consistent data format, and eliminated postMessage complexity
211281

212282
#### **Key Technical Decisions**
213283
- **Memory over Storage**: License status cached in `gate.js` for performance
@@ -216,6 +286,9 @@
216286
- **State Management**: LEO Element data properties for countdown state
217287
- **Event Listener Management**: Proper cleanup to prevent memory leaks and race conditions
218288
- **Error Handling**: Comprehensive error handling for all storage operations with user feedback
289+
- **Centralized Storage**: Storage utility with automatic error tracking and validation
290+
- **Data Down, Events Up**: License data flows from Core → App → Components via props
291+
- **Unidirectional Data Flow**: Eliminated complex postMessage request/response cycles
219292

220293
---
221294

@@ -228,8 +301,8 @@
228301
- [x] Manual "Run Now" button after countdown completion
229302
- [x] License tab with dual-state rendering
230303
- [x] Gumroad license verification and activation
231-
- [x] 2-device usage limit with Netlify Function proxy
232-
- [x] License info display and device usage tracking
304+
- [x] ~~2-device usage limit with Netlify Function proxy~~ (Temporarily disabled for easier management)
305+
- [x] License info display ~~and device usage tracking~~ (Device tracking temporarily hidden)
233306
- [x] License unlinking with usage count decrement
234307
- [x] Menu command gating for direct Figma menu access
235308
- [x] License status caching for fast gate decisions
@@ -238,18 +311,25 @@
238311
- [x] Fixed license storage/retrieval race conditions and reliability issues
239312
- [x] Comprehensive error handling with user feedback for all storage operations
240313
- [x] Proper event listener cleanup to prevent memory leaks
314+
- [x] **NEW**: Centralized Storage utility with automatic error tracking
315+
- [x] **NEW**: Eliminated postMessage timeout patterns for license retrieval
316+
- [x] **NEW**: Unidirectional data flow (Core → App → Components)
317+
- [x] **NEW**: Comprehensive storage operation tracking and analytics
241318

242319
#### **✅ Tested Scenarios**
243320
- [x] Licensed user: immediate command execution
244321
- [x] Unlicensed user: countdown → manual execution
245322
- [x] License activation: Gumroad API integration
246323
- [x] Menu commands: gating works from Figma menu
247-
- [x] Device limits: 2-device enforcement
324+
- [x] ~~Device limits: 2-device enforcement~~ (Temporarily disabled)
248325
- [x] License unlinking: usage count decremented
249326
- [x] Error handling: invalid keys, API failures
250327
- [x] License storage reliability: consistent save/load across plugin sessions
251328
- [x] Memory management: no event listener leaks or race conditions
252329
- [x] Error recovery: proper user feedback for storage failures
330+
- [x] **NEW**: Storage error tracking and analytics integration
331+
- [x] **NEW**: License data propagation through init messages
332+
- [x] **NEW**: Props-based license data flow without postMessage complexity
253333

254334
#### **🎯 Production Ready**
255335
The countdown monetization system is fully implemented and functional, with:
@@ -287,22 +367,124 @@ The countdown monetization system is fully implemented and functional, with:
287367

288368
---
289369

290-
### Future Enhancements (Optional)
291-
292-
#### **Potential Improvements**
293-
- [ ] Server-side license validation for stronger security
294-
- [ ] Usage analytics and conversion optimization
295-
- [ ] License transfer between devices
296-
- [ ] Bulk license management for teams
297-
- [ ] Additional license tiers or features
298-
299-
#### **Technical Debt**
300-
- [ ] Migrate from LEO.js to modern framework (if needed)
301-
- [x] Enhanced error handling and retry mechanisms (COMPLETED)
302-
- [ ] Automated testing for license flows
303-
- [ ] Performance optimization for large selections
304-
- [x] Memory leak prevention and proper cleanup (COMPLETED)
305-
- [x] Race condition fixes in license management (COMPLETED)
370+
### Development Best Practices
371+
372+
#### **Storage Operations**
373+
- Always use centralized Storage utility with key validation
374+
- Handle both success and failure cases with user feedback
375+
- Use batch operations for related data updates
376+
- Initialize all keys in Core.js, avoid hardcoded strings
377+
378+
#### **Data Flow Patterns**
379+
- Prefer "data down, events up" architecture
380+
- Include data in initialization messages rather than separate requests
381+
- Use component props/attributes instead of complex postMessage cycles
382+
- Maintain single source of truth for application state
383+
384+
#### **Error Handling & Observability**
385+
- Emit tracking events for all error conditions
386+
- Provide specific, actionable error messages to users
387+
- Log contextual information for effective debugging
388+
- Distinguish between recoverable and fatal error types
389+
390+
#### **Memory & Performance**
391+
- Clean up event listeners in component lifecycle methods
392+
- Use singleton patterns to prevent resource duplication
393+
- Prefer direct method calls over complex async coordination
394+
- Implement proper component cleanup patterns
395+
396+
#### **Code Organization**
397+
- Separate Figma API operations from UI logic
398+
- Create reusable utilities for common patterns
399+
- Use constructor-based classes for stateful services
400+
- Implement comprehensive input validation with clear error messages
401+
402+
---
403+
404+
### Implementation Phases
405+
406+
#### **Phase 1: Core Infrastructure**
407+
- Centralized Storage utility implementation with key validation
408+
- Basic countdown timer and gating logic
409+
- License data flow architecture via props
410+
- Error tracking and analytics integration
411+
412+
#### **Phase 2: Gumroad Integration**
413+
- License verification API integration
414+
- Secure key management and hashing
415+
- Purchase flow and activation process
416+
- Device management capabilities
417+
418+
#### **Phase 3: User Experience Polish**
419+
- Analog chronometer animation implementation
420+
- Visual design and interaction refinement
421+
- Comprehensive error handling and user messaging
422+
- Performance optimization and testing
423+
424+
#### **Phase 4: Analytics & Optimization**
425+
- Conversion funnel implementation
426+
- A/B testing framework setup
427+
- Performance monitoring and alerting
428+
- User feedback collection and analysis
429+
430+
### Testing Strategy
431+
432+
#### **Automated Testing**
433+
- Unit tests for Storage utility and core functions
434+
- Integration tests for license verification flow
435+
- Performance tests for countdown and activation timing
436+
- Error scenario testing for network and storage failures
437+
438+
#### **Manual Testing Scenarios**
439+
- Licensed user: instant command execution across all entry points
440+
- Unlicensed user: countdown completion and manual execution
441+
- License activation: Gumroad integration and key validation
442+
- Menu commands: gating functionality from Figma menu
443+
- Error recovery: invalid keys, network failures, storage issues
444+
445+
#### **User Acceptance Testing**
446+
- Conversion flow optimization and usability
447+
- User interface accessibility and cross-platform compatibility
448+
- Performance under various system conditions
449+
- Edge case handling and error recovery
450+
451+
---
452+
453+
### Future Enhancements
454+
455+
#### **Advanced Features**
456+
- Server-side license validation for enhanced security
457+
- Team license management and bulk operations
458+
- License transfer capabilities between devices
459+
- Advanced usage analytics and reporting
460+
- Multiple license tiers and feature sets
461+
462+
#### **Technical Improvements**
463+
- Automated testing framework expansion
464+
- Performance optimization for large selections
465+
- Modern framework migration considerations
466+
- Enhanced retry mechanisms for critical operations
467+
- Storage integrity verification systems
468+
469+
#### **Business Expansion**
470+
- Subscription model exploration
471+
- Partner integration opportunities
472+
- International market expansion
473+
- Advanced conversion optimization
474+
475+
### Success Metrics
476+
477+
#### **Primary KPIs**
478+
- License conversion rate from free to premium users
479+
- User retention and engagement metrics
480+
- Revenue per user and lifetime value
481+
- Customer satisfaction and support efficiency
482+
483+
#### **Technical KPIs**
484+
- System uptime and reliability metrics
485+
- License activation success rate
486+
- Storage operation performance and error rates
487+
- User experience quality indicators
306488

307489
---
308490

0 commit comments

Comments
 (0)