@powerhousedao/academy 0.1.0-dev.5 → 0.1.0-dev.6

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 0.1.0-dev.6 (2025-06-04)
2
+
3
+ ### 🩹 Fixes
4
+
5
+ - **academy:** docker build ([58e83be09](https://github.com/powerhouse-inc/powerhouse/commit/58e83be09))
6
+
7
+ ### ❤️ Thank You
8
+
9
+ - Frank
10
+
1
11
  ## 0.1.0-dev.5 (2025-06-03)
2
12
 
3
13
  ### 🩹 Fixes
package/Dockerfile CHANGED
@@ -11,7 +11,7 @@ ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0
11
11
  WORKDIR /app
12
12
  COPY . .
13
13
  RUN chmod +x entrypoint.sh
14
- RUN pnpm install --frozen-lockfile
14
+ RUN pnpm install
15
15
  RUN pnpm build
16
16
  ENV PORT=3000
17
17
  EXPOSE $PORT
@@ -33,6 +33,13 @@ This command downloads and sets up the Contributor Billing package, making its f
33
33
 
34
34
  You have now successfully installed `ph-cmd` and added your first package!
35
35
 
36
+ :::info
37
+ WORK IN PROGRESS @callmet
38
+ Let's explore what exactly you can do with this package
39
+ - Document model
40
+ - Drive App
41
+ :::
42
+
36
43
  ## Step 3: Run the Connect App in Studio mode
37
44
  To run the package locally in Connect Studio (our collaboration and contributor app), run the `ph connect` command.
38
45
 
@@ -40,7 +47,6 @@ To run the package locally in Connect Studio (our collaboration and contributor
40
47
 
41
48
  Renown is Powerhouse's decentralized identity and reputation system designed to address the challenge of trust within DAOs, where contributors often operate under pseudonyms. In traditional organizations, personal identity and reputation are key to establishing trust and accountability. Renown replicates this dynamic in the digital space, allowing contributors to earn experience and build reputation without revealing their real-world identities.
42
49
 
43
-
44
50
  :::tip
45
51
  When signing in with Renown, use an Ethereum or blockchain address that can function as your \'identity\', as this address will accrue more experience and history over time.
46
52
  :::
@@ -1,7 +1,7 @@
1
- # Create a new ToDoList Document
1
+ # Create a ToDoList Document
2
2
 
3
3
  ## Overview
4
- This tutorial guides you through creating a 'Powerhouse project' for a ToDoList. A Powerhouse project primarily consists of a document model and its editor. You'll be using Connect locally, known as 'Studio mode'.
4
+ This tutorial guides you through creating a 'Powerhouse project' for a **ToDoList**. A Powerhouse project primarily consists of a document model and its editor. You'll be using Connect locally, known as 'Studio mode'.
5
5
 
6
6
  ## Prerequisites
7
7
  - Powerhouse CLI installed: `pnpm install -g ph-cmd`
@@ -1,22 +1,21 @@
1
1
  # Define the ToDoList document specification
2
2
 
3
- In this tutorial, you will learn how to define the specifications for a `ToDoList` document model within the Connect application using its GraphQL schema, and then export the resulting document model specification document for your Powerhouse project.
3
+ In this tutorial, you will learn how to define the specifications for a **ToDoList** document model within the Connect application using its GraphQL schema, and then export the resulting document model specification document for your Powerhouse project.
4
4
  If you don't have a document specification file created yet, have a look at the previous step of this tutorial to create a new document specification.
5
5
 
6
6
  Before you start, make sure you have the Connect application running locally with the command `ph connect`
7
7
 
8
8
  ## ToDoList Document Specification
9
9
 
10
- Likely you have called your project 'ToDoList'. If you've used a different name, please create a new document specification named 'ToDoList'. Pay close attention to capitalization, as it influences our code.
10
+ Likely you have called your project 'ToDoList'. If you've used a different name, please create a new document specification named 'ToDoList'. **Pay close attention to capitalization, as it influences our code.**
11
+
11
12
  We'll continue with this project to teach you how to create a document model specification and later an editor for your document model. We use the **GraphQL Schema Definition Language** (SDL) to define the schema for the document model. Below, you can see the SDL for the `ToDoList` document model.
12
13
 
13
14
  :::info
14
15
  This schema defines the **data structure** of the document model and the types involved in its operations, which are detailed further as input types.
15
- Documents in Powerhouse leverage **event sourcing principles**, where every state transition is represented by an operation. GraphQL input types describe operations, ensuring that user intents are captured effectively. These operations detail the parameters needed for state transitions. The use of GraphQL aligns these transitions with explicit, validated, and reproducible commands, supporting **CQRS** (Command Query Responsibility Segregation) patterns.
16
+ Documents in Powerhouse leverage **event sourcing principles**, where every state transition is represented by an operation. GraphQL input types describe operations, ensuring that user intents are captured effectively. These operations detail the parameters needed for state transitions. The use of GraphQL aligns these transitions with explicit, validated, and reproducible commands.
16
17
  :::
17
18
 
18
-
19
-
20
19
  <details>
21
20
  <summary>State Schema of our ToDoList</summary>
22
21
 
@@ -6,21 +6,10 @@ To export the document model specification, follow the steps in the [Define ToDo
6
6
 
7
7
  ## Understanding Reducers in Document Models
8
8
 
9
- Reducers are a core concept in Powerhouse document models. They implement the state transition logic for each operation defined in your schema:
9
+ Reducers are a core concept in Powerhouse document models. They implement the state transition logic for each operation defined in your schema.
10
10
 
11
- 1. **Connection to Schema Definition Language (SDL)**: The reducers directly implement the operations you defined in your SDL. Remember how we defined `AddTodoItemInput`, `UpdateTodoItemInput`, and `DeleteTodoItemInput` in our schema? The reducers provide the actual implementation of what happens when those operations are performed.
12
-
13
- 2. **Event Sourcing Pattern**: Document models in Powerhouse follow event sourcing principles, where each operation is recorded in the document's history. The current state of the document is derived by applying all operations in sequence.
14
-
15
- 3. **Immutable Updates**: While the reducer code appears to modify the state directly, Powerhouse handles immutability behind the scenes. Each operation produces a new document state without modifying the previous one.
16
-
17
- 4. **Type Safety**: Powerhouse generates TypeScript types from your SDL, ensuring that your reducers and operations are type-safe.
18
-
19
- 5. **Pure Functions**: Reducers should be pure functions that depend only on the current state and the operation input, making them predictable and testable.
20
-
21
- Let's see how these concepts are implemented in our **ToDoList** document model.
22
-
23
- ## Importing the Document Model Specification and Generating Code
11
+ **Connection to Schema Definition Language (SDL)**: The reducers directly implement the operations you defined in your SDL. Remember how we defined `AddTodoItemInput`, `UpdateTodoItemInput`, and `DeleteTodoItemInput` in our schema?
12
+ The reducers provide the actual implementation of what happens when those operations are performed.
24
13
 
25
14
  To import the document model specification into your Powerhouse project, you can either:
26
15
 
@@ -71,7 +71,7 @@ import BrowserOnly from '@docusaurus/BrowserOnly';
71
71
  </div>
72
72
  <div className={styles.cardContent}>
73
73
  <a href="/docs/academy/GetStarted/BuildToDoListEditor" className="path-button">Building a Todo-list Editor</a>
74
- <a href="/docs/academy/BuildingUserExperiences/BuildingBeautifulDocumentEditors" className="path-button">Building Document Editors</a>
74
+ <a href="/docs/academy/BuildingUserExperiences/BuildingDocumentEditors" className="path-button">Building Document Editors</a>
75
75
  <a href="/docs/academy/MasteryTrack/BuildingUserExperiences/BuildingADriveExplorer" className="path-button">Building Custom Drive Explorers</a>
76
76
  <a href="/docs/academy/ComponentLibrary/DocumentEngineering" className="path-button">Component Library</a>
77
77
  </div>
@@ -1,6 +1,7 @@
1
1
  # Powerhouse Builder Tooling
2
2
 
3
3
  This page provides an overview of all the builder tooling offered by the Powerhouse ecosystem.
4
+ This list will be maintained and updated as our toolkit grows.
4
5
 
5
6
  ## Powerhouse Command Line Interface
6
7
  ___
@@ -181,7 +181,7 @@ Document Models offer a range of features that can be leveraged to create sophis
181
181
 
182
182
  - **API Integration**: Document Models can be integrated with Switchboard API or external APIs, allowing for the exchange of data between Connect and other systems or services.
183
183
 
184
- - **Data Analysi**s**: The structured nature of Document Models makes them ideal for data analysis and reporting. Users can extract insights and generate reports based on the data captured within the models which is accessible through read models. (Operational data + Analytics data which takes into account time series of the data).
184
+ - **Data Analysis**: The structured nature of Document Models makes them ideal for data analysis and reporting. Users can extract insights and generate reports based on the data captured within the models which is accessible through read models. (Operational data + Analytics data which takes into account time series of the data).
185
185
 
186
186
  - **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
187
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "label": "Document Model Creation",
3
3
  "link": {
4
- "type": "generated-index",
5
- "description": "This tutorial will guide you through the process of creating an advanced to-do list document model in Powerhouse, while getting you familiar with the Powerhouse document model framework."
4
+ "type": "doc",
5
+ "id": "academy/MasteryTrack/DocumentModelCreation/WhatIsADocumentModel"
6
6
  }
7
7
  }
@@ -0,0 +1,233 @@
1
+ # Build Document Editors
2
+
3
+ ## Build with React on Powerhouse
4
+
5
+ At Powerhouse, frontend development for document editors follows a simple and familiar flow, leveraging the power and flexibility of React.
6
+
7
+ ### Development Environment
8
+
9
+ Connect Studio is your primary tool for development. When you run `ph connect`, it provides a dynamic, local environment where you can define and preview your document models and their editors live. This replaces the need for tools like Storybook for editor development, though Storybook remains invaluable for exploring the [Powerhouse Component Library](#powerhouse-component-library).
10
+
11
+ Key aspects of the Powerhouse development environment:
12
+ - **React Foundation**: Build your editor UIs using React components, just as you would in any standard React project.
13
+ - **Automatic Build Processes**: Tailwind CSS is installed by default and fully managed by Connect Studio. There's no need to manually configure or run Tailwind or other build processes during development. Connect Studio handles CSS generation and other necessary build steps automatically, especially when you publish a package.
14
+ - **Styling Flexibility**: You are not limited to Tailwind. Regular CSS (`.css` files), inline styles, and any React-compatible styling method work exactly as you would expect.
15
+
16
+ Powerhouse aims to keep your developer experience clean, familiar, and focused:
17
+ - Build React components as you normally would.
18
+ - Use styling approaches you're comfortable with.
19
+ - Trust Connect Studio to handle the setup and build processes for you.
20
+
21
+ ### Generating Your Editor Template
22
+
23
+ To kickstart your editor development, Powerhouse provides a command to generate a basic editor template. This command reads your document model definition and creates the initial `editor.tsx` file.
24
+
25
+ For example, to generate an editor for a `ToDoList` document model with a document type `powerhouse/todolist`:
26
+ ```bash
27
+ ph generate --editor ToDoList --document-types powerhouse/todolist
28
+ ```
29
+ This will create the template in the `editors/to-do-list/editor.tsx` folder.
30
+
31
+ ### Styling Your Editor
32
+
33
+ You have several options for styling your editor components:
34
+
35
+ 1. **Default HTML Styling**: Standard HTML tags (`<h1>`, `<p>`, `<button>`, etc.) will render with default browser styles or any base styling provided by the Connect environment. This is suitable for basic structure and quick prototyping.
36
+
37
+ 2. **Tailwind CSS**: Connect Studio comes with Tailwind CSS integrated. You can directly use Tailwind utility classes in your JSX for rapid and consistent styling without writing separate CSS files.
38
+ *Example (from the ToDoList Editor):*
39
+ ```typescript
40
+ <div className="container mx-auto p-4 max-w-md">
41
+ <h1 className="text-2xl font-bold mb-4">To-do List</h1>
42
+ {/* ... more Tailwind styled elements */}
43
+ </div>
44
+ ```
45
+
46
+ 3. **Custom CSS Files**: You can import traditional CSS files (`.css`) to apply custom styles or integrate existing style libraries.
47
+ *Create an `editor.css` file in your editor's directory:*
48
+ ```css
49
+ /* editors/your-editor/editor.css */
50
+ .editor-container {
51
+ padding: 1rem;
52
+ border: 1px solid #ccc;
53
+ }
54
+ .editor-title {
55
+ color: navy;
56
+ font-size: 1.8rem;
57
+ }
58
+ ```
59
+ *Import and use it in your `editor.tsx`:*
60
+ ```typescript
61
+ import './editor.css'; // Import the CSS file
62
+
63
+ export default function Editor(props: IProps) {
64
+ return (
65
+ <div className="editor-container">
66
+ <h1 className="editor-title">My Document Title</h1>
67
+ {/* ... */}
68
+ </div>
69
+ );
70
+ }
71
+ ```
72
+
73
+ Choose the method or combination of methods that best suits your project needs and team preferences. Connect Studio (`ph connect`) will allow you to see your styles applied in real-time.
74
+
75
+ <details>
76
+ <summary>Refresher on React Hooks</summary>
77
+
78
+ All of the Powerhouse React Hooks can be found here: [Powerhouse React Hooks API Reference](docs/academy/APIReferences/ReactHooks)
79
+
80
+ React Hooks allow you to use various React features directly within your functional components. You can use built-in Hooks or combine them to create your own custom Hooks.
81
+
82
+ **What are Custom Hooks?**
83
+ A custom hook is a JavaScript function whose name starts with "use" and that calls other Hooks. They are used to:
84
+ - Reuse stateful logic between components.
85
+ - Abstract complex logic into a simpler interface.
86
+ - Isolate side effects, particularly those managed by `useEffect`.
87
+
88
+ **Key Built-in Hooks Examples:**
89
+ - `useState`: Lets a component "remember" information (state).
90
+ - `useEffect`: Lets a component perform side effects (e.g., data fetching, subscriptions, manually changing the DOM).
91
+ - `useContext`: Lets a component receive information from distant parent components without explicitly passing props through every level of the component tree.
92
+
93
+ **Naming Convention:**
94
+ Hook names must always start with `use` followed by a capital letter (e.g., `useState`, `useOnlineStatus`).
95
+
96
+ **Rules of Hooks:**
97
+ 1. **Only Call Hooks at the Top Level**: Don't call Hooks inside loops, conditions, or nested functions.
98
+ 2. **Only Call Hooks from React Functions**: Call Hooks from React functional components or from custom Hooks.
99
+
100
+ It's important to note that a function should only be named and treated as a hook if it actually utilizes one or more built-in React hooks. If a function (even if named `useSomething`) doesn't call any built-in hooks, it behaves like a regular JavaScript function, and making it a "hook" offers no specific React advantages.
101
+
102
+ For more details, see the official documentation and our API reference:
103
+ - [Reusing Logic with Custom Hooks (react.dev)](https://react.dev/learn/reusing-logic-with-custom-hooks)
104
+ - [Rules of Hooks (react.dev)](https://react.dev/reference/rules/rules-of-hooks)
105
+ - [Powerhouse React Hooks API Reference](docs/academy/APIReferences/ReactHooks)
106
+
107
+ </details>
108
+
109
+ ### State Management in Editors
110
+
111
+ When you build an editor in Powerhouse, your main editor component receives `EditorProps`. These props are crucial for interacting with the document:
112
+
113
+ * **`document`**: This object contains the entire document structure, including its current state. You'll typically access the global document state via `document.state.global`.
114
+ * **`dispatch`**: This function is your gateway to modifying the document's state. You call `dispatch` with an action object (usually created by action creators from your document model's generated code) to signal an intended change.
115
+
116
+ **Local vs. Global State:**
117
+ * **Local Component State**: For UI-specific state that doesn't need to be part of the persisted document model (e.g., the current text in an input field before submission, visibility of a dropdown), use React's `useState` hook.
118
+ ```typescript
119
+ const [inputValue, setInputValue] = useState('');
120
+ // ...
121
+ <input value={inputValue} onChange={(e) => setInputValue(e.target.value)} />
122
+ ```
123
+ * **Global Document State**: For data that is part of the document itself and should be saved (e.g., the items in a to-do list), you modify it by dispatching actions. The `document.state.global` object provides read-only access to this state within your editor.
124
+
125
+ **Dispatching Actions:**
126
+ Your document model's generated code (e.g., in `document-models/your-model/index.js` or `document-models/your-model/gen/operations.js`) will provide action creators.
127
+ ```typescript
128
+ // Assuming 'actions' are imported from your document model
129
+ // import { actions } from '../../document-models/to-do-list/index.js';
130
+
131
+ // Inside your editor component:
132
+ // function Editor({ document, dispatch }: IProps) {
133
+ // ...
134
+ // const handleAddItem = () => {
135
+ // if (todoItem.trim()) {
136
+ // dispatch(actions.addTodoItem({ // Dispatch action to add item.
137
+ // id: Math.random().toString(), // Generate a simple unique ID
138
+ // text: todoItem,
139
+ // }));
140
+ // setTodoItem(''); // Clear local input state
141
+ // }
142
+ // };
143
+ // }
144
+ ```
145
+ The actual state modification logic resides in your document model's reducers, ensuring that all changes are consistent and follow the defined operations.
146
+
147
+ ## Powerhouse Component Library
148
+
149
+ Powerhouse provides a rich set of reusable UI components through the **`@powerhousedao/document-engineering/scalars`** package. These components are designed for consistency, efficiency, and seamless integration with the Powerhouse ecosystem, with many based on GraphQL scalar types.
150
+
151
+ ### Exploring Components
152
+ You can explore available components, see usage examples, and understand their properties (props) using our Storybook instance:
153
+ [https://storybook.powerhouse.academy](https://storybook.powerhouse.academy)
154
+
155
+ Storybook allows you to:
156
+ * Visually inspect each component.
157
+ * Interact with different states and variations.
158
+ * View code snippets for basic implementation.
159
+ * Consult the props table for detailed configuration options.
160
+
161
+ ### Using Components
162
+ 1. **Import**: Add an import statement at the top of your editor file:
163
+ ```typescript
164
+ import { Checkbox, StringField, Form } from '@powerhousedao/document-engineering/scalars';
165
+ ```
166
+ 2. **Implement**: Use the component in your JSX, configuring it with props:
167
+ ```typescript
168
+ // Example using StringField for an input
169
+ <Form onSubmit={() => { /* Handle submission */ }}>
170
+ <StringField
171
+ name="taskName"
172
+ label="New Task"
173
+ value={taskText} // From local state
174
+ onChange={(e) => setTaskText(e.target.value)}
175
+ />
176
+ </Form>
177
+ ```
178
+
179
+ ### Creating Local Wrapper Components
180
+ Sometimes, you might want to create local wrapper components in your editor's project to encapsulate specific configurations or behaviors for library components. This was demonstrated in the "Build a ToDoList Editor" tutorial with `Checkbox.tsx` and `InputField.tsx` components, which internally used `BooleanField` and `StringField` from the `@powerhousedao/document-engineering/scalars` library.
181
+
182
+ **Example: Local `Checkbox` Wrapper (conceptual)**
183
+ ```typescript
184
+ // editors/to-do-list/components/checkbox.tsx
185
+ import { Form, BooleanField } from "@powerhousedao/document-engineering/scalars";
186
+
187
+ interface CustomCheckboxProps {
188
+ value: boolean;
189
+ onChange: (value: boolean) => void;
190
+ label?: string; // Added custom prop or passed through
191
+ }
192
+
193
+ export const Checkbox = ({ value, onChange, label }: CustomCheckboxProps) => {
194
+ return (
195
+ <Form onSubmit={() => { /* May not be needed for simple checkbox */ }}>
196
+ <BooleanField
197
+ name="customChecked" // Internal name for the form field
198
+ description={label || "Toggle state"} // Use label for description
199
+ value={value}
200
+ onChange={onChange}
201
+ />
202
+ </Form>
203
+ );
204
+ };
205
+ ```
206
+ This pattern helps keep your main editor file cleaner and allows for more complex compositions.
207
+
208
+ ## Conceptual Example: Building a ToDoList Editor
209
+
210
+ Let's consider key aspects of building an editor like the `ToDoList` example:
211
+
212
+ 1. **Input for New Items**:
213
+ * Use a local `useState` to manage the text of the new to-do item.
214
+ * Use an `InputField` (or a `StringField` from the library) for text entry.
215
+ * On "Add" button click or "Enter" key press, `dispatch` an `addTodoItem` action with the current input value.
216
+
217
+ 2. **Displaying List Items**:
218
+ * Map over `document.state.global.items`.
219
+ * For each item, display its `text` and a `Checkbox`.
220
+ * The `Checkbox` `value` should be bound to `item.checked`.
221
+ * Its `onChange` handler should `dispatch` an `updateTodoItem` action to toggle the `checked` status.
222
+
223
+ 3. **Editing Items**:
224
+ * Implement local state (`editingItemId`, `editedText`) to manage which item is being edited and its current text.
225
+ * Conditionally render either the item text (display mode) or an input field (edit mode).
226
+ * When entering edit mode, populate `editedText` with the item's current text.
227
+ * On saving the edit (e.g., "Enter" key in the input), `dispatch` an `updateTodoItem` action with the new text.
228
+
229
+ 4. **Deleting Items**:
230
+ * Provide a delete button/icon next to each item.
231
+ * Its `onClick` handler should `dispatch` a `deleteTodoItem` action with the item's `id`.
232
+
233
+ By combining local React state for UI control with dispatched actions for document state mutations, and leveraging the Powerhouse Component Library, you can build powerful and interactive document editors. Always refer to your document model's defined operations and state schema as the source of truth for how data should be structured and modified.
@@ -1,8 +1,7 @@
1
1
  {
2
- "label": "Build User Experiences",
3
- "position": 4,
4
- "link": {
5
- "type": "generated-index",
6
- "description": "Learn how to build beautiful document editors and drive-apps in Connect."
7
- }
8
- }
2
+ "label": "Building User Experiences",
3
+ "link": {
4
+ "type": "doc",
5
+ "id": "academy/MasteryTrack/BuildingUserExperiences/BuildingDocumentEditors"
6
+ }
7
+ }
@@ -1,5 +1,87 @@
1
1
  # React Hooks (WIP)
2
2
 
3
+ The idea is to make this feel as simple and familiar as using useState.
4
+ Happy Path would look something like this:
5
+
6
+ ```js
7
+ // in a component that only needs to read a value, you can use
8
+ const invoiceName = useReadDocumentField('myInvoiceDocumentId', 'name') // returns a string which is the `name`
9
+ // and for documents that need to update data as well, you would have
10
+ const updateInvoiceName = useUpdateDocumentField('myInvoiceDocumentId', 'name') // returns a function that takes a new string for the new name and dispatches the update
11
+ // finally, we can combine these into a single hook which works like react's useState hook returning both the value and updater function
12
+ const [invoiceName, updateInvoiceName] = useDocumentField('myInvoiceDocumentId', 'name')
13
+
14
+
15
+ // Read-only value
16
+ const invoiceName = useReadDocumentField('docId', 'name')
17
+
18
+ // Write-only updater
19
+ const updateInvoiceName = useUpdateDocumentField('docId', 'name')
20
+
21
+ // Combined read + write (like useState)
22
+ const [invoiceName, updateInvoiceName] = useDocumentField('docId', 'name')
23
+ ```
24
+
25
+ Request Translation
26
+ Global access to drive state: A top-level, possibly context-based, way to introspect and interact with any document and its state tree without manually passing things around.
27
+ Global dispatcher access: A utility or API (probably a hook or service function) where they give a document ID and get back all the relevant dispatch functions — kind of like a command palette for document ops.
28
+ Time spent wiring > time spent building Frustration with current DX (developer experience) — they want abstractions and helpers to just do the thing.
29
+
30
+ Core Hooks & Patterns
31
+ - useDocumentField
32
+ - useReadDocumentField
33
+ - useUpdateDocumentField
34
+ - useDocumentDispatch(docId): updateX, delete, ...
35
+
36
+ Global Drive Access
37
+ - How to access and manipulate the global document tree
38
+ - How to inspect children from parent context
39
+ - Tree traversal utilities (if any)
40
+
41
+ Convenience APIs
42
+ - Utility functions like getDispatchFunctions(docId)
43
+ - “Quick Start” to manipulate any document like a pro
44
+
45
+ Working with Context
46
+ - DriveContext: what lives there, how to use it
47
+ - Example: using context to get current doc, sibling docs
48
+
49
+ Best Practices & Patterns
50
+ - When to use useDocumentField vs getDispatch
51
+ - Composing document fields into custom logic
52
+
53
+ <details>
54
+ <summary>Refresher on React Hooks</summary>
55
+
56
+ React Hooks allow you to use various React features directly within your functional components. You can use built-in Hooks or combine them to create your own custom Hooks.
57
+
58
+ **What are Custom Hooks?**
59
+ A custom hook is a JavaScript function whose name starts with "use" and that calls other Hooks. They are used to:
60
+ - Reuse stateful logic between components.
61
+ - Abstract complex logic into a simpler interface.
62
+ - Isolate side effects, particularly those managed by `useEffect`.
63
+
64
+ **Key Built-in Hooks Examples:**
65
+ - `useState`: Lets a component "remember" information (state).
66
+ - `useEffect`: Lets a component perform side effects (e.g., data fetching, subscriptions, manually changing the DOM).
67
+ - `useContext`: Lets a component receive information from distant parent components without explicitly passing props through every level of the component tree.
68
+
69
+ **Naming Convention:**
70
+ Hook names must always start with `use` followed by a capital letter (e.g., `useState`, `useOnlineStatus`).
71
+
72
+ **Rules of Hooks:**
73
+ 1. **Only Call Hooks at the Top Level**: Don't call Hooks inside loops, conditions, or nested functions.
74
+ 2. **Only Call Hooks from React Functions**: Call Hooks from React functional components or from custom Hooks.
75
+
76
+ It's important to note that a function should only be named and treated as a hook if it actually utilizes one or more built-in React hooks. If a function (even if named `useSomething`) doesn't call any built-in hooks, it behaves like a regular JavaScript function, and making it a "hook" offers no specific React advantages.
77
+
78
+ For more details, see the official documentation and our API reference:
79
+ - [Reusing Logic with Custom Hooks (react.dev)](https://react.dev/learn/reusing-logic-with-custom-hooks)
80
+ - [Rules of Hooks (react.dev)](https://react.dev/reference/rules/rules-of-hooks)
81
+ - [Powerhouse React Hooks API Reference](docs/academy/APIReferences/ReactHooks)
82
+
83
+ </details>
84
+
3
85
  ### Hook Name and Signature
4
86
  The name of the hook and its TypeScript (or JavaScript) signature.
5
87
  ### Description
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powerhousedao/academy",
3
- "version": "0.1.0-dev.5",
3
+ "version": "0.1.0-dev.6",
4
4
  "homepage": "https://powerhouse.academy",
5
5
  "dependencies": {
6
6
  "@codesandbox/sandpack-react": "^2.14.4",
package/sidebars.ts CHANGED
@@ -10,7 +10,7 @@ import type { SidebarsConfig } from '@docusaurus/plugin-content-docs';
10
10
 
11
11
  Create as many sidebars as you want.
12
12
  */
13
- const sidebars: SidebarsConfig = {
13
+ const sidebars = {
14
14
  // By default, Docusaurus generates a sidebar from the docs folder structure
15
15
  academySidebar: [
16
16
  {
@@ -49,9 +49,18 @@ const sidebars: SidebarsConfig = {
49
49
  type: 'category',
50
50
  label: 'Document Model Creation',
51
51
  link: {
52
- type: 'generated-index',
52
+ type: 'doc',
53
+ id: "academy/MasteryTrack/DocumentModelCreation/WhatIsADocumentModel"
53
54
  },
54
- items: [{type: 'autogenerated', dirName: 'academy/02-MasteryTrack/02-DocumentModelCreation'}]
55
+ items: [
56
+ 'academy/MasteryTrack/DocumentModelCreation/WhatIsADocumentModel',
57
+ 'academy/MasteryTrack/DocumentModelCreation/SpecifyTheStateSchema',
58
+ 'academy/MasteryTrack/DocumentModelCreation/SpecifyDocumentOperations',
59
+ 'academy/MasteryTrack/DocumentModelCreation/UseTheDocumentModelGenerator',
60
+ 'academy/MasteryTrack/DocumentModelCreation/ImplementDocumentReducers',
61
+ 'academy/MasteryTrack/DocumentModelCreation/ImplementDocumentModelTests',
62
+ 'academy/MasteryTrack/DocumentModelCreation/ExampleToDoListRepository',
63
+ ]
55
64
  },
56
65
  {
57
66
  type: 'category',
@@ -59,7 +68,27 @@ const sidebars: SidebarsConfig = {
59
68
  link: {
60
69
  type: 'generated-index',
61
70
  },
62
- items: [{type: 'autogenerated', dirName: 'academy/02-MasteryTrack/03-BuildingUserExperiences'}]
71
+ items: [
72
+ 'academy/MasteryTrack/BuildingUserExperiences/BuildingDocumentEditors',
73
+ 'academy/MasteryTrack/BuildingUserExperiences/ConfiguringDrives',
74
+ 'academy/MasteryTrack/BuildingUserExperiences/BuildingADriveExplorer',
75
+ ]
76
+ },
77
+ {
78
+ type: 'category',
79
+ label: 'Document Tools',
80
+ link: {
81
+ type: 'generated-index',
82
+ },
83
+ items: [{ type: 'autogenerated', dirName: 'academy/02-MasteryTrack/03-BuildingUserExperiences/07-DocumentTools' }]
84
+ },
85
+ {
86
+ type: 'category',
87
+ label: 'Authorization',
88
+ link: {
89
+ type: 'generated-index',
90
+ },
91
+ items: [{ type: 'autogenerated', dirName: 'academy/02-MasteryTrack/03-BuildingUserExperiences/08-Authorization' }]
63
92
  },
64
93
  {
65
94
  type: 'category',
@@ -164,7 +164,7 @@ export default function HomepageFeatures() {
164
164
  </div>
165
165
  <div className={styles.cardContent}>
166
166
  <a href="/docs/academy/GetStarted/BuildToDoListEditor" className={styles.pathButton}>Building a Todo-list Editor</a>
167
- <a href="/docs/academy/BuildingUserExperiences/BuildingBeautifulDocumentEditors" className={styles.pathButton}>Building Beautiful Document Editors</a>
167
+ <a href="/docs/academy/BuildingUserExperiences/BuildingDocumentEditors" className={styles.pathButton}>Building Beautiful Document Editors</a>
168
168
  <a href="/docs/academy/MasteryTrack/BuildingUserExperiences/BuildingADriveExplorer" className={styles.pathButton}>Building Custom Drive Explorers</a>
169
169
  </div>
170
170
  </div>
@@ -459,3 +459,8 @@ html[data-theme='dark'] .DocSearch-Hits > *:empty {
459
459
  .doc-card-list-item {
460
460
  width: 100%; /* Ensure items take full width */
461
461
  }
462
+
463
+ /* Attempt to hide icons in DocCard titles */
464
+ .doc-card-list .card h2 svg {
465
+ display: none !important;
466
+ }
@@ -1,109 +0,0 @@
1
- # Build Document Editors
2
-
3
- *Placeholder for a tutorial about building beautiful document editors.*
4
-
5
- ## Build with React on Powerhouse
6
-
7
- At Powerhouse, frontend development follows a simple and familiar flow. Tailwind CSS is installed by default and fully managed by Connect Studio — you can use Tailwind classes freely, but you’re not required to. Regular CSS, inline styles, and any React-compatible styling method work exactly as you would expect in a standard React project. There is no need to manually configure or run Tailwind or build processes; **Connect Studio automatically handles everything during development.**
8
-
9
- For component visualization and testing, **Connect Studio replaces the need for Storybook**. Please do not use Storybook by default — Connect Studio provides a dynamic, local environment where you can define and preview your document models and editors live. If you still wish to set up Storybook on your own, you may, but it is unsupported and discouraged.
10
-
11
- During normal development, simply run Connect Studio with `ph connect`. Manual build commands are only needed when you publish a package, at which point the necessary build steps (including CSS generation) are handled automatically.
12
-
13
- Powerhouse aims to keep your developer experience clean, familiar, and focused.
14
- - Build React components as you would in any project.
15
- - Use styling approaches you're comfortable with.
16
- - Trust Connect Studio to handle the setup for you.
17
-
18
- ### Building with react hooks
19
-
20
- What are React Hooks?
21
-
22
- From the React docs:
23
-
24
- "Hooks let you use different React features from your components. You can either use the built-in Hooks or combine them to build your own."
25
- https://react.dev/reference/react/hooks
26
-
27
- The "combine them to build your own" part is key here. A so-called "custom hook" is just a function that uses these built-in hooks.
28
-
29
- There are several types of built-in hooks which are used to solve different problems.
30
-
31
- For example:
32
-
33
- State lets a component “remember” information like user input.
34
-
35
- Effects let a component connect to and synchronize with external systems.
36
-
37
- Context lets a component receive information from distant parents without passing it as props.
38
-
39
- Details about custom hooks are provided here: https://react.dev/learn/reusing-logic-with-custom-hooks
40
-
41
- In summary, there are three reasons to use custom hooks:
42
-
43
- To re-use logic that calls multiple hooks.
44
- To abstract away the complexity of multiple hooks.
45
- To isolate the side effects of the useEffect hook.
46
-
47
- Hook names must start with use followed by a capital letter, like useState (built-in) or useOnlineStatus (custom, like earlier on the page). Hooks may return arbitrary values.
48
-
49
- https://react.dev/learn/reusing-logic-with-custom-hooks#hook-names-always-start-with-use
50
-
51
- When you use any function that starts with "use", react will treat it as a hook and expect it to follow the rules of hooks.
52
-
53
- Rules of Hooks
54
- https://react.dev/reference/rules/rules-of-hooks
55
-
56
- Hooks are defined using JavaScript functions, but they represent a special type of reusable UI logic with restrictions on where they can be called.
57
-
58
- Only call Hooks at the top level
59
- Only call Hooks from React functions
60
-
61
- React needs these rules to ensure that the state is properly managed and that the component behaves as expected.
62
-
63
- So it is indeed possible to create a "hook" like so:
64
-
65
- ```
66
- function useCurrentTime() {
67
- const currentTime = new Date().toLocaleTimeString();
68
-
69
- return currentTime;
70
- }
71
- ```
72
-
73
- And this is technically a hook, but making it a hook is pointless because it doesn't use any of the built-in hooks.
74
-
75
- There is no reason that this could not just be:
76
-
77
- ```
78
- function getCurrentTime() {
79
- return new Date().toLocaleTimeString();
80
- }
81
- ```
82
-
83
- Because in a component, both hooks and normal functions are called on every render.
84
-
85
- So if your component looks like this:
86
-
87
- ```
88
- function MyComponent() {
89
- const currentTimeFromFunc = getCurrentTime();
90
- }
91
- ```
92
-
93
- or this:
94
-
95
- ```
96
- function MyComponent() {
97
- const currentTimeFromHook = useCurrentTime();
98
- }
99
- ```
100
-
101
- The end result would be the same. The function would be called on every render.
102
-
103
- So in summary, the only reason a function should be a hook is if it uses one or more built-in hooks.
104
-
105
- In general, you will not want to take a normal function and turn it into a hook, because your normal function should not have been trying to use react hooks in the first place.
106
-
107
- ## Powerhouse Component Library
108
-
109
- TBD