@powerhousedao/academy 2.5.0-dev.2 → 2.5.0-dev.21

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 (40) hide show
  1. package/CHANGELOG.md +124 -0
  2. package/docs/academy/01-GetStarted/00-ExploreDemoPackage.md +18 -10
  3. package/docs/academy/01-GetStarted/01-CreateNewPowerhouseProject.md +36 -39
  4. package/docs/academy/01-GetStarted/02-DefineToDoListDocumentModel.md +21 -6
  5. package/docs/academy/01-GetStarted/03-ImplementOperationReducers.md +5 -0
  6. package/docs/academy/01-GetStarted/04-BuildToDoListEditor.md +148 -420
  7. package/docs/academy/01-GetStarted/_04-BuildToDoListEditor +495 -0
  8. package/docs/academy/01-GetStarted/home.mdx +15 -15
  9. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/01-WhatIsADocumentModel.md +11 -2
  10. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/02-SpecifyTheStateSchema.md +5 -0
  11. package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/01-BuildingDocumentEditors.md +5 -37
  12. package/docs/academy/02-MasteryTrack/05-Launch/02-PublishYourProject.md +70 -5
  13. package/docs/academy/02-MasteryTrack/05-Launch/03-SetupEnvironment.md +159 -73
  14. package/docs/academy/02-MasteryTrack/05-Launch/{03-RunOnACloudServer.md → _03-RunOnACloudServer} +8 -5
  15. package/docs/academy/04-APIReferences/00-PowerhouseCLI.md +7 -40
  16. package/docs/academy/06-ComponentLibrary/00-DocumentEngineering.md +67 -21
  17. package/docs/academy/06-ComponentLibrary/02-CreateCustomScalars.md +403 -0
  18. package/docs/academy/06-ComponentLibrary/{02-BuildingWithScalars.md → 02-ScalarComponent.mdx} +10 -12
  19. package/docs/academy/06-ComponentLibrary/{04-Complex-Components/01-sidebar.mdx → 03-ComplexComponent.mdx} +3 -1
  20. package/docs/academy/06-ComponentLibrary/03-IntegrateIntoAReactComponent.md +1 -0
  21. package/docs/academy/06-ComponentLibrary/04-LayoutComponent.mdx +5 -0
  22. package/docs/academy/06-ComponentLibrary/05-FragmentsComponent.mdx +5 -0
  23. package/docs/academy/07-Cookbook.md +0 -4
  24. package/docs/academy/08-Glossary.md +4 -1
  25. package/docs/academy/09-AIResources +23 -0
  26. package/package.json +1 -1
  27. package/sidebars.ts +6 -45
  28. package/docs/academy/06-ComponentLibrary/03-Scalar-Components/01-phid-field.mdx +0 -72
  29. package/docs/academy/06-ComponentLibrary/03-Scalar-Components/02-input-field.mdx +0 -0
  30. package/docs/academy/06-ComponentLibrary/05-Layout-Components/01-test-toupdate.mdx +0 -61
  31. package/docs/academy/06-ComponentLibrary/06-Fragments/01-test-toupdate.mdx +0 -61
  32. /package/docs/academy/02-MasteryTrack/05-Launch/{02-IntroductionToPackages.md → 01-IntroductionToPackages.md} +0 -0
  33. /package/docs/academy/02-MasteryTrack/05-Launch/{00-IntegrateInAFront-End → _00-IntegrateInAFront-End} +0 -0
  34. /package/docs/academy/02-MasteryTrack/05-Launch/{01-IntroducingFusion → _01-IntroducingFusion} +0 -0
  35. /package/docs/academy/02-MasteryTrack/05-Launch/{04-GraphQLNamespacing → _04-GraphQLNamespacing} +0 -0
  36. /package/docs/academy/02-MasteryTrack/05-Launch/{05-LaunchYourBackend.md → _05-LaunchYourBackend} +0 -0
  37. /package/docs/academy/02-MasteryTrack/05-Launch/{06-LaunchYourFrontend.md → _06-LaunchYourFrontend} +0 -0
  38. /package/docs/academy/04-APIReferences/{01-ReactHooks.md → 01-ReactHooks} +0 -0
  39. /package/docs/academy/04-APIReferences/{02-ReactorAPI.md → 02-ReactorAPI} +0 -0
  40. /package/docs/academy/04-APIReferences/{03-Configuration.md → 03-Configuration} +0 -0
