@powerhousedao/academy 5.1.0-dev.9 → 5.1.0

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.
Files changed (75) hide show
  1. package/CHANGELOG.md +43 -1108
  2. package/blog/BeyondCommunication-ABlueprintForDevelopment.md +1 -2
  3. package/blog/TheChallengeOfChange.md +0 -1
  4. package/docs/academy/00-EthereumArgentinaHackathon.md +207 -0
  5. package/docs/academy/01-GetStarted/00-ExploreDemoPackage.mdx +27 -24
  6. package/docs/academy/01-GetStarted/01-CreateNewPowerhouseProject.md +9 -118
  7. package/docs/academy/01-GetStarted/02-DefineToDoListDocumentModel.md +28 -110
  8. package/docs/academy/01-GetStarted/03-ImplementOperationReducers.md +145 -191
  9. package/docs/academy/01-GetStarted/04-BuildToDoListEditor.md +218 -0
  10. package/docs/academy/{02-MasteryTrack/01-BuilderEnvironment → 01-GetStarted}/05-VetraStudio.md +6 -48
  11. package/docs/academy/01-GetStarted/06-ReactorMCP.md +58 -0
  12. package/docs/academy/01-GetStarted/_04-BuildToDoListEditor +1 -1
  13. package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/03-BuilderTools.md +2 -2
  14. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/02-SpecifyTheStateSchema.md +44 -75
  15. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/03-SpecifyDocumentOperations.md +22 -28
  16. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/04-UseTheDocumentModelGenerator.md +31 -28
  17. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/05-ImplementDocumentReducers.md +206 -211
  18. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/06-ImplementDocumentModelTests.md +62 -176
  19. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/07-ExampleToDoListRepository.md +0 -21
  20. package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/01-BuildingDocumentEditors.md +319 -309
  21. package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/00-DocumentToolbar.mdx +0 -4
  22. package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/01-OperationHistory.md +0 -4
  23. package/docs/academy/02-MasteryTrack/05-Launch/04-ConfigureEnvironment.md +1 -1
  24. package/docs/academy/03-ExampleUsecases/Chatroom/02-CreateNewPowerhouseProject.md +35 -111
  25. package/docs/academy/03-ExampleUsecases/Chatroom/03-DefineChatroomDocumentModel.md +76 -255
  26. package/docs/academy/03-ExampleUsecases/Chatroom/04-ImplementOperationReducers.md +160 -281
  27. package/docs/academy/03-ExampleUsecases/Chatroom/05-ImplementChatroomEditor.md +35 -188
  28. package/docs/academy/03-ExampleUsecases/Chatroom/06-LaunchALocalReactor.md +7 -95
  29. package/docs/academy/03-ExampleUsecases/Chatroom/_category_.json +1 -1
  30. package/docs/academy/04-APIReferences/00-PowerhouseCLI.md +2 -6
  31. package/docs/academy/04-APIReferences/01-ReactHooks.md +501 -291
  32. package/docs/academy/05-Architecture/00-PowerhouseArchitecture.md +39 -7
  33. package/docs/academy/05-Architecture/02-ReferencingMonorepoPackages +65 -0
  34. package/docs/academy/05-Architecture/04-MovingBeyondCRUD +61 -0
  35. package/docs/academy/06-ComponentLibrary/00-DocumentEngineering.md +24 -72
  36. package/docs/academy/08-Glossary.md +0 -7
  37. package/docusaurus.config.ts +3 -28
  38. package/package.json +1 -1
  39. package/sidebars.ts +12 -49
  40. package/src/css/custom.css +18 -26
  41. package/docs/academy/01-GetStarted/04-WriteDocumentModelTests.md +0 -378
  42. package/docs/academy/01-GetStarted/05-BuildToDoListEditor.md +0 -560
  43. package/docs/academy/03-ExampleUsecases/TodoList/00-GetTheStarterCode.md +0 -24
  44. package/docs/academy/03-ExampleUsecases/TodoList/01-GenerateTodoListDocumentModel.md +0 -211
  45. package/docs/academy/03-ExampleUsecases/TodoList/02-ImplementTodoListDocumentModelReducerOperationHandlers.md +0 -171
  46. package/docs/academy/03-ExampleUsecases/TodoList/03-AddTestsForTodoListActions.md +0 -462
  47. package/docs/academy/03-ExampleUsecases/TodoList/04-GenerateTodoListDocumentEditor.md +0 -45
  48. package/docs/academy/03-ExampleUsecases/TodoList/05-ImplementTodoListDocumentEditorUIComponents.md +0 -422
  49. package/docs/academy/03-ExampleUsecases/TodoList/06-GenerateTodoDriveExplorer.md +0 -61
  50. package/docs/academy/03-ExampleUsecases/TodoList/07-AddSharedComponentForShowingTodoListStats.md +0 -384
  51. package/docs/academy/03-ExampleUsecases/TodoList/_category_.json +0 -8
  52. package/docs/academy/03-ExampleUsecases/VetraPackageLibrary/VetraPackageLibrary.md +0 -7
  53. package/docs/academy/03-ExampleUsecases/VetraPackageLibrary/_category_.json +0 -9
  54. package/docs/academy/04-APIReferences/06-VetraRemoteDrive.md +0 -160
  55. package/docs/academy/04-APIReferences/renown-sdk/00-Overview.md +0 -316
  56. package/docs/academy/04-APIReferences/renown-sdk/01-Authentication.md +0 -672
  57. package/docs/academy/04-APIReferences/renown-sdk/02-APIReference.md +0 -957
  58. package/docs/academy/04-APIReferences/renown-sdk/_category_.json +0 -8
  59. package/docs/academy/10-TodoListTutorial/02-ImplementTodoListDocumentModelReducerOperationHandlers.md +0 -171
  60. package/docs/academy/10-TodoListTutorial/03-AddTestsForTodoListActions.md +0 -462
  61. package/docs/academy/10-TodoListTutorial/05-ImplementTodoListDocumentEditorUIComponents.md +0 -422
  62. package/docs/academy/10-TodoListTutorial/07-AddSharedComponentForShowingTodoListStats.md +0 -370
  63. package/static/img/Vetra-logo-dark.svg +0 -11
  64. package/static/img/vetra-logo-light.svg +0 -11
  65. /package/docs/academy/{02-MasteryTrack/01-BuilderEnvironment → 01-GetStarted}/images/Modules.png +0 -0
  66. /package/docs/academy/{02-MasteryTrack/01-BuilderEnvironment → 01-GetStarted}/images/VetraStudioDrive.png +0 -0
  67. /package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/{02-RevisionHistoryTimeline/360/237/232/247" → 02-RevisionHistoryTimeline} +0 -0
  68. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /01-WhatIsADocumentModel" → 01-WhatIsADocumentModel} +0 -0
  69. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /02-DAOandDocumentsModelsQ+A" → 02-DAOandDocumentsModelsQ+A} +0 -0
  70. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /02-domain-modeling" → 02-domain-modeling} +0 -0
  71. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /03-BenefitsOfDocumentModels" → 03-BenefitsOfDocumentModels} +0 -0
  72. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /04-UtilitiesAndTips" → 04-UtilitiesAndTips} +0 -0
  73. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /05-best-practices" → 05-best-practices} +0 -0
  74. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /_category_.json" → _category_.json} +0 -0
  75. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /three-data-layers.png" → three-data-layers.png} +0 -0
@@ -6,214 +6,100 @@ In the previous chapter, we implemented the core reducer logic for our document
6
6
 
7
7
  Testing is not an afterthought; it's an integral part of the development lifecycle, especially in systems like Powerhouse where data integrity and predictable state transitions are paramount. Well-crafted tests serve as a safety net, allowing you to refactor and extend your document model with confidence.
8
8
 
9
- This document provides a practical, hands-on tutorial for testing the `TodoList` document model reducers you have just built.
9
+ This document provides a practical, hands-on tutorial for testing the `To-do List` document model reducers you have just built.
10
10
 
11
- ## Practical implementation: Writing and running the TodoList tests
11
+ ## Practical implementation: Writing and running the To-do List tests
12
12
 
13
- This tutorial assumes you have implemented the `TodoList` reducers as described in the previous chapter and that the code generator has created a test file skeleton at `document-models/todo-list/src/tests/todos.test.ts`.
13
+ This tutorial assumes you have implemented the `To-do List` reducers as described in the previous chapter and that the code generator has created a test file skeleton at `document-models/to-do-list/src/reducers/tests/to-do-list.test.ts`.
14
14
 
15
15
  <details>
16
- <summary>Tutorial: Implementing and running the TodoList reducer tests</summary>
16
+ <summary>Tutorial: Implementing and running the `To-do List` reducer tests</summary>
17
17
 
18
18
  ### 1. Implement the reducer tests
19
19
 
20
- With the reducer logic in place, it's critical to test it. Navigate to the generated test file at `document-models/todo-list/src/tests/todos.test.ts` and replace its contents with comprehensive tests.
20
+ With the reducer logic in place, it's critical to test it. Navigate to the generated test file at `document-models/to-do-list/src/reducers/tests/to-do-list.test.ts` and replace its contents with the following test suite.
21
21
 
22
- This suite tests each operation, verifying not only that the `items` array is correct, but also that the operation itself is recorded properly in the document's history.
23
-
24
- **Basic tests (matching Get Started):**
22
+ This suite tests each operation, verifying not only that the `items` array is correct, but also that our `stats` object is updated as expected and that the operation itself is recorded properly in the document's history.
25
23
 
26
24
  ```typescript
27
- import { describe, it, expect } from "vitest";
28
- import { generateMock } from "@powerhousedao/codegen";
29
- import type {
30
- AddTodoItemInput,
31
- DeleteTodoItemInput,
32
- UpdateTodoItemInput,
33
- } from "todo-tutorial/document-models/todo-list";
34
- import {
35
- reducer,
36
- utils,
37
- isTodoListDocument,
38
- addTodoItem,
39
- AddTodoItemInputSchema,
40
- updateTodoItem,
41
- UpdateTodoItemInputSchema,
42
- deleteTodoItem,
43
- DeleteTodoItemInputSchema,
44
- TodoItemSchema,
45
- } from "todo-tutorial/document-models/todo-list";
46
-
47
- describe("Todos Operations", () => {
48
- it("should handle addTodoItem operation", () => {
49
- const document = utils.createDocument();
50
- const input: AddTodoItemInput = generateMock(AddTodoItemInputSchema());
51
-
52
- const updatedDocument = reducer(document, addTodoItem(input));
53
- expect(isTodoListDocument(updatedDocument)).toBe(true);
54
-
55
- // Verify the operation was recorded
56
- expect(updatedDocument.operations.global).toHaveLength(1);
57
- expect(updatedDocument.operations.global[0].action.type).toBe("ADD_TODO_ITEM");
58
- expect(updatedDocument.operations.global[0].action.input).toStrictEqual(input);
59
- expect(updatedDocument.operations.global[0].index).toEqual(0);
25
+ import utils from "../../gen/utils.js";
26
+ import { reducer } from "../../gen/reducer.js";
27
+ import * as creators from "../../gen/creators.js";
28
+ import { ToDoListDocument } from "../../gen/types.js";
29
+
30
+ describe("Todolist Operations", () => {
31
+ let document: ToDoListDocument;
32
+
33
+ beforeEach(() => {
34
+ // REMARKS: We start with a fresh, empty document for each test.
35
+ // The `createDocument` utility initializes the state with an empty 'items' array
36
+ // and a 'stats' object with all counts set to 0.
37
+ document = utils.createDocument();
60
38
  });
61
39
 
62
- it("should handle updateTodoItem operation to update text", () => {
63
- const mockItem = generateMock(TodoItemSchema());
64
- const input: UpdateTodoItemInput = generateMock(UpdateTodoItemInputSchema());
65
- input.id = mockItem.id;
66
- const newText = "new text";
67
- input.text = newText;
68
- input.checked = undefined;
69
-
70
- const document = utils.createDocument({
71
- global: {
72
- items: [mockItem],
73
- },
74
- });
75
-
76
- const updatedDocument = reducer(document, updateTodoItem(input));
77
- expect(isTodoListDocument(updatedDocument)).toBe(true);
78
-
79
- // Verify the operation was recorded
80
- expect(updatedDocument.operations.global).toHaveLength(1);
81
- expect(updatedDocument.operations.global[0].action.type).toBe("UPDATE_TODO_ITEM");
82
-
83
- // Verify the state was updated correctly
84
- const updatedItem = updatedDocument.state.global.items.find(
85
- (item) => item.id === input.id,
86
- );
87
- expect(updatedItem?.text).toBe(newText);
88
- expect(updatedItem?.checked).toBe(mockItem.checked);
89
- });
40
+ it("should handle addTodoItem operation", () => {
41
+ const input = { id: "1", text: "Buy milk" };
90
42
 
91
- it("should handle updateTodoItem operation to update checked", () => {
92
- const mockItem = generateMock(TodoItemSchema());
93
- const input: UpdateTodoItemInput = generateMock(UpdateTodoItemInputSchema());
94
- input.id = mockItem.id;
95
- const newChecked = !mockItem.checked;
96
- input.checked = newChecked;
97
- input.text = undefined;
98
-
99
- const document = utils.createDocument({
100
- global: {
101
- items: [mockItem],
102
- },
103
- });
104
-
105
- const updatedDocument = reducer(document, updateTodoItem(input));
106
- expect(isTodoListDocument(updatedDocument)).toBe(true);
107
-
108
- const updatedItem = updatedDocument.state.global.items.find(
109
- (item) => item.id === input.id,
110
- );
111
- expect(updatedItem?.text).toBe(mockItem.text);
112
- expect(updatedItem?.checked).toBe(newChecked);
113
- });
43
+ // REMARKS: We apply the 'addTodoItem' operation.
44
+ const updatedDocument = reducer(document, creators.addTodoItem(input));
114
45
 
115
- it("should handle deleteTodoItem operation", () => {
116
- const mockItem = generateMock(TodoItemSchema());
117
- const document = utils.createDocument({
118
- global: {
119
- items: [mockItem],
120
- },
121
- });
122
-
123
- const input: DeleteTodoItemInput = generateMock(DeleteTodoItemInputSchema());
124
- input.id = mockItem.id;
125
-
126
- const updatedDocument = reducer(document, deleteTodoItem(input));
127
- expect(isTodoListDocument(updatedDocument)).toBe(true);
128
-
129
- // Verify the operation was recorded
46
+ // REMARKS: We verify the operation was recorded in the document's history.
47
+ // Powerhouse records every operation in an array.
130
48
  expect(updatedDocument.operations.global).toHaveLength(1);
131
- expect(updatedDocument.operations.global[0].action.type).toBe("DELETE_TODO_ITEM");
132
-
133
- // Verify the item was removed from state
134
- const updatedItems = updatedDocument.state.global.items;
135
- expect(updatedItems).toHaveLength(0);
136
- });
137
- });
138
- ```
139
-
140
- **Advanced tests (with stats verification):**
141
-
142
- :::info Advanced Feature
143
- If you implemented the advanced version with statistics tracking, add these additional tests to verify the stats are updated correctly.
144
- :::
145
-
146
- ```typescript
147
- describe("Todos Operations with Stats", () => {
148
- it("should update stats when adding a todo item", () => {
149
- const document = utils.createDocument();
150
- const input = { text: "Buy milk" };
151
-
152
- const updatedDocument = reducer(document, addTodoItem(input));
49
+ expect(updatedDocument.operations.global[0].type).toBe("ADD_TODO_ITEM");
50
+ // REMARKS: We also check that the input data and index are recorded correctly.
51
+ expect(updatedDocument.operations.global[0].input).toStrictEqual(input);
52
+ expect(updatedDocument.operations.global[0].index).toEqual(0);
153
53
 
54
+ // REMARKS: Finally, we verify the state was updated according to our reducer logic.
154
55
  expect(updatedDocument.state.global.items).toHaveLength(1);
155
56
  expect(updatedDocument.state.global.stats.total).toBe(1);
156
57
  expect(updatedDocument.state.global.stats.unchecked).toBe(1);
157
- expect(updatedDocument.state.global.stats.checked).toBe(0);
158
58
  });
159
59
 
160
- it("should update stats when checking a todo item", () => {
161
- const document = utils.createDocument();
162
-
163
- // Add an item first
164
- const addedDocument = reducer(document, addTodoItem({ text: "Buy milk" }));
165
- const itemId = addedDocument.state.global.items[0].id;
166
-
167
- // Now check it
60
+ it("should handle updateTodoItem operation", () => {
61
+ // REMARKS: For an update, we first need to add an item.
62
+ const addInput = { id: "1", text: "Buy milk" };
63
+ const updateInput = { id: "1", checked: true }; // We'll test checking the item.
64
+
65
+ // REMARKS: Operations are applied sequentially to build up document state.
66
+ const createdDocument = reducer(document, creators.addTodoItem(addInput));
168
67
  const updatedDocument = reducer(
169
- addedDocument,
170
- updateTodoItem({ id: itemId, checked: true })
68
+ createdDocument,
69
+ creators.updateTodoItem(updateInput),
171
70
  );
172
71
 
72
+ // REMARKS: Now we should have 2 operations in the history.
73
+ expect(updatedDocument.operations.global).toHaveLength(2);
74
+ expect(updatedDocument.operations.global[1].type).toBe("UPDATE_TODO_ITEM");
75
+ expect(updatedDocument.operations.global[1].input).toStrictEqual(
76
+ updateInput,
77
+ );
78
+
79
+ // REMARKS: We check that the state reflects the update, including our stats.
80
+ expect(updatedDocument.state.global.items[0].checked).toBe(true);
173
81
  expect(updatedDocument.state.global.stats.total).toBe(1);
174
82
  expect(updatedDocument.state.global.stats.unchecked).toBe(0);
175
83
  expect(updatedDocument.state.global.stats.checked).toBe(1);
176
84
  });
177
85
 
178
- it("should update stats when deleting an unchecked todo item", () => {
179
- const document = utils.createDocument();
180
-
181
- // Add an item
182
- const addedDocument = reducer(document, addTodoItem({ text: "Buy milk" }));
183
- const itemId = addedDocument.state.global.items[0].id;
184
-
185
- // Delete it
186
- const updatedDocument = reducer(
187
- addedDocument,
188
- deleteTodoItem({ id: itemId })
189
- );
190
-
191
- expect(updatedDocument.state.global.items).toHaveLength(0);
192
- expect(updatedDocument.state.global.stats.total).toBe(0);
193
- expect(updatedDocument.state.global.stats.unchecked).toBe(0);
194
- expect(updatedDocument.state.global.stats.checked).toBe(0);
195
- });
86
+ it("should handle deleteTodoItem operation", () => {
87
+ const addInput = { id: "1", text: "Buy milk" };
88
+ const deleteInput = { id: "1" };
196
89
 
197
- it("should update stats when deleting a checked todo item", () => {
198
- const document = utils.createDocument();
199
-
200
- // Add and check an item
201
- const addedDocument = reducer(document, addTodoItem({ text: "Buy milk" }));
202
- const itemId = addedDocument.state.global.items[0].id;
203
- const checkedDocument = reducer(
204
- addedDocument,
205
- updateTodoItem({ id: itemId, checked: true })
206
- );
207
-
208
- // Delete it
90
+ const createdDocument = reducer(document, creators.addTodoItem(addInput));
209
91
  const updatedDocument = reducer(
210
- checkedDocument,
211
- deleteTodoItem({ id: itemId })
92
+ createdDocument,
93
+ creators.deleteTodoItem(deleteInput),
212
94
  );
213
95
 
96
+ // REMARKS: After deletion, we still have 2 operations in history,
97
+ // but the items array is now empty and the stats are back to zero.
98
+ expect(updatedDocument.operations.global).toHaveLength(2);
99
+ expect(updatedDocument.operations.global[1].type).toBe("DELETE_TODO_ITEM");
214
100
  expect(updatedDocument.state.global.items).toHaveLength(0);
215
101
  expect(updatedDocument.state.global.stats.total).toBe(0);
216
- expect(updatedDocument.state.global.stats.checked).toBe(0);
102
+ expect(updatedDocument.state.global.stats.unchecked).toBe(0);
217
103
  });
218
104
  });
219
105
  ```
@@ -232,7 +118,7 @@ Or with npm:
232
118
  npm test
233
119
  ```
234
120
 
235
- If all tests pass, you have successfully verified the core logic of your `TodoList` document model. This ensures that the reducers you wrote behave exactly as expected.
121
+ If all tests pass, you have successfully verified the core logic of your `To-do List` document model. This ensures that the reducers you wrote behave exactly as expected.
236
122
 
237
123
  </details>
238
124
 
@@ -263,6 +149,6 @@ By following the tutorial and applying these best practices, you can build a str
263
149
 
264
150
  ## Up next
265
151
 
266
- In the next chapter of the Mastery Track - Building User Experiences you will learn how to implement an [editor](/academy/MasteryTrack/BuildingUserExperiences/BuildingDocumentEditors) for your document model so you can see a simple user interface for the **TodoList** document model in action.
152
+ In the next chapter of the Mastery Track - Building User Experiences you will learn how to implement an [editor](/academy/MasteryTrack/BuildingUserExperiences/BuildingDocumentEditors) for your document model so you can see a simple user interface for the **To-do List** document model in action.
267
153
 
268
- For a complete, working example, you can always have a look at the [Example TodoList Repository](/academy/MasteryTrack/DocumentModelCreation/ExampleToDoListRepository) which contains the full implementation of the concepts discussed in this Mastery Track.
154
+ For a complete, working example, you can always have a look at the [Example To-do List Repository](/academy/MasteryTrack/DocumentModelCreation/ExampleToDoListRepository) which contains the full implementation of the concepts discussed in this Mastery Track.
@@ -14,13 +14,6 @@ There are several ways to explore this package:
14
14
  The Todo-demo and repository are your main reference points during the Mastery Track.
15
15
  Follow the steps in the "Mastery Track – Document Model Creation" chapters to build along with the examples.
16
16
 
17
- Key patterns used in the repository:
18
- - **Naming convention**: `TodoList`, `TodoItem`, `TodoListState` (one word, PascalCase)
19
- - **Document type**: `powerhouse/todo-list`
20
- - **Module name**: `todos`
21
- - **ID generation**: Uses `generateId()` from `document-model/core` in the reducer
22
- - **Hooks**: Uses `useSelectedTodoListDocument` for state management in the editor
23
-
24
17
  ### Option 2: Clone and run the code locally
25
18
 
26
19
  The package includes:
@@ -34,9 +27,6 @@ The package includes:
34
27
  You can clone the repository and run Connect Studio to see all the code in action:
35
28
 
36
29
  ```bash
37
- git clone https://github.com/powerhouse-inc/todo-demo
38
- cd todo-demo
39
- pnpm install
40
30
  ph connect
41
31
  ```
42
32
 
@@ -47,14 +37,3 @@ Alternatively, you can install this package in a Powerhouse project or in your d
47
37
  ```bash
48
38
  ph install @powerhousedao/todo-demo
49
39
  ```
50
-
51
- ## Comparing Get Started vs Mastery Track
52
-
53
- | Aspect | Get Started | Mastery Track (Advanced) |
54
- |--------|-------------|--------------------------|
55
- | Schema | Basic `items` array only | Includes `stats` object for tracking |
56
- | Reducer complexity | Simple CRUD operations | Includes statistics updates |
57
- | Editor | Component-based with hooks | Same approach + stats display |
58
- | Tests | Basic operation tests | Includes stats verification tests |
59
-
60
- Both approaches use the same naming conventions and patterns — the Mastery Track simply extends the foundation with additional features to demonstrate more advanced concepts.