So right now we have the ability to load workflows from our database and we also have the ability to create new workflows. The problem is every time we create a workflow or try to access an existing workflow, we are greeted with a 404 page. That is because this URL right here, workflows and then ID, doesn't exist in our file explorer. So we ought to create inside of the app folder, dashboard route group, that exact URL path, a workflows folder, and then a dynamic URL folder, which will accept any workflow ID. Let's create a prompt for that.
Create an individual workflow route at dashboard route group workflows and then ID in square parentheses indicating that this is a dynamic part of the URL with four files. The first file is page. Page will be responsible for displaying the dynamic ID part from the URL. We are not going to implement any fetching logic and it's a good idea to write that explicitly so it doesn't try to do that ahead of time. We're going to develop a loading file which will simply use the spinner component from chat CNUI.
And then we're going to use error and not found and we are going to utilize the empty TSX composition from chat CNUI. And we can even tell it reference existing page from the dashboard to see how we did empty composition so far. Because this page right here is something that we are already familiar with. If you go back to the root page here, there we go. This is that empty composition.
So let's use that to create the error loading and not found elements as well. So I'm going to go ahead and execute this prompt. There we go. Four files created within Workflows ID folder. A page file, which is an asynchronous server component that awaits the params and renders the ID, no fetching.
Loading is just a centered spinner. Error is a client component because that's required for error boundaries, that's a Next.js rule, and it uses the empty composition with a reset button wired. We also have a not found which also uses the empty composition with a link back to the workflows. Brilliant. Let's take a look at these changes.
So I'm going to close this. First we have a page file. It's located inside of app folder dashboard workflows ID. So all it does is it extracts the ID from the params. Params need to be awaited.
That is very important. That's why we have this right here. So a lot of training data don't include the newest version of Next.js in which you actually have to await the params. So what they usually do is they define params like this and then they just do this. This will technically work but it's also going to throw an error in the terminal.
So make sure that your agent has created params as a promise and it's actually awaiting it. So that's all I want from the page. Make sure it's an asynchronous function so that it can await and that's it. I just want to see the ID that I have clicked on. In the not found, what I'm expecting is something like this, just a random empty composition, workflow not found.
In here we have some errors because this can be escaped. Sure, Yeah, we can do that. And for example, this is an interesting thing that appears to be happening often. So I'm gonna go ahead and I will tell it to do the following. This is a good exercise for us.
So in not found.tsx, you've used apostrophes, however you pronounce that, which cause the following error. And I'm going to paste the error and then I'm going to tell it fix this and also add a new agents dot md rule to avoid doing this in the future. So this is how you update the agents.md. When you see something that's kind of annoying and the agent appears to be doing it over and over again, You can add that to the agents.md and then it's going to stop doing that. There we go.
So I have this updated in my agents.md file. JSX text escaping, escape apostrophes and quotes in JSX text content. And it's basically telling it how to avoid that error. And my not found now has proper apostrophes set here. Perfect.
And we also have a very simple loading, which includes a spinner and a not found. Great. So let's go ahead and try creating a new workflow now and what should happen is this. This time we shouldn't be getting an error but instead we should be getting the exact ID that you see in the URL. To test the error page, You can go inside of this new page.tsx and literally just go ahead and throw an error test error like this and then go ahead and reset this page and there we go.
This is how the error page is going to look like. And if you want to see the not found, you can go ahead and import not found from next navigation and save the file. And then go ahead and refresh again. There we go. Workflow not found.
The workflow you're looking for doesn't exist or may have been deleted and clicking on go back leads back to localhost 3000. Perfect. So now let's go ahead and enable clicking on the items in this list and keeping them active when you're actually in one of the workflows and make sure to remove the not found which we added here. So the component which we have to modify to enable the sidebar from being interactive and showing us which is the currently active workflow is workflow nav component. This is where we have to add that logic.
We can achieve that with this prompt. So in the workflow nav component, make each workflow in the list link to its own page and highlight the one that is currently Open. Wrap each workflow's sidebar menu button in a Next.js link using as-child prop so that link becomes the button component, and make sure that it points to workflows and then workflow ID. Use the usePathName hook from Next.js navigation to detect the active workflow and pass is active to that button so it shows as selected. Apply this both in the collapsed popover list and the expanded sidebar list since both render the same workflow items.
Let's go ahead and execute this prompt. And that should produce results like this. The workflow nav component should now have a link import, use path name import, it should use the use path name hook to get the path name value and then instead of the workflow nav component here each sidebar menu button should have an as child prop, is active prop which is calculated by comparing the path name to a generated URL which we expect with workflow ID injected and then a link wrapping the span which renders the workflow name with an href workflows workflow ID. And if we go ahead and test that out, there we go. We can now navigate between our existing workflows.
This seems like a pretty good place for a checkpoint so let's go ahead and commit our changes and then git push. What we have to develop next is the workflow shell which should look something like this. A very big center panel where all of our nodes and the canvas in general is going to be. Beneath it, we should have a logs panel where we are going to display each of the nodes status happening in real time. And then we're going to have a right sidebar which will serve both as the toolbar to add new nodes and as the inspector for individual selected node and it's also going to have some functions like run or delete this workflow.
The prompt to develop this is going to be a little bit bigger than usual. So what I've prepared for you is the exact file which you can just download or copy or paste because I don't expect you to pause the screen and copy the whole thing. So whenever we have these longer prompts, which are mostly related to UI changes, I'm going to add them in the specifications folder right here. So make sure you are in the main branch or simply select the branch of this chapter. Go inside of specifications, find the workflow shell and then simply add it to your specifications right here.
And these are the instructions which we are going to give. Create a workflow shell component in features workflows components folder that takes a workflow ID and is the layout shell for the workflow editor. Then render it from the workflow page.tsx located inside of the dashboard route group inside of workflows id page.tsx so that is currently this right here which right now just renders the id then we are going to say build all of this in one file using resizable components from ShadCN UI, meaning components UI resizable. And use rem values for every size. That is because it's training data will probably tell it to use percentages but they don't look as good when you actually do it that way, especially when zooming in and zooming out.
So using RM values is actually much better. And then what we do is we basically describe exactly how this canvas is supposed to look like. The layout is a horizontal resizable panel group that fills the space size full with two panels and a handle between them. So we have the left panel, which is essentially this right here. That is the primary column with this specific min size.
Inside is a vertical resizable panel group split into two panels with a handle between them. The top panel has a minimum size of 18 rem for the canvas placeholder. The bottom panel has a default size of 8 rem and minimum size 6 rem for the logs placeholder. So that is this panel right here. And then we have the right panel, which is the inspector with default size 16 rem, minimum size 14 rem and max size 36 rem.
So Antonio, where do you get these values from? I just tweaked them until they looked good. That's why I'm giving you the prompt to implement this because it isn't really educational. It's just tweaking the values until they look and feel good. And I also instructed to put a simple label in each panel as placeholder content so we can identify which one is the canvas, which one is the logs and which one is the inspector.
No subcomponents and no data fetching yet. So purely presentational, we just want to get a skeleton of this layout. Let's go ahead and simply run implement specifications workflow shell md and the result should look something like this. A main canvas panel beneath it a logs panel and on the right side the inspector panel. And these should be resizable to their minimum and maximum values which we have defined.
Beautiful exactly as we imagined it from the picture. I purposely didn't append this picture because then it would notice all of the cursors and it would notice all of these icons and some agents can go crazy and just try to implement all of that. All I wanted was a simple shell which is exactly what this prompt implemented. Let's take a look at the changes together. So the page has been modified to no longer just render the ID, but instead to render the workflow shell and the workflow ID prop.
We implemented the workflow shell inside of features workflows components workflow shell as instructed right now we don't use the workflow id prop for anything but we will later on and in here we simply make use of components UI resizable component and this is the result. There we go. Pretty clean implementation. Brilliant. So that is exactly what we wanted to achieve and that is the perfect end for this chapter.
So once again let's make sure we create a checkpoint, git commit and git push.