@@ -0,0 +1,495 @@
1
+ # Build a ToDoList Editor
2
+
3
+ In this chapter we will continue with the interface or editor implementation of the **ToDoList** document model. This means you will create a simple user interface for the **ToDoList** document model which will be used inside the Connect app to create, update and delete your ToDoList items.
4
+
5
+ ## Generate the editor template
6
+
7
+ Run the command below to generate the editor template for the **ToDoList** document model.
8
+ This command reads the **ToDoList** document model definition from the `document-models` folder and generates the editor template in the `editors/to-do-list` folder as `editor.tsx`.
9
+
10
+ Notice the `--editor` flag which specifies the **ToDoList** document model, and the `--document-types` flag defines the document type `powerhouse/todolist`.
11
+
12
+ ```bash
13
+ ph generate --editor ToDoList --document-types powerhouse/todolist
14
+ ```
15
+
16
+ Once complete, navigate to the `editors/to-do-list/editor.tsx` file and open it in your editor.
17
+
18
+
19
+ ### Editor Implementation Options
20
+
21
+ When building your editor component within the Powerhouse ecosystem, you have several options for styling, allowing you to leverage your preferred methods:
22
+
23
+ 1. **Default HTML Styling:** Standard HTML tags (`<h1>`, `<p>`, `<button>`, etc.) will render with default styles offered through the boilerplate.
24
+ 2. **Tailwind CSS:** Connect Studio comes with Tailwind CSS integrated. You can directly use Tailwind utility classes for rapid, consistent styling without writing separate CSS files.
25
+ 3. **Custom CSS Files:** You can import traditional CSS files (`.css`) to apply custom styles or integrate existing style libraries.
26
+
27
+ Connect Studio provides a dynamic local environment (`ph connect`) to visualize your components instantly as you build them, regardless of the styling method you choose. Manual build steps are typically only needed when publishing packages.
28
+
29
+ Let's look at a simple example component structure a styling method can be applied.
30
+
31
+ **Example Component Structure (Base HTML with inline styles)**
32
+
33
+ <details>
34
+ <summary>Base HTML Example</summary>
35
+
36
+ Here's a basic editor structure using only standard HTML tags.
37
+ This demonstrates how elements look with very minimal default styling:
38
+
39
+ ```typescript
40
+ import { EditorProps } from 'document-model';
41
+ // Assuming a simple document model for demonstration
42
+ // import { ExampleDocument, actions } from '../../document-models/example';
43
+
44
+ // Replace with your actual document type props if needed
45
+ export type IProps = EditorProps<any>;
46
+
47
+ export default function Editor({ document, dispatch }: IProps) {
48
+ return (
49
+ <div>
50
+ <h1 style={{ fontWeight: 'bold' }}>Document Title</h1>
51
+ <h2>Document Subtitle</h2>
52
+ <input
53
+ type="text"
54
+ placeholder="Small text input"
55
+ style={{ border: '1px solid gray', marginBottom: '0.5rem' }}
56
+ />
57
+ <textarea
58
+ placeholder="Large text area"
59
+ rows={4}
60
+ style={{ border: '1px solid gray', display: 'block', marginBottom: '0.5rem' }}
61
+ />
62
+ <button style={{ backgroundColor: 'yellow' }}>
63
+ Submit
64
+ </button>
65
+ </div>
66
+ );
67
+ }
68
+ ```
69
+ </details>
70
+
71
+ *Run `ph connect` to see the default styles applied to components in real-time.*
72
+
73
+ **Styling with Tailwind CSS**
74
+
75
+ <details>
76
+ <summary>Tailwind CSS Example</summary>
77
+
78
+ Now, let's add Tailwind utility classes to the same structure for styling:
79
+
80
+ ```typescript
81
+ import { EditorProps } from 'document-model';
82
+ // import { ExampleDocument, actions } from '../../document-models/example';
83
+
84
+ export type IProps = EditorProps<any>;
85
+
86
+ export default function Editor({ document, dispatch }: IProps) {
87
+ return (
88
+ <div className="p-4 space-y-4"> {/* Add padding and spacing */}
89
+ <h1 className="text-2xl font-bold">Document Title</h1> {/* Style heading */}
90
+ <h2 className="text-lg text-gray-600 mb-4">Document Subtitle</h2> {/* Style subheading */}
91
+ <input
92
+ type="text"
93
+ placeholder="Small text input"
94
+ className="w-full p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500 mb-4" // Style input
95
+ />
96
+ <textarea
97
+ placeholder="Large text area"
98
+ rows={4}
99
+ className="w-full p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500" // Style textarea
100
+ />
101
+ <button className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded transition-colors"> {/* Style button */}
102
+ Submit
103
+ </button>
104
+ </div>
105
+ );
106
+ }
107
+ ```
108
+ </details>
109
+
110
+ *Run `ph connect` to see these Tailwind styles applied in real-time.*
111
+
112
+ **Styling with a Custom CSS File**
113
+
114
+ <details>
115
+ <summary>Custom CSS File Example</summary>
116
+
117
+ You can also import a standard CSS file.
118
+
119
+ 1. Create a CSS file (e.g., `editor.css`) in the same directory as your `editor.tsx`:
120
+
121
+ ```css
122
+ /* editors/your-editor/editor.css */
123
+ .editor-container {
124
+ padding: 1rem;
125
+ border: 1px solid #ccc;
126
+ border-radius: 4px;
127
+ }
128
+
129
+ .editor-title {
130
+ color: rgb(51, 51, 54);
131
+ font-size: 2rem;
132
+ margin-bottom: 4px;
133
+ }
134
+
135
+ .editor-subtitle {
136
+ color: rgb(51, 51, 54);
137
+ font-size: 1.5rem;
138
+ margin-bottom: 4px;
139
+ }
140
+
141
+ .editor-button {
142
+ background-color: green;
143
+ color: white;
144
+ padding: 0.5rem 1rem;
145
+ border: none;
146
+ border-radius: 4px;
147
+ cursor: pointer;
148
+ }
149
+
150
+ .editor-button:hover {
151
+ background-color: darkgreen;
152
+ }
153
+ ```
154
+
155
+ 2. Import the CSS file and use the classes in your component:
156
+
157
+ ```typescript
158
+ import { EditorProps } from 'document-model';
159
+ // import { ExampleDocument, actions } from '../../document-models/example';
160
+ import './editor.css'; // Import the CSS file
161
+
162
+ export type IProps = EditorProps<any>;
163
+
164
+ export default function Editor({ document, dispatch }: IProps) {
165
+ return (
166
+ <div className="editor-container"> {/* Use custom class */}
167
+ <h1 className="editor-title">Document Title</h1> {/* Use custom class */}
168
+ <h2 className="editor-subtitle">Document Subtitle</h2> {/* Default or other styles */}
169
+ <input
170
+ type="text"
171
+ placeholder="Small text input"
172
+ className="w-full p-2 border rounded mb-4" // Can mix with Tailwind/defaults
173
+ />
174
+ <textarea
175
+ placeholder="Large text area"
176
+ rows={4}
177
+ className="w-full p-2 border rounded mb-4" // Can mix with Tailwind/defaults
178
+ />
179
+ <button className="editor-button"> {/* Use custom class */}
180
+ Submit
181
+ </button>
182
+ </div>
183
+ );
184
+ }
185
+ ```
186
+ </details>
187
+
188
+ *Run `ph connect` to see your custom CSS styles applied.*
189
+
190
+ ---
191
+
192
+ ## ToDoList Editor
193
+
194
+ :::tip
195
+ ### Implementing Components
196
+ The editor we are about to implement makes use of some components from **Powerhouse Document Engineering**.
197
+ When you add the editor code, you'll see it makes use of two components, the `Checkbox` and `InputField`.
198
+ These are imported from the Powerhouse Document Engineering design system (`@powerhousedao/document-engineering/scalars`).
199
+
200
+ This system provides a library of reusable components to ensure consistency and speed up development.
201
+ You can explore available components, see usage examples, and understand their properties (props) using our Storybook instance. For a detailed guide on how to leverage the Document Engineering design system and Storybook, see [Using the Powerhouse Document Engineering](/academy/ComponentLibrary/DocumentEngineering) page.
202
+
203
+ For this tutorial, create a `components` folder inside `editors/to-do-list`. Then, within this new `components` folder, create the files for the `Checkbox` and `InputField` components (e.g., `Checkbox.tsx` and `InputField.tsx`) with the following code:
204
+ :::
205
+
206
+ <details>
207
+ <summary>Checkbox</summary>
208
+ ```typescript
209
+ import { Form, BooleanField } from "@powerhousedao/document-engineering/scalars";
210
+
211
+ interface CheckboxProps {
212
+ value: boolean;
213
+ onChange: (value: boolean) => void;
214
+ }
215
+
216
+ export const Checkbox = ({ value, onChange }: CheckboxProps) => {
217
+ return (
218
+ <Form onSubmit={() => {}}>
219
+ <BooleanField
220
+ name="checked"
221
+ description="Check this box to mark the todo as completed"
222
+ value={value}
223
+ onChange={onChange}
224
+ />
225
+ </Form>
226
+ );
227
+ };
228
+ ```
229
+ </details>
230
+
231
+ <details>
232
+ <summary>Inputfield</summary>
233
+ ```typescript
234
+ import { Form, StringField } from "@powerhousedao/document-engineering/scalars";
235
+
236
+ interface InputFieldProps {
237
+ input: string;
238
+ value: string;
239
+ label?: string;
240
+ onKeyDown: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;
241
+ handleInputChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
242
+ }
243
+
244
+ export const InputField = (props: InputFieldProps) => {
245
+ const { input, value, label, onKeyDown, handleInputChange } = props;
246
+
247
+ return (
248
+ <Form
249
+ defaultValues={{
250
+ input: input,
251
+ }}
252
+ onSubmit={() => {}}
253
+ resetOnSuccessfulSubmit
254
+ >
255
+ <StringField
256
+ style={{
257
+ color: "black",
258
+ }}
259
+ label={label}
260
+ name="input"
261
+ value={value}
262
+ onKeyDown={onKeyDown}
263
+ onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
264
+ handleInputChange(e);
265
+ }}
266
+ />
267
+ </Form>
268
+ );
269
+ };
270
+ ```
271
+ </details>
272
+
273
+
274
+ Below is the complete code for the To-Do List editor. It primarily uses Tailwind CSS for styling and imports the local `Checkbox` and `InputField` components you created in the previous step. These local components, in turn, utilize elements from the Powerhouse Document Engineering design system.
275
+
276
+ <details>
277
+ <summary>Complete ToDoList Editor Example (using Tailwind CSS)</summary>
278
+
279
+ ```typescript
280
+ // Import necessary types and components.
281
+ import { EditorProps } from 'document-model'; // Core type for editor components.
282
+ import {
283
+ ToDoListState, // Type for the global state of the ToDoList.
284
+ ToDoListAction, // Type for actions that can modify the ToDoList state.
285
+ ToDoListLocalState, // Type for local (non-shared) editor state (if needed).
286
+ ToDoItem, // Type for a single item in the list.
287
+ actions, // Object containing action creators for dispatching changes.
288
+ ToDoListDocument // The complete document structure including state and metadata.
289
+ } from '../../document-models/to-do-list/index.js'; // Path to your document model definition.
290
+ import { useState } from 'react'; // React hook for managing component-local state.
291
+ import { Checkbox } from './components/checkbox.js'; // Custom Checkbox component.
292
+ import { InputField } from './components/inputField.js'; // Custom InputField component.
293
+
294
+ // Define the props expected by this Editor component. It extends EditorProps with our specific document type.
295
+ export type IProps = EditorProps<ToDoListDocument>;
296
+
297
+ // Define the main Editor component function.
298
+ export default function Editor(props: IProps) {
299
+ // Destructure props for easier access.
300
+ const { document, dispatch } = props;
301
+ // Access the global state from the document object.
302
+ const { state: { global: state } } = document;
303
+
304
+ // --- Component State ---
305
+ // State for the text input field where new tasks are typed.
306
+ const [todoItem, setTodoItem] = useState('');
307
+ // State to track which item is currently being edited (null if none). Stores the item's ID.
308
+ const [editingItemId, setEditingItemId] = useState<string | null>(null);
309
+ // State to hold the text of the item currently being edited.
310
+ const [editedText, setEditedText] = useState('');
311
+
312
+ // --- JSX Structure (What gets rendered) ---
313
+ return (
314
+ // Main container div.
315
+ // `container`: Sets max-width based on viewport breakpoints.
316
+ // `mx-auto`: Centers the container horizontally.
317
+ // `p-4`: Adds padding on all sides (4 units, typically 1rem).
318
+ // `max-w-md`: Sets a maximum width (medium size).
319
+ <div className="container mx-auto p-4 max-w-md">
320
+ {/* Heading for the editor */}
321
+ {/* `text-2xl`: Sets font size to extra-large. */}
322
+ {/* `font-bold`: Makes the text bold. */}
323
+ {/* `mb-4`: Adds margin to the bottom (4 units). */}
324
+ <h1 className="text-2xl font-bold mb-4">To-do List</h1>
325
+
326
+ {/* Container for the input field and "Add" button */}
327
+ {/* `flex items-end`: Enables flexbox layout for children with bottom alignment. */}
328
+ {/* `gap-2`: Adds a small gap between flex items. */}
329
+ {/* `mb-4`: Adds margin to the bottom. */}
330
+ <div className="flex items-end gap-2 mb-4">
331
+ {/* Custom InputField component */}
332
+ <InputField
333
+ label="New Task" // Prop for accessibility/placeholder.
334
+ input={todoItem} // Current value from state.
335
+ value={todoItem} // Controlled component value.
336
+ handleInputChange={(e) => setTodoItem(e.target.value)} // Update state on change.
337
+ onKeyDown={(e) => { // Handle "Enter" key press to add item.
338
+ if (e.key === 'Enter' && todoItem.trim()) { // Check if key is Enter and input is not empty
339
+ dispatch(actions.addTodoItem({ // Dispatch action to add item.
340
+ id: Math.random().toString(), // Generate a simple unique ID (use a better method in production!).
341
+ text: todoItem,
342
+ }));
343
+ setTodoItem(''); // Clear the input field.
344
+ }
345
+ }}
346
+ />
347
+ {/* "Add" button */}
348
+ {/* `bg-blue-500`: Sets background color to blue. */}
349
+ {/* `hover:bg-blue-600`: Changes background color on hover. */}
350
+ {/* `text-white`: Sets text color to white. */}
351
+ {/* `px-4`: Adds horizontal padding (4 units). */}
352
+ {/* `py-1.5`: Adds vertical padding (1.5 units). */}
353
+ {/* `rounded`: Applies rounded corners. */}
354
+ {/* `transition-colors`: Smoothly animates color changes. */}
355
+ <button
356
+ className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-1.5 rounded transition-colors"
357
+ onClick={() => { // Handle button click to add item.
358
+ if (todoItem.trim()) { // Check if input is not empty
359
+ dispatch(actions.addTodoItem({ // Dispatch action to add item.
360
+ id: Math.random().toString(), // Simple unique ID.
361
+ text: todoItem,
362
+ }));
363
+ setTodoItem(''); // Clear the input field.
364
+ }
365
+ }}
366
+ >
367
+ Add
368
+ </button>
369
+ </div>
370
+
371
+ {/* Unordered list to display the to-do items */}
372
+ {/* `list-none`: Removes default list bullet points. */}
373
+ {/* `p-0`: Removes default padding. */}
374
+ <ul className="list-none p-0">
375
+ {/* Map over the items array in the global state to render each item */}
376
+ {state.items.map((item: ToDoItem) => (
377
+ // List item element for each to-do.
378
+ // `key={item.id}`: React requires a unique key for list items for efficient updates.
379
+ // `flex`: Enables flexbox layout (checkbox, text, delete icon in a row).
380
+ // `items-center`: Aligns items vertically in the center.
381
+ // `p-2`: Adds padding.
382
+ // `relative`: Needed for positioning the delete icon absolutely (if we were doing that).
383
+ // `border-b`: Adds a bottom border.
384
+ // `border-gray-100`: Sets border color to light gray.
385
+ <li
386
+ key={item.id}
387
+ className="flex items-center p-2 relative border-b border-gray-100"
388
+ >
389
+ {/* Custom Checkbox component */}
390
+ <Checkbox
391
+ value={item.checked} // Bind checked state to item's checked property.
392
+ onChange={() => { // Handle checkbox click.
393
+ dispatch(actions.updateTodoItem({ // Dispatch action to update item.
394
+ id: item.id,
395
+ checked: !item.checked, // Toggle the checked state.
396
+ }));
397
+ }}
398
+ />
399
+
400
+ {/* Conditional Rendering: Show input field or text based on editing state */}
401
+ {editingItemId === item.id ? (
402
+ // --- Editing State ---
403
+ // Input field shown when this item is being edited.
404
+ // `ml-2`: Adds left margin.
405
+ // `flex-grow`: Allows input to take available horizontal space.
406
+ // `p-1`: Adds small padding.
407
+ // `border`: Adds a default border.
408
+ // `rounded`: Applies rounded corners.
409
+ // `focus:outline-none`: Removes the default browser focus outline.
410
+ // `focus:ring-1 focus:ring-blue-500`: Adds a custom blue ring when focused.
411
+ <input
412
+ className="ml-2 flex-grow p-1 border rounded focus:outline-none focus:ring-1 focus:ring-blue-500"
413
+ value={editedText} // Controlled input value from editedText state.
414
+ onChange={(e) => setEditedText(e.target.value)} // Update editedText state.
415
+ onKeyDown={(e) => { // Handle "Enter" key to save changes.
416
+ if (e.key === 'Enter') {
417
+ dispatch(actions.updateTodoItem({ // Dispatch update action.
418
+ id: item.id,
419
+ text: editedText, // Save the edited text.
420
+ }));
421
+ setEditingItemId(null); // Exit editing mode.
422
+ }
423
+ }}
424
+ autoFocus // Automatically focus the input when it appears.
425
+ />
426
+ ) : (
427
+ // --- Display State ---
428
+ // Container for the item text and delete icon when not editing.
429
+ // `ml-2`: Adds left margin.
430
+ // `flex items-center`: Aligns text and icon vertically.
431
+ // `flex-grow`: Allows this container to take available space.
432
+ // `gap-1`: Adds a small gap between text and icon.
433
+ <div className="ml-2 flex items-center flex-grow gap-1">
434
+ {/* The actual to-do item text */}
435
+ {/* `cursor-pointer`: Shows a pointer cursor on hover, indicating clickability. */}
436
+ {/* Conditional class: Apply line-through and gray text if item is checked. */}
437
+ {/* `line-through`: Strikes through the text. */}
438
+ {/* `text-gray-500`: Sets text color to gray. */}
439
+ <span
440
+ className={`cursor-pointer ${item.checked ? 'line-through text-gray-500' : ''}`}
441
+ onClick={() => { // Handle click to enter editing mode.
442
+ setEditingItemId(item.id); // Set the ID of the item being edited.
443
+ setEditedText(item.text); // Initialize the input with current text.
444
+ }}
445
+ >
446
+ {item.text} {/* Display the item's text */}
447
+ </span>
448
+ {/* Delete "button" (using a span styled as a button) */}
449
+ {/* `text-gray-400`: Sets default text color to light gray. */}
450
+ {/* `cursor-pointer`: Shows pointer cursor. */}
451
+ {/* `opacity-40`: Makes it semi-transparent by default. */}
452
+ {/* `transition-all duration-200`: Smoothly animates all changes (opacity, color). */}
453
+ {/* `text-base font-bold`: Sets text size and weight. */}
454
+ {/* `inline-flex items-center`: Needed for proper alignment if using an icon font/SVG. */}
455
+ {/* `pl-1`: Adds small left padding. */}
456
+ {/* `hover:opacity-100`: Makes it fully opaque on hover. */}
457
+ {/* `hover:text-red-500`: Changes text color to red on hover. */}
458
+ <span
459
+ className="text-gray-400 cursor-pointer opacity-40 transition-all duration-200 text-base font-bold inline-flex items-center pl-1 hover:opacity-100 hover:text-red-500"
460
+ onClick={() => dispatch(actions.deleteTodoItem({ id: item.id }))} // Dispatch delete action on click.
461
+ >
462
+ × {/* Simple multiplication sign used as delete icon */}
463
+ </span>
464
+ </div>
465
+ )}
466
+ </li>
467
+ ))}
468
+ </ul>
469
+ </div>
470
+ );
471
+ }
472
+ ```
473
+ </details>
474
+
475
+ Now you can run the Connect app and see the **ToDoList** editor in action.
476
+
477
+ ```bash
478
+ ph connect
479
+ ```
480
+
481
+ In Connect, in the bottom right corner you'll find a new Document Model that you can create: **ToDoList**.
482
+ Click on it to create a new ToDoList document.
483
+
484
+ :::info
485
+ The editor will update dynamically, so you can play around with your editor styling while seeing your results appear in Connect Studio.
486
+ :::
487
+
488
+ Congratulations!
489
+ If you managed to follow this tutorial until this point, you have successfully implemented the **ToDoList** document model with its reducer operations and editor.
490
+
491
+ Now you can move on to creating a [custom drive explorer](/academy/MasteryTrack/BuildingUserExperiences/BuildingADriveExplorer) for your ToDoList document.
492
+ Imagine you have many ToDoLists sitting in a drive. A custom drive explorer will allow you to organize and track them at a glance, opening up a new world of possibilities to increase the functionality of your documents!
493
+
494
+
495
+
@@ -55,7 +55,7 @@ import BrowserOnly from '@docusaurus/BrowserOnly';
55
55
  <h3 className="card-title">Get Started</h3>
