diff --git a/exercises/01.use-state/01.solution.initial-state/README.mdx b/exercises/01.use-state/01.solution.initial-state/README.mdx
index 0917c31..4dc0803 100644
--- a/exercises/01.use-state/01.solution.initial-state/README.mdx
+++ b/exercises/01.use-state/01.solution.initial-state/README.mdx
@@ -1,4 +1,4 @@
# Initial State
👨💼 Great work! Now at least we're not just throwing an error. But let's handle
-the state update...
+the state update next.
diff --git a/exercises/01.use-state/02.problem.update-state/README.mdx b/exercises/01.use-state/02.problem.update-state/README.mdx
index ba173fd..a43e616 100644
--- a/exercises/01.use-state/02.problem.update-state/README.mdx
+++ b/exercises/01.use-state/02.problem.update-state/README.mdx
@@ -1 +1,11 @@
# Update State
+
+👨💼 Alright, right now when you click the button, nothing happens. Let's get it
+to update the state.
+
+Update the `setState` function to assign the given state to the new state.
+
+
+ When you do this, it'll not actually update the number in the button either.
+ We'll get to that soon!
+
diff --git a/exercises/01.use-state/02.solution.update-state/README.mdx b/exercises/01.use-state/02.solution.update-state/README.mdx
index ba173fd..2f33ae5 100644
--- a/exercises/01.use-state/02.solution.update-state/README.mdx
+++ b/exercises/01.use-state/02.solution.update-state/README.mdx
@@ -1 +1,4 @@
# Update State
+
+👨💼 So we're updating the state value, but it's not actually updating the number
+in the button? What gives?!
diff --git a/exercises/01.use-state/03.problem.re-render/README.mdx b/exercises/01.use-state/03.problem.re-render/README.mdx
index 7ebea2b..83d9b32 100644
--- a/exercises/01.use-state/03.problem.re-render/README.mdx
+++ b/exercises/01.use-state/03.problem.re-render/README.mdx
@@ -1 +1,30 @@
# Re-render
+
+👨💼 Ok, so we're initializing our state properly and we're updating the state
+properly as well. The problem is we're not updating the UI when the state gets
+updated. Remember, we're not React. We need to tell React when the state has
+changed so it will render our component again.
+
+Because we're not React, the way we will do this is by simply calling `render`
+our our root again. Remember what the bottom of our file looks like?
+
+```tsx lines=4
+const rootEl = document.createElement('div')
+document.body.append(rootEl)
+const appRoot = createRoot(rootEl)
+appRoot.render()
+```
+
+That last line there is where we render the component. So we just need to call
+that any time we want the component updated!
+
+So in this exercise, wrap that bit in a function and call it once for the
+initial render and once in the `setState` function.
+
+Feel free to toss in a `console.log` in the component to make sure it's
+re-rendering.
+
+
+ When you're finished with this, the UI will **still** not work like you
+ expect. I promise we'll get to that very soon!
+
diff --git a/exercises/01.use-state/03.solution.re-render/README.mdx b/exercises/01.use-state/03.solution.re-render/README.mdx
index 7ebea2b..247f3df 100644
--- a/exercises/01.use-state/03.solution.re-render/README.mdx
+++ b/exercises/01.use-state/03.solution.re-render/README.mdx
@@ -1 +1,5 @@
# Re-render
+
+👨💼 Great work! Now we're not only updating the state, but we're also triggering
+a re-render so the UI can be updated. Unfortunately that seems to not be working
+either? Let's figure out why.
diff --git a/exercises/01.use-state/04.problem.preserve-state/README.mdx b/exercises/01.use-state/04.problem.preserve-state/README.mdx
index 48be07e..deb434c 100644
--- a/exercises/01.use-state/04.problem.preserve-state/README.mdx
+++ b/exercises/01.use-state/04.problem.preserve-state/README.mdx
@@ -1 +1,26 @@
# Preserve State
+
+👨💼 Alright, so there are actually two problems here. First, when the user clicks
+on the button, we update the `state` variable inside the `useState` closure, but
+that variable is not accessible by our component. Our component has its own
+variable called `count` which is not being updated
+
+
+ Just because two variables point to the same object in memory (or in our case,
+ the same number) doesn't mean they stay in sync when one is reassigned. That's
+ just how JavaScript works.
+
+
+The second problem we have is when our component is called, it calls `useState`
+and that creates a brand new `state` variable that's assigned to the
+`initialState` variable again.
+
+So we need a way to preserve the state between renders. We can do that by
+pulling the `state` and `setState` variables outside the `useState` hook and
+simply assigning them on the initial render of the component.
+
+Give that a try!
+
+
+ The button will finally work on this one, I promise!
+
diff --git a/exercises/01.use-state/04.solution.preserve-state/README.mdx b/exercises/01.use-state/04.solution.preserve-state/README.mdx
index 48be07e..9c2fb51 100644
--- a/exercises/01.use-state/04.solution.preserve-state/README.mdx
+++ b/exercises/01.use-state/04.solution.preserve-state/README.mdx
@@ -1 +1,4 @@
# Preserve State
+
+👨💼 Great work! Our UI is working properly! By preserving our state we're able to
+make changes to it and render again whenever that value changes.
diff --git a/exercises/01.use-state/FINISHED.mdx b/exercises/01.use-state/FINISHED.mdx
index 2f1904c..60269b3 100644
--- a/exercises/01.use-state/FINISHED.mdx
+++ b/exercises/01.use-state/FINISHED.mdx
@@ -1 +1,7 @@
# useState
+
+👨💼 This is a great time for you to take a break and reflect on your learnings so
+far. Take a moment and then when you're ready, we'll see you in the next
+exercise.
+
+There's still plenty to do!
diff --git a/exercises/02.multiple-hooks/01.problem.phase/README.mdx b/exercises/02.multiple-hooks/01.problem.phase/README.mdx
index 4606169..551bf2b 100644
--- a/exercises/02.multiple-hooks/01.problem.phase/README.mdx
+++ b/exercises/02.multiple-hooks/01.problem.phase/README.mdx
@@ -1 +1,31 @@
# Render Phase
+
+🧝♂️ Hi! I made a change to the code a bit. Now we're rendering two buttons, the
+count button is still there, but now we're also a button for disabling the count
+button. I needed to add another `useState` for that, but it's not working. You
+can check my work if you'd like. Can you get it
+working? Thanks!
+
+👨💼 Thanks for adding those buttons Kellie!
+
+Ok, so what we need you to do is fix the problem. If you add a
+`console.log({ count, enabled })` to the component, you'll get
+`{ count: 0, enabled: 0 }`. This is because the first time the `useState` is
+called initializes the state and the second time it's called, it just references
+the first one.
+
+So to start off fixing this issue, you're going to need to formalize how we
+determine whether state gets initialized or referenced.
+
+Really, `useState` can be called in two scenarios:
+
+- Initialization
+- Updates
+
+So we're going to keep track of how this is called with a `phase` variable. The
+emoji will guide you in the right direction. Good luck!
+
+
+ Note it's not going to quite work when you're finished with this step, but
+ it'll work soon!
+
diff --git a/exercises/02.multiple-hooks/01.solution.phase/README.mdx b/exercises/02.multiple-hooks/01.solution.phase/README.mdx
index 4606169..499af69 100644
--- a/exercises/02.multiple-hooks/01.solution.phase/README.mdx
+++ b/exercises/02.multiple-hooks/01.solution.phase/README.mdx
@@ -1 +1,8 @@
# Render Phase
+
+👨💼 Great! It's not quite working yet, now if we add
+`console.log({ count, enabled })` to the component, we'll get
+`{ count: 0, enabled: true }` like you'd expect, but when you click the counter
+button we get `{ count: 1, enabled: 1 }` 😅. And if you click the disable button
+you get `{ count: false, enabled: false }`. What the heck is going on!? Let's
+find out.
diff --git a/exercises/02.multiple-hooks/02.problem.hook-id/README.mdx b/exercises/02.multiple-hooks/02.problem.hook-id/README.mdx
index fcbe8c5..2d9e08f 100644
--- a/exercises/02.multiple-hooks/02.problem.hook-id/README.mdx
+++ b/exercises/02.multiple-hooks/02.problem.hook-id/README.mdx
@@ -1 +1,18 @@
# Hook ID
+
+👨💼 Based on what's happening now, I think we're not isolating the `state`
+between the two hooks. We need to uniquely identify each hook and store their
+state separately.
+
+We know that the hooks are called in the same order every time, so we could keep
+a call index (we'll call it the `hookIndex`) and increment it every time
+`useState` is called. That way, we could assign the first hook an ID of `0` and
+the second hook an ID of `1`.
+
+Then we store the `state` and `setState` in an array with their ID as the
+key.
+
+Then, whenever we render we just reset the `hookIndex` to `0` and we'll be
+golden!
+
+It'll work this time, I promise!
diff --git a/exercises/02.multiple-hooks/02.solution.hook-id/README.mdx b/exercises/02.multiple-hooks/02.solution.hook-id/README.mdx
index fcbe8c5..02fd639 100644
--- a/exercises/02.multiple-hooks/02.solution.hook-id/README.mdx
+++ b/exercises/02.multiple-hooks/02.solution.hook-id/README.mdx
@@ -1 +1,5 @@
# Hook ID
+
+👨💼 Hey, that works! And now you understand why it's important to avoid
+conditionally calling hooks or call them in loops. Their call order is their
+only uniquely identifying trait!
diff --git a/exercises/02.multiple-hooks/FINISHED.mdx b/exercises/02.multiple-hooks/FINISHED.mdx
index 2ac69f7..8d6d98e 100644
--- a/exercises/02.multiple-hooks/FINISHED.mdx
+++ b/exercises/02.multiple-hooks/FINISHED.mdx
@@ -1 +1,5 @@
# Multiple Hooks
+
+👨💼 Whew, now we've got multiple `useState` hooks in a single component working!
+It's a good time for a break. Write down what you learned, then we'll see you
+back soon!
diff --git a/exercises/02.multiple-hooks/README.mdx b/exercises/02.multiple-hooks/README.mdx
index 67aeb28..dd2a1b7 100644
--- a/exercises/02.multiple-hooks/README.mdx
+++ b/exercises/02.multiple-hooks/README.mdx
@@ -1,10 +1,36 @@
# Multiple Hooks
+Often components require more than a single hook. In fact, often they'll use
+two or more of the `useState` hook. If we tried that with our implementation
+right now things wouldn't work so well and I think you can imagine why.
+
+The tricky part about this is when you have more than one hook, you need to be
+able to track their values over the lifetime of the component relative to each
+other and that component. What makes this difficult though is that there's no
+uniquely identifying information about the hooks:
+
+```tsx
+const [count1, setCount1] = useState(0)
+const [count2, setCount2] = useState(0)
+```
+
+Having two elements of state like this in a component is perfectly legitimate,
+but our current implementation wouldn't work for that at all because the state
+would be shared between the two hooks.
+
+So how do we get around that?
+
+Well, it's not entirely true to say that there's no uniquely identifying
+information about the hooks.... There actually is something unique about these
+function calls and that is the order in which they are called!
+
+If we can assume that they'll always be called in the same order, then we can
+assign the first one an ID of `0` and the second one an ID of `1`. Then we can
+use that ID to track the state of the hooks!
+
Something you will hopefully gather from this exercise is an understanding of
why the ["rules of hooks"](https://react.dev/reference/rules/rules-of-hooks) is
-a thing. The rules are:
-
-- Only call Hooks at the top level
-- Only call Hooks from React functions
+a thing. Specifically the rule that hooks must be called at the top level (and
+not conditionally).
-As we work to implement th
+So, let's get into it!
diff --git a/exercises/03.use-effect/01.problem.callback/README.mdx b/exercises/03.use-effect/01.problem.callback/README.mdx
index 447a95f..ea2cc2c 100644
--- a/exercises/03.use-effect/01.problem.callback/README.mdx
+++ b/exercises/03.use-effect/01.problem.callback/README.mdx
@@ -1 +1,25 @@
# Callback
+
+🧝♂️ I've added a `useEffect`, but it's not supported yet so the app's busted:
+
+```tsx
+useEffect(() => {
+ console.log('consider yourself effective!')
+})
+```
+
+You can check my work if you'd like. Can you fix
+it? Thanks!
+
+👨💼 Sure thing Kellie, thanks!
+
+Ok, so what we need to do here is going to feel a little familiar. We'll want to
+create an `effects` array that stores all the callbacks. Then our `useEffect`
+hook implementation will actually be pretty darn simple: get the `ID` for our
+hook, add the callback to the `effects` array. We don't even have to return
+anything.
+
+The tricky bit will be to make the `appRoot.render` call synchronous with
+`flushSync` so we can iterate through all the effects to call the callback.
+
+I think you can do it. Let's go!
diff --git a/exercises/03.use-effect/01.solution.callback/README.mdx b/exercises/03.use-effect/01.solution.callback/README.mdx
index 447a95f..ca2d628 100644
--- a/exercises/03.use-effect/01.solution.callback/README.mdx
+++ b/exercises/03.use-effect/01.solution.callback/README.mdx
@@ -1 +1,3 @@
# Callback
+
+👨💼 Great job! Now, can you handle the dependency array?
diff --git a/exercises/03.use-effect/02.problem.dependencies/README.mdx b/exercises/03.use-effect/02.problem.dependencies/README.mdx
index 3c3f15c..f558db8 100644
--- a/exercises/03.use-effect/02.problem.dependencies/README.mdx
+++ b/exercises/03.use-effect/02.problem.dependencies/README.mdx
@@ -1 +1,24 @@
# Dependencies
+
+🧝♂️ I've updated the `useEffect`:
+
+```tsx
+useEffect(() => {
+ if (enabled) {
+ console.log('consider yourself effective!')
+ } else {
+ console.log('consider yourself ineffective!')
+ }
+}, [enabled])
+```
+
+You can check my work if you'd like. The app's not
+technically broken, but the logs should only happen when toggling enabled and
+right now we're getting logs when clicking the counter as well.
+
+👨💼 We can handle this! So you'll need to also keep track of the deps array and
+even the previous value of the deps array. Then just add a little logic to
+determine whether to call the effect callback based on whether any of the
+dependencies changed.
+
+You can do this. Let's go!
diff --git a/exercises/03.use-effect/02.solution.dependencies/README.mdx b/exercises/03.use-effect/02.solution.dependencies/README.mdx
index 3c3f15c..48138e5 100644
--- a/exercises/03.use-effect/02.solution.dependencies/README.mdx
+++ b/exercises/03.use-effect/02.solution.dependencies/README.mdx
@@ -1 +1,3 @@
# Dependencies
+
+👨💼 Great work! Now the `useEffect` dependencies work. Well done 👏
diff --git a/exercises/03.use-effect/FINISHED.mdx b/exercises/03.use-effect/FINISHED.mdx
index 412c328..aaa17be 100644
--- a/exercises/03.use-effect/FINISHED.mdx
+++ b/exercises/03.use-effect/FINISHED.mdx
@@ -1 +1,8 @@
# useEffect
+
+👨💼 That's as far as we're going to take `useEffect`. Unfortunately there's just
+not a good way to handle the cleanup function since we don't have a way to track
+when a component gets added and removed from the page because the API React
+offers us for that is `useEffect` 😅
+
+But hopefully you learned something valuable here! Write down what you learned!
diff --git a/exercises/03.use-effect/README.mdx b/exercises/03.use-effect/README.mdx
index 412c328..db3db6a 100644
--- a/exercises/03.use-effect/README.mdx
+++ b/exercises/03.use-effect/README.mdx
@@ -1 +1,23 @@
# useEffect
+
+The `useEffect` hook has a simple API:
+
+```tsx
+useEffect(callback, [dep1, dep2])
+```
+
+The dependencies are optional, the callback can return a cleanup function. On
+re-renders that change the dependencies, the callback will be called again (
+after first calling the previous cleanup if one was given). If no dependency
+array is provided, the callback will be called on every render. That's about it.
+
+We can follow the same pattern with storing the callback and dependencies as we
+did with `useState` before. And we can call the callbacks in the `render`
+function we have. Should be pretty simple!
+
+However, because we're not React, we don't actually know when the component has
+finished rendering. So we're going to use React's
+[`flushSync`](https://react.dev/reference/react-dom/flushSync) API to force the
+render to happen synchronously so that we can get the callbacks to run.
+
+So let's get into it!
diff --git a/exercises/FINISHED.mdx b/exercises/FINISHED.mdx
index 076a863..a512a43 100644
--- a/exercises/FINISHED.mdx
+++ b/exercises/FINISHED.mdx
@@ -1,3 +1,13 @@
# Build React Hooks 🪝
Hooray! You're all done! 👏👏
+
+Of course there's much more we can do for our implementations to make them more
+like the actual built in version of these hooks, but I think we've gone far
+enough for you to understand how hooks work behind the scenes a bit.
+
+If you want to explore the actual implementation of hooks in the source code,
+[start here](https://github.com/facebook/react/blob/e02baf6c92833a0d45a77fb2e741676f393c24f7/packages/react-reconciler/src/ReactFiberHooks.js#L3837-L3964).
+It's pretty interesting (and certainly more complicated), but it's not entirely
+dissimilar to what we've implemented. Hopefully this helps you understand how
+React hooks work under the hood!
diff --git a/exercises/README.mdx b/exercises/README.mdx
index ea8f544..1e8df43 100644
--- a/exercises/README.mdx
+++ b/exercises/README.mdx
@@ -1,5 +1,18 @@
# Build React Hooks 🪝
+👨💼 Hello, my name is Peter the Product Manager. I'm here to help you get
+oriented and to give you your assignments for the workshop!
+
+We're going to build our own implementation of React hooks so you get a deeper
+understanding of how they work behind the scenes. We'll be building `useState`
+and `useEffect`.
+
+
+ This will of course not be as rigerous as the official implementation.
+
+
+You're gonna rock with this! Let's get going!
+
🦺 One note, we're going to be doing some fun hackery around here so we'll be
abusing TypeScript a bit. Feel free to throw around `any` and
`// @ts-expect-error` here and there.