@biglogic/rgs 3.7.6 → 3.7.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,125 +1,125 @@
1
- # 🏗️ Chapter 4: Persistence and Safety - Built like a Tank
2
-
3
- In a real-world application, state that vanishes on page refresh is a developer failure. RGS handles data saving **intelligently**.
4
-
5
- ## 💾 Persistence: "Set and Forget"
6
-
7
- When you initialize RGS or a Magnetar, you can enable persistence. But it's not a simple `localStorage.set`.
8
-
9
- ```typescript
10
- initState({
11
- persist: true,
12
- storage: 'local' // or 'session', or a custom adapter
13
- });
14
- ```
15
-
16
- ### Advanced Storage: Beyond 5MB
17
-
18
- For applications that need to store massive amounts of data (Gigabytes), standard `localStorage` is not enough. RGS provides official plugins for advanced scenarios:
19
-
20
- | Technology | Capacity | Purpose | Plugin |
21
- | :--- | :--- | :--- | :--- |
22
- | **LocalStorage** | ~5MB | Basic UI settings, small profiles. | Core (Native) |
23
- | **IndexedDB** | GBs | Offline-first apps, large datasets, logs. | `indexedDBPlugin` |
24
- | **Cloud Sync** | Unlimited | Remote backup, cross-device sync. | `cloudSyncPlugin` |
25
-
26
- ---
27
-
28
- ## ☁️ Hybrid Persistence: The "Cloud-Cloud" Strategy
29
-
30
- RGS allows you to combine local power with cloud safety. You can store your active data in **IndexedDB** for speed and capacity, while automatically backing it up to a remote database (MongoDB, Firebase, SQL) using the **Cloud Sync Plugin**.
31
-
32
- ### Why use Cloud Sync?
33
- - **Differential Updates**: Safely sends only what was changed since the last sync.
34
- - **Scheduled or On-Demand**: Sync every 5 minutes automatically, or triggered by a "Save to Cloud" button.
35
- - **Diagnostics**: Track how much data you are syncing and detect errors before they reach the user.
36
-
37
- ---
38
-
39
- ### What happens under the hood?
40
-
41
- ```mermaid
42
- sequenceDiagram
43
- participant C as Component
44
- participant RGS as Globo State
45
- participant S as LocalStorage
46
-
47
- Note over C,RGS: User clicks a button
48
- C->>RGS: set('count', 10)
49
- RGS-->>C: Update UI (Instant)
50
-
51
- Note over RGS: Waiting 300ms (Debounce)
52
-
53
- RGS->>S: Write to Disk
54
- Note right of S: Data saved successfully
55
- ```
56
-
57
- - **Debouncing**: If you update the state 100 times in one second, RGS writes to the disk only once at the end. This saves battery life and browser performance.
58
- - **Selective Persistence**: Don't want to save everything? You can tell RGS which keys to ignore or which ones to save only temporarily.
59
-
60
- ## 🛡️ Immutability: The Immer Shield
61
-
62
- Have you ever had bugs where state changed "mysteriously" because you mutated an array directly? RGS uses **Immer** at its core (the Stellar Engine).
63
-
64
- **Dangerous Code (Standard JS):**
65
-
66
- ```javascript
67
- const user = store.get('user');
68
- user.permissions.push('admin'); // BOOM! You mutated the original without triggering a re-render.
69
- ```
70
-
71
- **The RGS Way:**
72
-
73
- ```javascript
74
- store.set('user', (draft) => {
75
- draft.permissions.push('admin'); // SAFE! RGS creates an immutable copy for you.
76
- });
77
- ```
78
-
79
- ## 🕵️ Validation: Schema Plugin
80
-
81
- Never trust data coming back from the server or saved in the browser 6 months ago. Use the **schemaPlugin**.
82
-
83
- ```typescript
84
- import { schemaPlugin } from '@biglogic/rgs';
85
- import { z } from 'zod'; // Recommended!
86
-
87
- const store = initState();
88
- store._addPlugin(schemaPlugin({
89
- price: (val) => typeof val === 'number' && val > 0,
90
- email: (val) => val.includes('@')
91
- }));
92
- ```
93
-
94
- If anyone tries to `set('price', -50)`, RGS will block the operation and warn you. **Clean State = Happy App.**
95
-
96
- ---
97
-
98
- ## ⚠️ Size Limits: maxObjectSize & maxTotalSize
99
-
100
- Protect your app from memory issues with automatic size warnings:
101
-
102
- ```typescript
103
- const store = initState({
104
- // Warn if single value exceeds 5MB (default: 5MB)
105
- maxObjectSize: 5 * 1024 * 1024,
106
- // Warn if total store exceeds 50MB (default: 50MB)
107
- maxTotalSize: 50 * 1024 * 1024
108
- });
109
-
110
- // Setting a value that exceeds the limit will trigger a warning
111
- store.set('largeData', bigObject); // Warns if > maxObjectSize
112
- ```
113
-
114
- ---
115
-
116
- ## 💡 Case Study: The Cart that Never Lost an Item
117
-
118
- **Challenge**: User adds products, closes the browser, comes back after two days. The cart must still be there, and synced with their account on other devices.
119
- **RGS Solution**:
120
-
121
- 1. Enable `indexedDBPlugin` for robust local storage (handles thousands of items).
122
- 2. Use `cloudSyncPlugin` to bridge the local state with your company's MongoDB Atlas or Firebase.
123
- 3. Result? 5-star UX with full data durability and cross-device sync.
124
-
125
- **Next step:** [Ecosystem and Plugins: Extending the Power](05-plugins-and-extensibility.md)
1
+ # 🏗️ Chapter 4: Persistence and Safety - Built like a Tank
2
+
3
+ In a real-world application, state that vanishes on page refresh is a developer failure. RGS handles data saving **intelligently**.
4
+
5
+ ## 💾 Persistence: "Set and Forget"
6
+
7
+ When you initialize RGS or a Magnetar, you can enable persistence. But it's not a simple `localStorage.set`.
8
+
9
+ ```typescript
10
+ initState({
11
+ persist: true,
12
+ storage: 'local' // or 'session', or a custom adapter
13
+ });
14
+ ```
15
+
16
+ ### Advanced Storage: Beyond 5MB
17
+
18
+ For applications that need to store massive amounts of data (Gigabytes), standard `localStorage` is not enough. RGS provides official plugins for advanced scenarios:
19
+
20
+ | Technology | Capacity | Purpose | Plugin |
21
+ | :--- | :--- | :--- | :--- |
22
+ | **LocalStorage** | ~5MB | Basic UI settings, small profiles. | Core (Native) |
23
+ | **IndexedDB** | GBs | Offline-first apps, large datasets, logs. | `indexedDBPlugin` |
24
+ | **Cloud Sync** | Unlimited | Remote backup, cross-device sync. | `cloudSyncPlugin` |
25
+
26
+ ---
27
+
28
+ ## ☁️ Hybrid Persistence: The "Cloud-Cloud" Strategy
29
+
30
+ RGS allows you to combine local power with cloud safety. You can store your active data in **IndexedDB** for speed and capacity, while automatically backing it up to a remote database (MongoDB, Firebase, SQL) using the **Cloud Sync Plugin**.
31
+
32
+ ### Why use Cloud Sync?
33
+ - **Differential Updates**: Safely sends only what was changed since the last sync.
34
+ - **Scheduled or On-Demand**: Sync every 5 minutes automatically, or triggered by a "Save to Cloud" button.
35
+ - **Diagnostics**: Track how much data you are syncing and detect errors before they reach the user.
36
+
37
+ ---
38
+
39
+ ### What happens under the hood?
40
+
41
+ ```mermaid
42
+ sequenceDiagram
43
+ participant C as Component
44
+ participant RGS as Globo State
45
+ participant S as LocalStorage
46
+
47
+ Note over C,RGS: User clicks a button
48
+ C->>RGS: set('count', 10)
49
+ RGS-->>C: Update UI (Instant)
50
+
51
+ Note over RGS: Waiting 300ms (Debounce)
52
+
53
+ RGS->>S: Write to Disk
54
+ Note right of S: Data saved successfully
55
+ ```
56
+
57
+ - **Debouncing**: If you update the state 100 times in one second, RGS writes to the disk only once at the end. This saves battery life and browser performance.
58
+ - **Selective Persistence**: Don't want to save everything? You can tell RGS which keys to ignore or which ones to save only temporarily.
59
+
60
+ ## 🛡️ Immutability: The Immer Shield
61
+
62
+ Have you ever had bugs where state changed "mysteriously" because you mutated an array directly? RGS uses **Immer** at its core (the Stellar Engine).
63
+
64
+ **Dangerous Code (Standard JS):**
65
+
66
+ ```javascript
67
+ const user = store.get('user');
68
+ user.permissions.push('admin'); // BOOM! You mutated the original without triggering a re-render.
69
+ ```
70
+
71
+ **The RGS Way:**
72
+
73
+ ```javascript
74
+ store.set('user', (draft) => {
75
+ draft.permissions.push('admin'); // SAFE! RGS creates an immutable copy for you.
76
+ });
77
+ ```
78
+
79
+ ## 🕵️ Validation: Schema Plugin
80
+
81
+ Never trust data coming back from the server or saved in the browser 6 months ago. Use the **schemaPlugin**.
82
+
83
+ ```typescript
84
+ import { schemaPlugin } from '@biglogic/rgs';
85
+ import { z } from 'zod'; // Recommended!
86
+
87
+ const store = initState();
88
+ store._addPlugin(schemaPlugin({
89
+ price: (val) => typeof val === 'number' && val > 0,
90
+ email: (val) => val.includes('@')
91
+ }));
92
+ ```
93
+
94
+ If anyone tries to `set('price', -50)`, RGS will block the operation and warn you. **Clean State = Happy App.**
95
+
96
+ ---
97
+
98
+ ## ⚠️ Size Limits: maxObjectSize & maxTotalSize
99
+
100
+ Protect your app from memory issues with automatic size warnings:
101
+
102
+ ```typescript
103
+ const store = initState({
104
+ // Warn if single value exceeds 5MB (default: 5MB)
105
+ maxObjectSize: 5 * 1024 * 1024,
106
+ // Warn if total store exceeds 50MB (default: 50MB)
107
+ maxTotalSize: 50 * 1024 * 1024
108
+ });
109
+
110
+ // Setting a value that exceeds the limit will trigger a warning
111
+ store.set('largeData', bigObject); // Warns if > maxObjectSize
112
+ ```
113
+
114
+ ---
115
+
116
+ ## 💡 Case Study: The Cart that Never Lost an Item
117
+
118
+ **Challenge**: User adds products, closes the browser, comes back after two days. The cart must still be there, and synced with their account on other devices.
119
+ **RGS Solution**:
120
+
121
+ 1. Enable `indexedDBPlugin` for robust local storage (handles thousands of items).
122
+ 2. Use `cloudSyncPlugin` to bridge the local state with your company's MongoDB Atlas or Firebase.
123
+ 3. Result? 5-star UX with full data durability and cross-device sync.
124
+
125
+ **Next step:** [Ecosystem and Plugins: Extending the Power](05-plugins-and-extensibility.md)
@@ -1,190 +1,190 @@
1
- # 🔌 Chapter 5: Ecosystem and Plugins - Become a Power User
2
-
3
- RGS is not a closed box. It's a modular engine that you can extend to cover every business need. All plugins are designed to be "Plug & Play".
4
-
5
- ## 🔌 Available Plugins
6
-
7
- RGS includes 11 official plugins:
8
-
9
- | Plugin | Purpose | Import |
10
- |--------|---------|--------|
11
- | `devToolsPlugin` | Redux DevTools integration | `rgs` |
12
- | `debugPlugin` | Console debug access (DEV only) | `rgs` |
13
- | `indexedDBPlugin` | GB-scale Local Storage | `rgs/advanced` |
14
- | `cloudSyncPlugin` | Remote Cloud Backup/Sync | `rgs/advanced` |
15
- | `syncPlugin` | Cross-tab synchronization | `rgs/advanced` |
16
- | `immerPlugin` | Immer for mutable-style updates | `rgs` |
17
- | `snapshotPlugin` | Save/restore state snapshots | `rgs` |
18
- | `undoRedoPlugin` | History management | `rgs` |
19
- | `schemaPlugin` | Schema validation | `rgs` |
20
- | `guardPlugin` | Pre-set value transformation | `rgs` |
21
- | `analyticsPlugin` | Track state changes | `rgs` |
22
-
23
- ## 🔎 1. DevTools: See Under the Hood
24
-
25
- Import the official plugin and you'll see every state change, transaction, and execution time in the console or dev tools (Redux DevTools support included!).
26
-
27
- ```typescript
28
- import { devToolsPlugin } from '@biglogic/rgs';
29
-
30
- store._addPlugin(devToolsPlugin({ name: 'My Store' }));
31
- ```
32
-
33
- ## 🐛 2. Debug: Console Access (DEV ONLY)
34
-
35
- ⚠️ **FOR DEVELOPMENT ONLY** - This plugin is automatically disabled in production.
36
-
37
- Access your store directly from the browser console:
38
-
39
- ```typescript
40
- import { debugPlugin } from '@biglogic/rgs';
41
-
42
- // Always wrap in dev check
43
- if (process.env.NODE_ENV === 'development') {
44
- store._addPlugin(debugPlugin())
45
- }
46
- ```
47
-
48
- Then in the browser console:
49
- ```javascript
50
- gstate.list() // View all state
51
- gstate.get('key') // Get a value
52
- gstate.set('key', val) // Set a value
53
- gstate.info() // Store info
54
- gstate.banner() // Show help
55
- ```
56
-
57
- ## 2. Cross-Tab Sync: Multi-Tab Magic
58
-
59
- Have your app open in three browser tabs? With the `syncPlugin`, if a user changes the theme in one tab, all other tabs update instantly. **Without hitting the server.**
60
-
61
- ```typescript
62
- import { syncPlugin } from 'rgs/advanced';
63
-
64
- store._addPlugin(syncPlugin({ channelName: 'my_app_sync' }));
65
- ```
66
-
67
- ## 🔐 3. Encode Option: Base64 Encoding
68
-
69
- Use the `encoded` option for simple base64 encoding (not encryption, just obfuscation):
70
-
71
- ```typescript
72
- // Per-value encoding
73
- store.set('token', 'secret-value', { persist: true, encoded: true })
74
-
75
- // Or global encoding for all persisted values
76
- const store = initState({ encoded: true })
77
- ```
78
-
79
- > **Note:** Use `encryptionKey` with AES-256-GCM for real security. The `encoded` option is just simple obfuscation.
80
-
81
- ## 🕐 4. TTL (Time To Live): Expiring Data
82
-
83
- Use the `ttl` option in persist to make data expire automatically:
84
-
85
- ```typescript
86
- store.set('session_token', tokenValue, {
87
- persist: true,
88
- ttl: 3600000 // Expires in 1 hour
89
- });
90
- ```
91
-
92
- ## 🎲 5. Undo/Redo: History Management
93
-
94
- ```typescript
95
- import { undoRedoPlugin } from '@biglogic/rgs';
96
-
97
- store._addPlugin(undoRedoPlugin({ limit: 50 }));
98
-
99
- // Later...
100
- store.undo();
101
- store.redo();
102
- store.canUndo(); // boolean
103
- store.canRedo(); // boolean
104
- ```
105
-
106
- ## 📸 6. Snapshots: Save & Restore State
107
-
108
- ```typescript
109
- import { snapshotPlugin } from '@biglogic/rgs';
110
-
111
- store._addPlugin(snapshotPlugin());
112
-
113
- // Save current state
114
- store.takeSnapshot('backup_1');
115
-
116
- // Restore
117
- store.restoreSnapshot('backup_1');
118
-
119
- // List all snapshots
120
- store.listSnapshots(); // ['backup_1', ...]
121
-
122
- // Delete
123
- store.deleteSnapshot('backup_1');
124
- store.clearSnapshots();
125
- ```
126
-
127
- ## 🛡️ 7. Guard: Pre-Set Transformation
128
-
129
- Transform values before they hit the store:
130
-
131
- ```typescript
132
- import { guardPlugin } from '@biglogic/rgs';
133
-
134
- store._addPlugin(guardPlugin({
135
- 'user_input': (val) => val.trim().toLowerCase()
136
- }));
137
- ```
138
-
139
- ## ✅ 8. Schema: Validation
140
-
141
- Validate values before setting:
142
-
143
- ```typescript
144
- import { schemaPlugin } from '@biglogic/rgs';
145
-
146
- store._addPlugin(schemaPlugin({
147
- 'email': (val) => {
148
- if (typeof val !== 'string') return 'Must be a string';
149
- return val.includes('@') ? true : 'Invalid email';
150
- }
151
- }));
152
- ```
153
-
154
- ## 📊 9. Analytics: Track Changes
155
-
156
- ```typescript
157
- import { analyticsPlugin } from '@biglogic/rgs';
158
-
159
- store._addPlugin(analyticsPlugin({
160
- provider: (event) => {
161
- console.log('State changed:', event);
162
- // Send to analytics service
163
- },
164
- keys: ['user', 'cart'] // Only track these keys
165
- }));
166
- ```
167
-
168
- ## 🔄 10. Immer Integration
169
-
170
- ```typescript
171
- import { immerPlugin } from '@biglogic/rgs';
172
-
173
- store._addPlugin(immerPlugin());
174
-
175
- // Update nested state with Immer
176
- store.setWithProduce('user', (draft) => {
177
- draft.name = 'New Name';
178
- draft.address.city = 'New City';
179
- });
180
- ```
181
-
182
- ---
183
-
184
- ## 💡 A Word of Wisdom for Easy & Advanced Scenarios
185
-
186
- Plugins are used to **abstract the boring logic**. If you find yourself writing the same `useEffect` to sync two things in 5 different parts of your app... **Stop.** Create a plugin or use an existing one.
187
-
188
- The best code is the code you write once and forget about.
189
-
190
- **Next step:** [Case Studies: Real-World Production Strategies](06-case-studies.md)
1
+ # 🔌 Chapter 5: Ecosystem and Plugins - Become a Power User
2
+
3
+ RGS is not a closed box. It's a modular engine that you can extend to cover every business need. All plugins are designed to be "Plug & Play".
4
+
5
+ ## 🔌 Available Plugins
6
+
7
+ RGS includes 11 official plugins:
8
+
9
+ | Plugin | Purpose | Import |
10
+ |--------|---------|--------|
11
+ | `devToolsPlugin` | Redux DevTools integration | `rgs` |
12
+ | `debugPlugin` | Console debug access (DEV only) | `rgs` |
13
+ | `indexedDBPlugin` | GB-scale Local Storage | `rgs/advanced` |
14
+ | `cloudSyncPlugin` | Remote Cloud Backup/Sync | `rgs/advanced` |
15
+ | `syncPlugin` | Cross-tab synchronization | `rgs/advanced` |
16
+ | `immerPlugin` | Immer for mutable-style updates | `rgs` |
17
+ | `snapshotPlugin` | Save/restore state snapshots | `rgs` |
18
+ | `undoRedoPlugin` | History management | `rgs` |
19
+ | `schemaPlugin` | Schema validation | `rgs` |
20
+ | `guardPlugin` | Pre-set value transformation | `rgs` |
21
+ | `analyticsPlugin` | Track state changes | `rgs` |
22
+
23
+ ## 🔎 1. DevTools: See Under the Hood
24
+
25
+ Import the official plugin and you'll see every state change, transaction, and execution time in the console or dev tools (Redux DevTools support included!).
26
+
27
+ ```typescript
28
+ import { devToolsPlugin } from '@biglogic/rgs';
29
+
30
+ store._addPlugin(devToolsPlugin({ name: 'My Store' }));
31
+ ```
32
+
33
+ ## 🐛 2. Debug: Console Access (DEV ONLY)
34
+
35
+ ⚠️ **FOR DEVELOPMENT ONLY** - This plugin is automatically disabled in production.
36
+
37
+ Access your store directly from the browser console:
38
+
39
+ ```typescript
40
+ import { debugPlugin } from '@biglogic/rgs';
41
+
42
+ // Always wrap in dev check
43
+ if (process.env.NODE_ENV === 'development') {
44
+ store._addPlugin(debugPlugin())
45
+ }
46
+ ```
47
+
48
+ Then in the browser console:
49
+ ```javascript
50
+ gstate.list() // View all state
51
+ gstate.get('key') // Get a value
52
+ gstate.set('key', val) // Set a value
53
+ gstate.info() // Store info
54
+ gstate.banner() // Show help
55
+ ```
56
+
57
+ ## 2. Cross-Tab Sync: Multi-Tab Magic
58
+
59
+ Have your app open in three browser tabs? With the `syncPlugin`, if a user changes the theme in one tab, all other tabs update instantly. **Without hitting the server.**
60
+
61
+ ```typescript
62
+ import { syncPlugin } from 'rgs/advanced';
63
+
64
+ store._addPlugin(syncPlugin({ channelName: 'my_app_sync' }));
65
+ ```
66
+
67
+ ## 🔐 3. Encode Option: Base64 Encoding
68
+
69
+ Use the `encoded` option for simple base64 encoding (not encryption, just obfuscation):
70
+
71
+ ```typescript
72
+ // Per-value encoding
73
+ store.set('token', 'secret-value', { persist: true, encoded: true })
74
+
75
+ // Or global encoding for all persisted values
76
+ const store = initState({ encoded: true })
77
+ ```
78
+
79
+ > **Note:** Use `encryptionKey` with AES-256-GCM for real security. The `encoded` option is just simple obfuscation.
80
+
81
+ ## 🕐 4. TTL (Time To Live): Expiring Data
82
+
83
+ Use the `ttl` option in persist to make data expire automatically:
84
+
85
+ ```typescript
86
+ store.set('session_token', tokenValue, {
87
+ persist: true,
88
+ ttl: 3600000 // Expires in 1 hour
89
+ });
90
+ ```
91
+
92
+ ## 🎲 5. Undo/Redo: History Management
93
+
94
+ ```typescript
95
+ import { undoRedoPlugin } from '@biglogic/rgs';
96
+
97
+ store._addPlugin(undoRedoPlugin({ limit: 50 }));
98
+
99
+ // Later...
100
+ store.undo();
101
+ store.redo();
102
+ store.canUndo(); // boolean
103
+ store.canRedo(); // boolean
104
+ ```
105
+
106
+ ## 📸 6. Snapshots: Save & Restore State
107
+
108
+ ```typescript
109
+ import { snapshotPlugin } from '@biglogic/rgs';
110
+
111
+ store._addPlugin(snapshotPlugin());
112
+
113
+ // Save current state
114
+ store.takeSnapshot('backup_1');
115
+
116
+ // Restore
117
+ store.restoreSnapshot('backup_1');
118
+
119
+ // List all snapshots
120
+ store.listSnapshots(); // ['backup_1', ...]
121
+
122
+ // Delete
123
+ store.deleteSnapshot('backup_1');
124
+ store.clearSnapshots();
125
+ ```
126
+
127
+ ## 🛡️ 7. Guard: Pre-Set Transformation
128
+
129
+ Transform values before they hit the store:
130
+
131
+ ```typescript
132
+ import { guardPlugin } from '@biglogic/rgs';
133
+
134
+ store._addPlugin(guardPlugin({
135
+ 'user_input': (val) => val.trim().toLowerCase()
136
+ }));
137
+ ```
138
+
139
+ ## ✅ 8. Schema: Validation
140
+
141
+ Validate values before setting:
142
+
143
+ ```typescript
144
+ import { schemaPlugin } from '@biglogic/rgs';
145
+
146
+ store._addPlugin(schemaPlugin({
147
+ 'email': (val) => {
148
+ if (typeof val !== 'string') return 'Must be a string';
149
+ return val.includes('@') ? true : 'Invalid email';
150
+ }
151
+ }));
152
+ ```
153
+
154
+ ## 📊 9. Analytics: Track Changes
155
+
156
+ ```typescript
157
+ import { analyticsPlugin } from '@biglogic/rgs';
158
+
159
+ store._addPlugin(analyticsPlugin({
160
+ provider: (event) => {
161
+ console.log('State changed:', event);
162
+ // Send to analytics service
163
+ },
164
+ keys: ['user', 'cart'] // Only track these keys
165
+ }));
166
+ ```
167
+
168
+ ## 🔄 10. Immer Integration
169
+
170
+ ```typescript
171
+ import { immerPlugin } from '@biglogic/rgs';
172
+
173
+ store._addPlugin(immerPlugin());
174
+
175
+ // Update nested state with Immer
176
+ store.setWithProduce('user', (draft) => {
177
+ draft.name = 'New Name';
178
+ draft.address.city = 'New City';
179
+ });
180
+ ```
181
+
182
+ ---
183
+
184
+ ## 💡 A Word of Wisdom for Easy & Advanced Scenarios
185
+
186
+ Plugins are used to **abstract the boring logic**. If you find yourself writing the same `useEffect` to sync two things in 5 different parts of your app... **Stop.** Create a plugin or use an existing one.
187
+
188
+ The best code is the code you write once and forget about.
189
+
190
+ **Next step:** [Case Studies: Real-World Production Strategies](06-case-studies.md)