56
56
  </div>
57
57
  <div className={styles.cardContent}>
58
- <a href="/docs/academy/GetStarted/CreateNewPowerhouseProject" className="path-button">Build a Todo-list Document Model</a>
58
+ <a href="/academy/GetStarted/CreateNewPowerhouseProject" className="path-button">Build a Todo-list Document Model</a>
59
59
  </div>
60
60
  </div>
61
61
 
@@ -70,10 +70,10 @@ import BrowserOnly from '@docusaurus/BrowserOnly';
70
70
  <h3 className="card-title">Build User Experiences</h3>
71
71
  </div>
72
72
  <div className={styles.cardContent}>
73
- <a href="/docs/academy/GetStarted/BuildToDoListEditor" className="path-button">Building a Todo-list Editor</a>
74
- <a href="/docs/academy/BuildingUserExperiences/BuildingDocumentEditors" className="path-button">Building Document Editors</a>
75
- <a href="/docs/academy/MasteryTrack/BuildingUserExperiences/BuildingADriveExplorer" className="path-button">Building Custom Drive Explorers</a>
76
- <a href="/docs/academy/ComponentLibrary/DocumentEngineering" className="path-button">Component Library</a>
73
+ <a href="/academy/GetStarted/BuildToDoListEditor" className="path-button">Building a Todo-list Editor</a>
74
+ <a href="/academy/MasteryTrack/BuildingUserExperiences/BuildingDocumentEditors" className="path-button">Building Document Editors</a>
75
+ <a href="/academy/MasteryTrack/BuildingUserExperiences/BuildingADriveExplorer" className="path-button">Building Custom Drive Explorers</a>
76
+ <a href="/academy/ComponentLibrary/DocumentEngineering" className="path-button">Component Library</a>
77
77
  </div>
78
78
  </div>
79
79
 
@@ -106,10 +106,10 @@ import BrowserOnly from '@docusaurus/BrowserOnly';
106
106
  <h3 className="card-title">Work with Data</h3>
107
107
  </div>
108
108
  <div className={styles.cardContent}>
109
- <a href="//docs/academy/MasteryTrack/WorkWithData/ReadingAndWritingThroughTheAPI" className="path-button">Reading & Writing through the API</a>
110
- <a href="/docs/academy/MasteryTrack/WorkWithData/WorkingWithSubgraphs" className="path-button">Create your own Subgraph</a>
111
- <a href="/docs/academy/WorkWithData/Analytics Engine/intro" className="path-button">Using the Analytics Engine</a>
112
- <a href="/docs/academy/WorkWithData/Analytics Engine/intro" className="path-button">Using the Analytics Engine</a>
109
+ <a href="/academy/MasteryTrack/WorkWithData/ReadingAndWritingThroughTheAPI" className="path-button">Reading & Writing through the API</a>
110
+ <a href="/academy/MasteryTrack/WorkWithData/WorkingWithSubgraphs" className="path-button">Create your own Subgraph</a>
111
+ <a href="/academy/MasteryTrack/WorkWithData/Analytics-Engine/intro" className="path-button">Using the Analytics Engine</a>
112
+ <a href="/academy/MasteryTrack/WorkWithData/Analytics-Engine/intro" className="path-button">Using the Analytics Engine</a>
113
113
  </div>
114
114
  </div>
115
115
 
@@ -123,9 +123,9 @@ import BrowserOnly from '@docusaurus/BrowserOnly';
123
123
  </div>
124
124
  <div className={styles.cardContent}>
125
125
  <div className={styles.buttonContainer}>
126
- <a href="/docs/academy/MasteryTrack/Launch/PublishYourProject" className="path-button">Package & Publish</a>
127
- <a href="/docs/academy/Launch/LaunchYourBackend" className="path-button">Launch Back-end</a>
128
- <a href="/docs/academy/Launch/LaunchYourFrontend" className="path-button">Launch Front-end</a>
126
+ <a href="/academy/MasteryTrack/Launch/IntroductionToPackages" className="path-button">Intro To Packages</a>
127
+ <a href="/academy/MasteryTrack/Launch/PublishYourProject" className="path-button">Publish Your Project</a>
128
+ <a href="/academy/MasteryTrack/Launch/SetupEnvironment" className="path-button">Setup a Cloud Environment</a>
129
129
  </div>
130
130
  </div>
131
131
  </div>
@@ -139,7 +139,7 @@ import BrowserOnly from '@docusaurus/BrowserOnly';
139
139
  <h3 className="card-title">Cookbook</h3>
140
140
  </div>
141
141
  <div className={styles.cardContent}>
142
- <a href="/docs/academy/Cookbook" className="path-button">Powerhouse Recipes</a>
142
+ <a href="/academy/Cookbook" className="path-button">Powerhouse Recipes</a>
143
143
  </div>
144
144
  </div>
145
145
 
@@ -152,7 +152,7 @@ import BrowserOnly from '@docusaurus/BrowserOnly';
152
152
  <h3 className="card-title">Use-cases</h3>
153
153
  </div>
154
154
  <div className={styles.cardContent}>
155
- <a href="/docs/academy/ExampleUsecases/Chatroom/SetupBuilderEnvironment" className="path-button">Explore Use-cases</a>
155
+ <a href="/academy/ExampleUsecases/Chatroom/SetupBuilderEnvironment" className="path-button">Explore Use-cases</a>
156
156
  </div>
157
157
  </div>
158
158
 
@@ -164,7 +164,7 @@ import BrowserOnly from '@docusaurus/BrowserOnly';
164
164
  <h3 className="card-title">Architecture</h3>
165
165
  </div>
166
166
  <div className={styles.cardContent}>
167
- <a href="/academy/05-Architecture/00-PowerhouseArchitecture" className="path-button">Learn More</a>
167
+ <a href="/academy/Architecture/PowerhouseArchitecture" className="path-button">Learn More</a>
168
168
  </div>
169
169
  </div>
170
170
  </div>
@@ -1,5 +1,10 @@
1
1
  # What is a Document Model?
2
2
 
3
+ :::tip
4
+ This chapter on **Document Model Creation** will help you with an in depth practicial understanding while building an **advanced ToDoList** document model.
5
+ If you have completed the Get Started tutorial you will revisit familiar topics.
6
+ :::
7
+
3
8
  A Document Model is:
4
9
  - A structured software framework that represents and **manages business logic** within a digital environment.
5
10
  - A sophisticated template that **encapsulates the essential aspects of a digital process or a set of data**.
@@ -111,7 +116,7 @@ Every operation applied to a document is **stored as an event** in an append-onl
111
116
 
112
117
  ## **2. How Document Models Work Technically**
113
118
 
114
- Document models in Powerhouse rely on **event-driven architecture, event sourcing, and CQRS principles**. Heres a step-by-step breakdown:
119
+ Document models in Powerhouse rely on **event-driven architecture, event sourcing, and CQRS principles**. Here's a step-by-step breakdown:
115
120
 
116
121
  ### **2.1 Document Creation**
117
122
 
@@ -185,4 +190,8 @@ Document Models offer a range of features that can be leveraged to create sophis
185
190
 
186
191
  - **Version Control**: Similar to how Git manages changes to source code, Document Models in Connect will support version control, enabling users to track changes, compare different versions, and ensure data integrity over time.
187
192
 
188
- Document Models are a powerful primitive within the Powerhouse vision, offering a flexible, structured, and efficient way to manage business logic and data.
193
+ Document Models are a powerful primitive within the Powerhouse vision, offering a flexible, structured, and efficient way to manage business logic and data.
194
+
195
+ ### Up Next: How to build a Document Model
196
+
197
+ In the next chapters, we'll teach you how to build a ToDoList document model while explaining all of the theory that is involved.
@@ -21,6 +21,8 @@ GraphQL has a set of built-in **scalar types**:
21
21
  * `Boolean`: `true` or `false`.
22
22
  * `ID`: A unique identifier, often used as a key for a field. It is serialized in the same way as a String; however, it is not intended to be human-readable.
23
23
 
24
+ In addition to these standard types, the Powerhouse Document-Engineering system introduces custom scalars that are linked to reusable front-end components. These scalars are tailored for the web3 ecosystem and will be explored in the Component Library section of the documentation.
25
+
24
26
  ### Lists and Non-Null
25
27
  You can modify types using lists and non-null indicators:
26
28
  * **Lists**: To indicate that a field will return a list of a certain type, you wrap the type in square brackets, e.g., `[ToDoItem!]!`. This means the field `items` in `ToDoListState` will be a list of `ToDoItem` objects.
@@ -70,3 +72,6 @@ type ToDoItem {
70
72
  6. **Root State Type**: It's a common pattern to have a single root type for your document state (e.g., `ToDoListState`). This provides a clear entry point for accessing all document data.
71
73
 
72
74
  By carefully defining your state schema, you lay a solid foundation for your Powerhouse document model, making it robust, maintainable, and easy to work with. The schema dictates not only how data is stored but also how it can be queried and mutated through operations, which will be covered in the next section.
75
+
76
+ At the end of this Document Model Creation Chapter you will find the ToDoList Repository where you can explore the code and implementation of all the items we have discussed.
77
+ You'll be able to run the advanced ToDoList in Connect Studio and explore the reducers and editor code.