In this video, we're going to do a comprehensive Codex tutorial. I want to show you not just what
Codex is, but how to actually use it as a serious app building agent. We'll start with the foundations,
how Codex works, how the Mac app and the CLI fit together, how to choose models and thinking modes,
how threads and context work, and how to use tools like the browser, terminal files, and external
systems. Then we'll turn that foundation into a real workflow. We'll use Codex to plan, architect,
design, implement, debug, and ultimately deploy a production-ready app from scratch. By the end,
you should understand the full Codex workflow well enough to take your app idea, break it into
manageable steps, and use Codex to build it with much more confidence. Now, when you Google for
Codex, you're going to land on this website here. And here you can learn more about Codex and you can
also download the app. Now, as you can see, it says here, download for macOS. That is because I have
macOS. If you're running Windows, you're going to have a button that says download for Windows. So
it does support macOS and Windows. And when you scroll down, you can see the main screenshot
that kind of gives you a general overview,
general idea of what this app looks like, okay?
And you can kind of scroll down,
you can learn more about it,
or we can jump into my Codex instance here
and I can give you a quick overview.
So on the left-hand side,
we have things like starting a new chat,
search, various plugins, automations.
Just below that, we have our main organization, right?
And this is where you can organize your projects.
Okay.
And the idea here is that anytime you have a project, you want to click here and you want to actually either start it from scratch or you use an existing folder because these are not organized just logically.
They're actually linked to folders on your disk.
Okay.
And so everything that you see here represents actual folders.
Now, inside of these folders, we have some items here.
Now, these are not files, and they do not represent anything on the disk.
These are actually conversations, right?
And you can think of them as, you know, similar to what you may have in chat GPT, okay?
So if you're working on this project, you can create a new conversation simply by, you know,
clicking here or pressing Command and telling it what you want to happen.
Now, in the center pane over here, this is where you're going to be communicating, right?
So if we scroll back up, this was my initial prompt here.
I want to build a very, very simple web app that arranges items as a Trello Kanban board
style, et cetera.
And then I have this interaction here, right?
It does something.
I ask it to do something else, et cetera, et cetera.
Now, just below that is where you're going to be entering your prompt, okay?
So you're going to be selecting the model, the different reasoning, and we're going to be covering all that.
But this is the main text box for the model.
Now, on the right-hand side, there's a lot of interesting things happening here that a lot of people are not really aware of.
And a lot of people are not really using it.
And you need to understand to leverage this whole app experience.
right? So right here, we have this little card that displays a little bit of information about
this specific conversation, right? So we have branch details, we have some artifacts, right?
And these are the data that happened as a result of this convo. And so if I go to another
conversation, we might have different artifacts, right? And you can think of an artifact as a
side effect of your conversation.
So if you've created the readme file, you're going to see it here.
If you did a web search, you're going to see it here.
Now, one of the more interesting things happens when you click this button and open the right
hand pane.
And here you can see all kinds of interesting things.
So for instance, if I click this button, I can have a side chat or I can have a browser.
Now, the browser feature is actually very, very powerful because I can simply open this up here.
And as I'm developing this app, it's going to give me a URL that I can open here in this browser.
And that will allow me quick iteration because I'll be able to see exactly how the app looks as I'm developing it.
And we're going to be doing all of that in more detail a little bit later in this tutorial.
First, let's talk about Codex.
The easiest way to understand Codex is that it starts from the same basic idea as ChatGPT,
but it is connected to your actual working environment.
So instead of only answering questions, it can inspect files, edit code, run commands,
use the browser, test the app, and help move a project forward.
The difference matters a lot.
ChatGPT is great when I want an explanation, a rewrite, a brainstorm, or a quick answer.
Codex is what I use when I want work to happen inside a real project.
It can do many of the same reasoning tasks as ChatGPT, but it can also act on the project directly.
That is why I keep ChatGPT mostly for pure informational questions,
and I keep codecs for work threads so my project context stays focused and clean.
There are two main ways to use codecs.
The first is through the CLI, which is best when you already live in the terminal
and want to run quick repo tasks, scripts, lightweight edits, or developer-style iterations.
The second is the Mac app, which is usually better for visual app building work.
If I want to see the browser preview, inspect file changes, manage a longer project, approve permissions, review artifacts, or teach the workflow on screen, the Mac app gives me a much clearer workspace.
And that is why I highly prefer to use the Mac app, and that is what I recommend you use as well.
Inside the Mac app, the main pieces to understand are the project or the workspace, the thread area, the model selector, the thinking mode selector, file changes, terminal output, browser preview, artifacts, permissions, and the review flow.
Once those pieces make sense, Codex stops feeling like a chat box and starts feeling like an app-building environment.
The project pane is where you open or switch between projects.
The thread area is where the conversation and task history live.
The file change view shows what Codex wants to edit before those changes are accepted.
The terminal output shows commands, builds, errors, and verification steps.
The browser preview is where you can inspect the running app visually.
Together, these pieces make Codex feel less like a chatbot
and more like a working development environment.
Permission flow is also important.
Codex should never feel like a black box that silently changes everything.
everything. As soon as it finishes running commands, editing files, or taking an action
that matters, you can always inspect what it's doing, approve the right actions, and
keep control over the project.
The next thing to understand is that Codex is not just one fixed experience.
There are a few workflow decisions you make each time you use it, and the first one is which model to use.
use. In practice, I usually default to the latest strongest model unless I have a clear reason not to,
because most app building tasks benefit from better reasoning. Here's a rough guide to picking
the correct model for your specific task. So for architecture, backend design, multi-step
implementation, difficult debugging, or final review passes, I want a stronger model, such as
GPT 5.5. For small copy tweaks, simple UI polish, short refactors, or low-risk tasks, a faster,
a lighter model can be a better tool. And here's where you can use an older model, or a mini or a
nano version of the current latest model. For example, if I'm asking Codex to rename a button,
tighten some copy, or adjust spacing on one component, I do not need to overthink the model
choice. But if I'm asking Codex to design the convex schema, think through permissions,
restructure several files, or debug a problem that spans front-end and back-end code,
That is where I want the strongest model available.
The more expensive the mistake, the more I want to slow down and use the better reasoning setup.
The next important decision is the reasoning mode.
This controls how much time and effort Codex spends thinking through the task before and during the work.
This decision is a little more nuanced than model choice because every reasoning mode has a place.
Low thinking is useful for quick, obvious tasks where the risk is small.
Medium is good for normal app building work, first pass UI implementation,
straightforward debugging, and routine feature work.
High is what I use when the decision is more expensive.
architecture, convex, data model design, authentication, permissions, hard bugs,
multi-file changes, and the final review. My default for serious app building work
is usually a strong model with high thinking because that gives me the best balance between
speed and quality. But the practical lesson is simple. Match the model and thinking mode
to the risk of the decision. If the task is small and reversible, keep it fast. If the task affects
the structure of the app, slow the model down and let it reason. Now, as you're working on your
project and you're in this conversation view, you can enter your prompts here and just below
you can select various things. Now, first of all, you have your context window here, right? Here,
you can see how much of the context you have used. Now, Kodak says that it automatically compacts
its context. And yeah, you can do that, but over time, it's not going to be as effective. And so
you always want to be starting new conversations anytime you're working on something new that
requires a context switch. Next, we have here the all-important model selector. So if I click over
here, I have it automatically set to GPT 5.5, which is the newest model as of the time of recording
this video. You can also switch it to some of the older models as well, but I see no reason to do
that because this model has been very, very capable. We also have things like speed, standard versus fast,
Fast is one and a half times faster, but it also uses more of your usage.
Okay, so depending on which plan you're at, you may want to stay on standard.
I mostly keep it on standard unless, you know, I'm in a hurry and I want to switch it on fast.
Next, we have intelligence, right?
Now, this is very, very important.
By default, I keep this on high.
I found that to be a good balance between speed and quality, because as you go towards lower
intelligence, the model is going to be faster, but you're going to be giving up quality, right?
You're going to be giving up intelligence. On the other hand, as you go into higher and higher
intelligence, the model is going to be slower, but it's going to be thinking more, right? It's
kind of like a person, right? You can ask a person a question and that person may think more,
think through something longer, right? You know how people say, let me sleep on it,
or let me think it over, right? The longer you think, the more you figure something out,
and the higher chance you're going to arrive at the correct answer, at least for you. You're
going to think through all the possibilities. Whereas the first answer might be wrong and
usually is because you haven't thought everything through. And it's the exact same thing here,
right? If you set something too low and you're working through something fairly complex,
well, the model is not going to think it through. It's going to give you an answer that, well,
it's an answer, but it might not be the ideal answer. Okay. On the other hand, with extra high,
you know, the model is going to think longer, but it may not be necessary in a lot of situations.
And so I typically keep it on high, sometimes medium, very rarely low, and also very rarely
extra high, unless I'm working through something that the model has trouble with high. You know,
the situations where extra high really proven itself over high, it hasn't been that many. And
And so for the most part, I keep it on high, sometimes I also switch it back to medium.
And as you start to use Codex more and more, and as you begin building more and more apps
with it, you'll be able to better judge which thinking mode to select.
Now, before we go deeper into the workflow, I want to quickly talk about pricing and plans,
because this is one of the first practical questions people have with Codex.
For most people learning codex, the important question is not what is the most expensive
plan.
The question is what do I actually need for the kind of work I'm doing.
If you're learning, testing prompts, and building smaller projects, you can usually
start with the normal ChatGPT plan access available to you.
If you're doing heavier app builds, longer agent runs, team workflows, or professional
coding work, then plan limits, credits, and business options start to matter more.
Now, here I am on OpenAI's Codex pricing page.
And if you scroll down, you can see the prices that are available at the time of filming this video, right?
So we have the free plan, and this allows you to explore Codex capabilities and quick coding tasks.
We have the go plan, which is $8 a month, and you can use Codex for lightweight coding tasks.
We have the plus plan, which is fairly popular, $20 a month.
And here you can finally start to actually do something meaningful, right?
Something like, you know, building...
Something like, you know, building a part of an app or building some scripts.
And they say this can power a few focused coding sessions each week.
Next, we have the Pro plan, right?
And so here you can choose whether you want the 5X or the 20X higher rate limits than plus.
And this is $100 a month.
I'm actually using the ProPlan 20X.
Okay, so I'm paying 200 bucks a month.
And at this level, I am at a point where I pretty much never reach any limits.
And that means I can build, you know, multiple projects at once and use codecs for all kinds
of tasks and still not reach limits.
And so during the time when I'm, you know, building heavy apps and doing some serious work, I may get close, right?
But I never really get to the limit.
You need to decide which plan is right for you.
Now, from what I understand, Plus Plan is very, very popular.
And so what I would do is I would obviously, you know, try the free plan, try to see how that goes.
And, you know, obviously, you know, if you do anything serious or remotely serious, you're probably, you know, you're going to run out of this plan.
And so the next logical step is to try out the plus plan.
The plus plan is where a lot of people start.
And it gives you a reference point as to, you know, the amount of work that you're doing.
How much can this plan actually cover the amount of work you're doing?
Because the fact of the matter is there are people that work on very heavy projects.
And, you know, they work on big repos, right?
Lots and lots of code base.
They run out of their plan very, very quickly.
But if you're working on the smaller projects, you're not using the fast mode.
So for instance, you're not coming here and you're changing, you're not changing speed
because I'm using the fast mode from time to time.
And that, you know, increases the usage as well.
So if you're on standard and you're using maybe medium often, right?
You're not really using high that much and you're almost never using extra high.
You can get a lot of mileage out of this plus plan.
And when this plus plan starts to run out, you know, you're starting to notice some tight limits,
you may want to switch to a higher plan, okay, such as the Pro, 5X, or 20X. Now, you can also
ask Codex to help you choose the right Codex plan for your specific use case. For instance,
you can use this prompt here, help me choose the right Codex plan for my use case, okay,
use only current official OpenAI pricing and help center information. And I'm going to go ahead and
run this and see what it says. Right. And this is what we got back. As of this day,
ChatGPT plans that include codecs. Okay. So this is the practical read. Free, try codecs on quick
tasks, go lightweight coding tasks, plus a few focused coding sessions each week. Okay. And this
is exactly what I just told you from that official page. And so if you scroll down, you can see how
codecs usage and credits work. You can learn, you can read this. Best fit for your use case. Okay.
for learning codex and building small to medium apps, chat GPT plus is the sensible default. If
your current plan is plus, I would not upgrade until you actually hit codex limits often enough
that the friction matters. Okay, when heavier or business plans make sense, what to verify live
before deciding. And so a sensible thing to do would be to try codex plus and see if that's
enough for your specific use case. If you're not a heavy codex user, if you just want to experiment,
it should be more than enough. And then you can decide whether you want to upgrade to the higher
tier plans. Now, before we move into the app building workflow, I want to take a moment to
talk about some of the things Codex does that can greatly increase your productivity. These are
features I use all the time across different projects. Skills, plugins, automations, and MCP,
along with its tools and connectors. The best way to think about all that is skills tell Codex how
to do a workflow, plugins package capabilities, automations let work happen later, and MCP tools
and connectors give Codex controlled access to outside systems. Once those pieces make sense,
Codex feels less like a code editor and more like a project agent.
First, let's talk about one of my favorite features that I use pretty much all the time – skills.
Skills are reusable instructions for how Codex should do a workflow.
They're not external tools by themselves.
They're more like local playbooks that tell Codex the style, process, output format,
format and validation steps for a specific kind of work.
For example, this course uses skills for explainers, notion editing, video timelines, and other
repeatable production tasks.
Instead of explaining the same rules every time, I can point Codex to the skill and it
knows the house style, the workflow, and the mistakes to avoid.
The rule is simple. Anything that gets used over and over again becomes a skill. That matters
because a lot of real work is not just about getting an answer. It's about getting an answer
in the right format, following the right process, and producing something consistent with the rest
of the project. All right, so here I am in my Codex instance here, and I want to show you some
things that you can do with skills. So I have here a conversation for an app that I was building.
And if I press the forward slash, you can see that I have many options here, right?
I can do many, many things.
And as you can see for skills, I have lots and lots of skills.
I have tons and tons of skills over there.
And skills allow me to package a repeatable process.
You can think of it as a function that does something.
It gets some input and it produces an output.
And the goal is to produce consistent output as you've done before.
And so as an example, let's say if I'm working in this convoy here, right?
And I asked the model to do something for me.
So here I have, I want to build a very simple web app
that arranges items as a Trello Kanban board style.
Okay. And it comes up with this.
Now, right here, I can package that as a skill.
Now, what do I want to package as a skill?
Well, I want to package, for instance, maybe creating the architecture.
So I can say something like package the architecture step
as a skill, and then I just give it a name of the skill, sample art stack, okay? And that's going to
create a repeatable skill that will allow me to generate an architecture for any kind of project
that I may be working in the future. I'm going to go ahead and jump into the plan mode in case the
model wants to confirm something or clarify something, and I'm going to go ahead and execute
this and let's see what happens now it came back to me and it wants me to answer a question
should the sample arch stack package this as a general architecture planning skill or specifically
as the kanban trello architecture right so we want it to be general app architecture so i'm
going to go ahead and save this and now it came back with a plan okay create the reusable codex
skill named samplearchstack under wherever it's storing those skills, the skill will guide codecs
through the architecture step for simple app ideas. And it's going to package that step into
a reusable process. All right. And now it tells me that I created the skill at it contains skill.md
and then agents forward slash openai.yaml. Validation passed, et cetera, et cetera. And now
would I
And now what I can do is I can enter a prompt and I can say use this skill for a brand new
project management app. And it should use this skill to create an architecture stack
for this kind of app. So it wants to know for the brand new project management app,
what should the version one data model support? We're just going to do local only. And here it
came back with a plan. Brand new local only project management app architecture, right?
That's the purpose of the skill. Okay. We're going to expand this and it's coming up with
this architecture, right? App shape, data state model, component architecture, test plan, et cetera,
etc. And we can say yes, and it's going to go ahead and implement all that. And so this is
actually a fairly valuable skill, because that is exactly what you want to be doing in those
initial stages when you're building an app, as you're going to see a little bit later.
But by having the skill, we do not need to explain all of that over and over again. So as you're
building more and more apps, you can simply reuse this skill from now on. Now, before moving further,
I also want to explain a few terms that can sound similar at first, plugins, automations,
and MCP. They all expand what Codex can do, but they are not the same thing. Plugins are
package capabilities or workflows that make Codex better at a specific kind of work. For example,
a Notion plugin can help Codex read and update Notion pages. A Vercel plugin can help with
deploys on project settings, a Hyperframes plugin can help create explainers, and browser
or document tools can help Codex inspect apps or work with files.
The simple way to think about plugins is this.
They give Codex a more specialized tool set for a specific job.
Codex still needs the right context and the right instruction, but the plugin gives it
a cleaner way to operate inside that workflow. Automations are different. A plugin gives Codex
a capability, but an automation gives Codex a time-based job or follow-up behavior. That might
be a reminder, a recurring check, a scheduled review, or a request to come back to a thread
later and continue the work. This is useful because not every task needs to happen immediately.
Sometimes you may want Codex to check something again tomorrow, remind you to review an outline,
monitor whether a deployment is still working, or wake this thread back up when you need it to
continue. Automations turn Codex from a one-time assistant into something that can help manage
longer running work. The important distinction is simple. Plugins are about what Codex can do,
and automations are about when Codex should do it. All right, so here I am back in Codex,
and I want to show you how plugins work, right? So if you click over here on plugins,
you can see all the plugins that you have here, okay?
And so it tells you that make Codex work your way.
And if you scroll down,
you can see all the different plugins, right?
So you can click on the plugin
and you can learn more about it, right?
So for instance, this spreadsheets
allows you to create and edit spreadsheet files, right?
You can use this plugin to create a spreadsheet
to analyze this company's financial, et cetera, et cetera,
right?
Create, edit, inspect, render, verify, and export
Excel, SX, CSV, and TSV spreadsheets locally. Use spreadsheets when the durable output or target is
a spreadsheet, workbook, etc., etc. So this includes the skill, right? So you can think of package
as kind of an umbrella that includes a skill, but it also gives codecs an ability to connect
to external systems, right? It's kind of this higher level structure, okay? Whereas the skill
is a very, very specific thing.
It's a specific piece of instruction,
essentially a specific prompt.
A plugin is this umbrella that contains a skill, right?
So you can have that.
One plugin that I use all the time is Notion.
So if we click over here,
you can see that this actually includes
a lot more interesting things, right?
Notion workflows for specs, research, meetings,
and knowledge capture, right?
So you can specify this,
and then you can give it a prompt.
And if you scroll down, you can see that it includes the Notion app, the knowledge capture.
These are skills.
This is an app.
Okay, so this allows it to connect to an external system, right?
So if I click over here, I can manage this in ChatGPT as well because it's an external app.
And this right here, these are skills, right?
I can open that, and that's going to open this skill right here, right?
This is how the skill is actually stored.
And I can also turn it off or turn it on, depending on if I want that skill enabled or not.
Now, this is a plugin that I use all the time, right?
I use Notion for my planning, for, you know, writing stuff, scheduling, stuff like that.
It's the brain of my workflow, essentially.
And then I installed this pre-built Notion plugin.
And the first time I ran it, it authenticated against my Notion workspace, right?
connected to my Notion account. And from then on, I can simply say, hey, use this Notion spec to do
this or to do that, or edit this document, edit that document. And it's able to go out and edit
the right documents and essentially make Notion an extension of codecs. That's kind of the purpose
of a skill, to make something an extension of codecs. And that's the main idea with all of this.
Another really cool one is, for instance, Google Calendar is another one.
Instead of connecting to Notion, or in addition to connecting to Notion,
you can also connect to Google Calendar.
I personally do not use Google Calendar.
I use Notion, so I do not have this skill set up.
Another really useful skill that you're definitely going to be using
if you're building apps is Vercel.
Vercel or maybe something like Netlify for deploying your apps.
right? I use Vercel when demoing apps. And by having this package installed, it can figure out
how to deploy, how to check deployment, how to do everything without me needing to actually
understand how all of that works, without me needing to go to Vercel and read their docs and
understand how to deploy and all of that. I simply install this skill and then I click here and now
can say you know vercel ordered this repo for vercel deployment risk or vercel which vercel
tools will fit this app at best or vercel deployed this app right and if you scroll down you can see
that this has this app and then it has all of these skills all of these different skills look
at this it has a son a ton of skills vercel cli vercel agent all of these and obviously these
skills are not just for deploying, because we also have payments, we have best practices,
we have all of these other ones. These skills essentially map to different parts of our cell,
to different features of our cell. We're not just talking about deploying your app,
because this could be just a skill, deployment. This could be one skill that I may need. I may
not need all of these other skills, but why not?
out which skill it needs to consult, you know, according to the prompt that I give it. So it
doesn't, you know, it's not a big deal to have all of these enabled if I'm using Vercel. And like I
this allows me to basically bring Vercel into my Codex workflow. That's the beauty of these plugins.
And that's the same idea with all of these plugins. You're essentially bringing an external
system and letting Codex manage it for you. Now, automations work very, very differently.
So if you click on automations here, you can see that automations, they allow you to automate work
by setting up scheduled chats.
Okay, and you can learn more here.
Now, if you click on any of these automations,
you can see exactly how they're going to be working.
So if I click on something like
summarize yesterday's Git activity for standup,
you can see that it wants to create an automation for me.
Okay, and what exactly is it trying to do?
Well, it's essentially trying to create a conversation
that will be repeatable.
Okay, so it creates this automation.
This is the name of the automation.
right? This is the prompt. This right here is the prompt. And the prompt is summarize yesterday's
Git activity for standup, grounding rules, et cetera, et cetera. We can select a work tree.
We can select a project here. And then we can select the time where it's going to run over and
over again, right? So with this kind of automation, you may want to run it on weekdays at 9 a.m.
but you can also select it, make it hourly, daily, weekly, etc., etc. And you can also change the time,
obviously. Now, here you can change the model, and here you can change the reasoning level. Now,
with this kind of automation, you don't really need a high reasoning. Medium is going to be just
fine. And after you're done, you can simply click create, and now you're going to have an automation
that will run every weekday at 9 a.m. running this prompt.
And remember, this is a special prompt.
Here, you're asking it to consult Git activity.
And so the idea is you may have Git connected via a plugin or something else,
and it's going to connect to your Git environment
and then figure something out for you.
And that's going to run every weekday at 9 a.m., right?
So instead of you needing to jump into Codex first thing weekday morning and execute this
prompt manually, you can create an automation to do just that.
If you scroll down, you can see some other automations here.
You have incidents, you have code quality, right?
Maybe you want to run a code quality check every 24 hours.
Well, you can click here daily at 9 a.m., right?
scan recent commits since the last run or last 24 hours for likely bugs and propose minimal fixes.
That's another very, very useful automation. Repo maintenance. You have here growth and
exploration. Click here. From recent PRs and reviews suggest next skills to deepen. This is
great, right? So automations, they could be used for pretty much anything, right? And they are,
you know, it doesn't really matter what kind of niche you're in. You don't need to be in software
development or project management or anything like that. You can be a writer, right? You want
a status. You're writing maybe a thousand words every day. You know, you can have an automation
that checks for spelling, grammar errors that you may have done, and then it may suggest some fixes
this. And also another automation that gives you more ideas, you know, to break through writer's
block. And that can run every morning at 9 or 10 a.m. Okay. And so automations are very, very useful
if you need some kind of a repeatable structure in your workflow. And I want to talk a little bit
about MCP. So MCP or model context protocol is very, very important. Okay. So if you press
command comma or you go into settings over here, you're going to be on this screen. And if you
choose MCP servers, you're going to see all your MCP servers that you have here configured. And you
can also see whether they're enabled or not. Now, an MCP server is basically a server. It's a remote
system that your codex instance can connect to. So as you can see, I have a bunch of MCP servers here
that do all kinds of interesting things.
For instance, I have here a Stitch MCP server configured.
I have here a Superbase MCP server.
I also have, you know, Flutter Flow Designer, Flowbase,
a bunch of apps that support MCP.
And when you connect to them,
Codex is acting like an MCP client.
So you have that same client-server paradigm.
Now, why would you want to use an MCP server
to connect to something like Superbase or something else?
Well, the reason is very simple.
You want Codex to do all the administration,
all the work for you, right?
So if you're building an app using something like Superbase,
and we're gonna touch upon that a little bit later
in the video, you can set up Superbase yourself.
You can configure all of that.
That takes time, but it's very, very doable.
or you can simply configure a Superbase MCP server in your Codex instance.
And that will allow Codex to use that MCP server to essentially manage this remote server,
this tool, this app for you.
And as you're going to see a little bit later in this tutorial,
this is very, very helpful to us because it saves a lot of time
and it enables things that we couldn't really do before.
because now Codex understands one piece, and via MCP, it can get more context and create a much
more robust app for you, or a tool for you, or anything else, a system, if you will, because now
it can connect to other remote systems and essentially consult that data with the data we
already have, such as the code or things it has been working on, and figure out a unified solution.
And this is extremely helpful to us, okay?
And so there's a couple of ways that you can add a server.
You can click here and you can fill all of this manually.
Or you can simply tell Codex, set up and activate a Superbase MCP server.
And it's going to figure out how to do that.
It's going to search for it.
It's going to figure out the specs.
And it's going to set it up for you.
And the same thing for all of these other ones.
Now, after setting up the MCP server, you can simply tell Codex to use it.
So I can say something like, use the Superbase MCP server to query data or check how many tables we have or pretty much anything else.
And it's going to go ahead and connect to your Superbase instance in this example via the configured MCP server.
server. Now that we have laid the foundation and before we start building the real app,
let's talk about the ideal codex workflow. What is the best way to approach it? Before we begin
building our app, you want to establish the workflow that you're going to use again and again.
The loop is simple. Inspect, plan, edit, verify, and report. That sounds basic, but it is the
difference between using Codex as a random code generator and using Codex as a controlled build
partner. The mistake a lot of people make is that they jump straight to build this app or fix this
problem without giving the agent a clean process. That can work for small tasks,
but it breaks down quickly on real projects. For a serious build, you want Codex to understand the
repo first, explain the plan, make a focus change, verify the result, and then report back in a way
that you can review. A good Codex prompt is not just a request, it is a small project brief.
The better the prompt is, the easier it is for Codex to understand the current state,
choose the right amount of work, and verify the result. The basic structure is simple.
Explain the goal, give the relevant context, define what should change, define what should not change,
and tell Codex how to verify the work. If the task is risky or unclear,
ask Codex to inspect first and make a plan before editing. For instance, instead of saying
build the app, I would say inspect the project first, do not edit yet, identify the existing
structure, propose the smallest first version, list the files you expect to touch, and explain
how you will verify. That gives Codex a much cleaner job. For implementation prompts, I want
the request to be specific enough that Codex can act, but not so over-specify that I accidentally
force the wrong solution. I usually describe the outcome I want, the constraints I care about,
and the checks that need to pass. Then Codex can use the actual project context to choose the
cleanest path. As part of this workflow, I want to introduce you to one of the most important Codex
features. Plan mode. Plan mode is a superpower that I use for 80 to 90% of my prompts. There are
two main benefits to using the plan mode. First, it's a form of brainstorming where the model
cannot change or alter your files. Second, it's a way for the model to clarify your requests
by asking follow-up questions. This is especially useful when the request is under specified.
If I say build the booking flow, there are a lot of hidden decisions inside that request.
What fields does the form need?
What status should the booking start with?
Where should the booking appear for the helper?
What should happen after submission?
Plan mode gives Codex a chance to surface those questions before it edits the app.
I also use plan mode as a quality filter.
If the plan is vague, too large, or misses something important, I know the implementation will probably be messy.
If the plan is specific, scope, and easy to verify, then the actual coding step becomes much safer.
So you want to use plan mode initially while brainstorming, and also as you enhance your app,
because it gives the model a chance to ask follow-up questions to ensure there's no misunderstanding.
Now, if you're working with an existing repo, the first step should always be to inspect.
Codex should understand the files, the app structure, the current state, and the goal before changing anything.
Then it should plan the work in a way that is small enough to review,
Only then, once Codex is fully in sync with your goals, should it make the actual edits
and write code.
Once the code is written, it should verify the code with the browser, terminal, using
tests or the build output.
And finally, it should report what changed and what still needs attention.
Verification is the part I want to emphasize.
A task is not finished just because Codex wrote code.
For UI work, I want to see the browser.
For backend work, I want to see the function call, the dashboard row, or the test results.
For deployment work, I want the live URL and a real smoke test.
That habit keeps the workflow grounded in evidence instead of trusting that the code
is probably fine.
Additionally, you always want to break big tasks into smaller ones.
Instead of asking Codex to build the whole marketplace as one prompt, you want to ask
it to plan the app, build the first UI shell, wire one initial database-backed version,
add the booking flow, add the helper dashboard, and so on.
Each step has a clear target and a clear way to check whether it worked.
A good Codex task should usually fit into one reviewable outcome.
Create the first static marketplace homepage is reviewable.
Wire service listings from Convex is reviewable.
Add booking creation and verify the booking row appears is reviewable.
Build the whole app is not reviewable because there are too many decisions happening at
once.
So the workflow is not just a technical process.
It is also a way to stay in control.
We let Codex do meaningful work, but we keep the work divided into chunks where we can
understand the change, approve the direction, and catch problems before they spread.
And so here I am back in Codex, and you can enable plan mode by pressing Shift-Tab, and
here you have plan mode.
Or you can click here and toggle this.
I typically just use Shift-Tab because it's a lot easier and it's a lot faster.
And then whenever I'm in plan mode, I can start brainstorming.
And not only that, it's useful because Codex will not make changes whenever it's in plan
mode.
And it also gives Codex to come back to you with follow-up, clarifying questions.
And I find that super, super helpful because we always want to make sure that Codex knows
exactly what it's doing.
The last thing that we want is for Codex to assume something.
We never wanted to assume anything.
We always want to make sure that we are on the same page.
And so let's say I have a convo here going and I want to build an architecture.
I want to build some kind of an intricate architecture.
And I want to make sure that we built out an architecture.
I may not know exactly how far I want to go, exactly all the details, but I want to make
sure that Codex is on the same page.
I can say something like, come up with an architecture that will allow me to create both web and mobile and desktop versions of the app.
Ensure it is fast and robust.
I'm here in plan mode, and typically with this kind of prompt, it's not clear what I want.
I don't even know what I want.
I want Codex to figure it out, but I want Codex to come back to me and confirm with me. And so,
if we execute this prompt, hopefully it's going to ask me some follow-up questions. Let's see.
And so as expected, Codex came back with a question, which cross-platform strategy should
the architecture optimize for? And there are two questions, okay? Do we want shared core native
shells? And you can click here and you can get a little detail. Use shared TypeScript domain logic
with separate Expo mobile, et cetera. Do we want a one universal app or do we want web-first
wrappers, right? Because I asked for a cross-platform product, but there's many ways of
doing it, and there's many trade-offs with each approach. And so it came back to me,
and it wants to clarify one universal app, this or that. So I'm going to say this one. I'm going to
go with recommended. And now it wants to know what should the app support for data and reliability.
offline first cloud sync cloud only real time or local only and you can click and you can hover
over the little i to get more details users can work can work offline then sync across devices
cloud only simpler shared back and with live updates but weaker offline behavior now here
you can also tell codex something else you can say well i want this this this this right or you
can press escape and you can ask Codex to explain the question. I can say something like this,
explain the last question in simple terms. Okay. I don't need to answer it right away. I can get
Codex to kind of walk me through it. Right. Explain the last question. Let's see what it says.
I was asking two choices. How should data work? My recommendation, shared code and native shells
plus offline first cloud sync if you want this to become a serious app so it tells you these things
and so you don't need to pick it pick a choice or tell it something else you can close that and you
can ask codex to clarify and now what we can do is ask me those questions again you can do that
or you can simply answer it here it doesn't matter so if you do that it's going to come back with
that questionnaire again and here are the questions i'm going to say this and now i want to say this
because I understood what it was asking me.
Got it.
Your choices are,
that means the architecture should prioritize
a shared TypeScript app,
a brain used by this, this, this, this.
And that's good.
And now I can exit the plan mode
and I can say, go ahead and do it.
Go and implement this.
Something like this or something more specific.
And so plan mode is something that I use all the time.
And you should definitely make it an integral part
of your workflow as well.
Now I want to talk to you about some advanced Codex workflow techniques.
These are the little tips and tricks that I use all the time and will greatly help you when using
Codex to build apps and solve problems. One thing I do all the time is asking Codex to create a
handoff before I start a new thread. This is useful when a thread has gotten long, when the context
has been compacted, or when I want to move from planning into implementation with a cleaner
workspace. A good handoff is not a vague summary. I want the current state, the files that changed,
the commands that were run, what still needs to happen, and any risks or open decisions. That way,
the next codex thread can pick up the work without rereading the entire conversation or repeating
mistakes. There are two main reasons that you may want to do that. The first reason is that after a
while, this conversation here, it starts to degrade. As you keep typing new prompts and as the model
answers, the convo starts to degrade. Now, Codex tells you that it automatically compacts its
context. And that is true. You do not need to start a new convo every time. It does automatically
compact it. But you're going to notice that as your conversations get long and you keep asking
questions and it keeps answering, quality of the responses will degrade. And moreover, you know,
your conversation is going to get fairly long and that might, you know, degrade the performance of
the app itself. And that right there is a good use case to create a brand new convo using the
handoff as the starting point. Another really, really good reason to create a new convo with a
handle is when you're trying to solve a problem, but the model is not getting you the solution that
you want. And so if you're trying to solve a particular problem and you've prompted the model
a couple of ways and it's trying, it's giving you answers, but those answers are not ideal.
It doesn't give you the right algorithm. It doesn't give you the right solution. There is a high chance
that each additional prompt is not going to get you closer to a solution. So when you experience
something like that, the best thing that you can do would be starting over by creating a new
conversation and giving the model a handoff with the things that it has done and the things that
are not working and where you are right now and selling the model as part of that handoff prompt
to work on a different solution. And because AI can be fairly random in some ways, creating a new
conversation usually gives you a different solution. That solution might actually work.
Now, there are various ways to create this handoff prompt that's going to give you a handoff for a new conversation.
One of the simplest ways would be by typing something like this.
Okay, this is a very, very simple prompt that still delivers a fairly high quality handoff.
Okay, so you can type create a detailed handoff prompt that I can use for a new Codex Convo.
Okay, so let's go ahead and send this and see what answer we get.
And this is the response we got. I want to design a fast, robust, cross-platform project management
app. So it's essentially summarizing everything that has happened in the convo, right? This is
the context. This is the product direction. This is the architecture preference. Please produce a
detailed architecture plan covering all this important, right? Also some constraints. And so
what you can do is you can copy that and then you can go ahead and create a brand new convo. For
instance, you can click here and you can simply paste it. Okay, well, you want to delete that,
you want to delete like the top, you want to delete that. And when you paste it, that's going
to create a conversation and the model can simply continue where the other conversation ended. That
is one way to do it. Another way to do it is by giving it a more detailed handoff prompt. So let's
go back here and let's go ahead and give it a slightly different prompt. Create a clean handle
for a new codex thread. Include all of this. Do not make any changes. So this prompt is slightly
more detailed, and you can bet that it's going to give you a higher quality handoff. Okay, so let's
go ahead and run this, and then we can compare the two handoffs and see which one is more detailed.
Now take a look at this handoff right here. Look at how much more detail this handoff versus this
handoff right here. Now, this handoff would definitely work, but this handoff would work
even better. It's going to result in a higher quality conversation. Okay, so given an option,
you can certainly use a prompt such as this, but it's a lot better to use something like this
that's more detailed and it's going to save you a lot of time in the long run.
save you a lot of time in the long run. The next practical habit is using Git as a
checkpoint system. Before I let Codex do meaningful work, I want to know whether the current state
is clean. After each milestone, I want a diff that is small enough to review and explain. That is what
keeps an agentic workflow from turning into one giant mystery edit. The useful trick is to make
Codex summarize the diff in plain English. I do not only want to know what files change, I want to
know why they changed, whether each change belongs to the task, and whether anything looks unrelated
before I accept it or move on. So when you are working in Codex, you do not want to be just
creating edits without recording what the edit is all about. And in software development, you want
to be using a source control system such as Git. We have here a convo where we were building an app
and in this particular instance, we did not use Git. And so I do not know, I have no way to check
which changes were made where. I have no way to revert the changes. I have no way to see what the
actual change represents. And if working in bigger teams, I do not know who was the person responsible
for the change. Now, in this convo, we have another problem. The current working directory
is missing. So in this case, what we can do is we can take a handoff prompt and we can create a
brand new project, insert that handoff prompt, start a new convo, and then enable git and set
up so that we have git control. So I'm going to go over here. I'm just going to do start from scratch.
I'm going to paste this handoff prompt to start a brand new convo. And I'm going to preface it
by selling it to create a git repository. Create a git repo if it doesn't exist and do an initial
commit with the code. So I'm going to run that. And the idea is we are going to initialize git
if needed and then commit the current code as is. All right. So what it did was it initialized a git
repo in this directory and made an initial commit, initial architecture plan here. Okay. The workspace
was empty when inspected. There was nothing there. We just created a brand new project and it
essentially created an architecture. And so at this point we have here a git repo, which means that
each additional change will be automatically tracked. So for instance, I can say something like
make the smallest possible change a route that displays hello world. Okay, let's go ahead and run
that. So it now created this index.html. We're going to open it and it says hello world. And so
now what we can do is we can say check the git status. And obviously this file is not going to
be in our Git, right? You see, this is not tracked, an untracked file. And so what we want is we want
to commit index.html as initial commit, because in Git, you can have files that are tracked and also
files that are not tracked. The files that are not tracked are the files you don't really care about,
right? You don't really need to store them in Git. These could be like media files or generated files,
code generated files that can always be regenerated. But for your actual code, you always
want to be tracking them, right? So we have this commit, and now this file is going to be tracked,
and it's going to be committed as well. Okay, so now it says committed as initial commit, right?
We have this, it's now on main, which is a type of branch. And so now we go into changes, you can see
that we can select the branch here. And as you can see here, it says no file changes yet. And that is
because we have not made any changes since tracking that file. So what I'm going to do now is that make
index.html output hello, James. That has updated. And now it says hello, James. And now what we can
do is we can commit it. Commit index.html. And now if you type give me git status, it's going to tell
you that it hasn't been committed, right? It's modified. It's tracked, but it hasn't been committed.
Okay, it has been modified and uncommitted, right?
You see this M, which means this has been modified.
So we're going to do commit index.html.
And it will also generate a default message.
Here it has committed it.
We can click here and we can select review.
And you can select the type of change you want to see.
You can see on stage, stage, branch, or last turn.
And when you click on last turn, you can see what was changed.
because we are using source control. We can see the stuff that was changed. As you can see,
this is the one line that was changed. Red means it was deleted, and green means it was inserted.
So this was deleted, and this was inserted. We basically changed the message that it says from
hello world to hello James. And so Git is very, very important. If you're working on any kind of
project, anything beyond something super simple, you want to create a repo, and you want to
implement source control into your workflow. One advanced trick that becomes more useful
as projects get bigger is working with Git worktrees. A worktree is a separate working copy
of the same repo connected to a different branch. The practical benefit is that you can keep one
version of the app stable while trying a risky feature, UI direction, or refactor somewhere else.
This matters a lot with agentic coding.
If you want to try two approaches in parallel or keep a clean version ready for recording
while another codex thread keeps building, a worktree gives you that separation.
Now, what's nice about worktrees is that they give you parallelism.
So if you are working on multiple features in your app, maybe you're using subagents
or something else, it's important that no two processes work on the same file at the same time
because that's going to create corruption. And so what you typically end up doing is you create a
work tree for a specific feature and you work on that work tree. And when you're done, you merge
the changes back onto your main tree. Now, that doesn't mean you can only create one work tree.
You can create multiple work trees, as many as you want, and you can also work on the same feature because after one work tree is done, it's going to merge to main.
And if there's a conflict, it's going to resolve that conflict.
And then another work tree, when it is done, it's going to also merge into your main branch where your development is happening.
And if there's a conflict because they ended up working on the same feature, it will also resolve that conflict so that there's no corruption.
Now, this is a feature I use all the time in big projects.
Now, let's say I'm working on this app over here.
You can ask Codex to work in main without creating any work trees.
Or I can ask it to create a new work tree while it makes changes.
So let's continue what we were doing.
So let's say I want to change this index.html, and I wanted to say something else.
So I'm going to go ahead and tell it, make index.html output hello planet.
But this time, we want to make sure that it works in a different work tree.
So what I'm going to do is I'm going to say work in a new work tree and then merge cleanup
after you're done.
Okay, so we're going to go ahead and run this.
And now it's not going to modify the file on our main branch.
It's going to branch out, do the work, and then come back and merge the changes back
in.
And so as you can see here, there's more stuff happening.
I'll make this in a separate Git work tree, commit there,
fast forward merge changes to main,
and then remove the work tree and delete the branch.
And that's exactly what it did, except it did it very, very...
you know, a very small change. But you saw it doing all that. And before you know it, it did all that,
made the change, merged everything back, and deleted the worktree. And so that was a very,
very small change. Now, another thing that you can do is you can click here and you can fork this
whole convo in a separate work tree, right? So if I click over here, that will fork it into a separate
work tree. And here you can see we're working in a separate work tree here, okay? So now as we're
doing work, we need to constantly tell Codex, hey, you know, create a new work tree, clean up,
and do all this when you're done.
We can continue working and then merge our changes.
So for instance, I can say something like
to say hello USA.
I can simply do that.
I don't need to tell it to work in a separate work tree
because we are isolated here.
Okay, so here's the file.
We can open it.
Hello USA here.
And so at this point,
we have merged the work tree change into main
and cleaned up the temporary work tree, right?
Index now displays hello USA
and we no longer have this temporary work tree.
We've done everything that we needed to do separate from the main branch, and then we merged.
And as far as we are concerned, this convo is now finished because it's tied to the old work tree,
but we've did everything we needed to do.
We've updated the files.
We've merged back into main.
And so now we can start a brand new convo to work on a different feature.
And so this is really nice for feature isolation.
Create a new work tree, work there, merge back into main,
and then simply click here to archive this conversation.
Another advanced trick is using sub-agents for parallel work. The idea is not to throw a whole
project at a bunch of agents and hope it works. The useful version is much more controlled.
One agent explores the codebase, another works on a clearly bounded part of the UI,
another checks tests or reviews the results. The key is ownership. If you use sub-agents,
You want each one to have a specific job, clear file area, and a clear output.
That keeps the work parallel without turning it into a merge mess.
Sub-agents are best when the tasks are independent enough to run side by side,
but still simple enough to integrate at the end.
Now, sub-agents is another really cool feature that will help speed up your workflows.
And this is something that I use all the time, especially in big repos, in big code bases to do multiple tasks in parallel.
All right.
So here I have a very, very simple Kanban app.
If I click over here, I have this.
I can drag and drop.
I can create new tasks, et cetera, et cetera.
And so what I want to know is if I'm going to be building more and more features, complex stuff, new functionality,
I want to use subagents to help me kind of make sense of it.
and help me build it in the most efficient way possible. And so I'm going to paste this prompt
here, plan how to split this feature across subagents, right? Do not edit files yet, recommend.
We're going to jump into plan mode, preface this with the feature, add two party apps such as
make.com, Zapier, et cetera. And so I'm going to leave it at this, and I'm going to go ahead and
run this. And so let's go ahead and run this. And here we have the plan. The safest split
is for the main thread to own architecture, shared data contracts. Subagents can work on
isolated feature areas inside index.html, but they must not all edit the same broad sections at once.
Okay, so we have main thread responsibilities, and then we have subagent delegation,
integration settings, integration data model, webhook event dispatcher. So I'm going to copy
this plan, and then I'm going to preface it by telling it spawn subagents right away to help
design the third-party API functionality. Let's go ahead and run this. Right away, it's telling me
I'll spawn the four focused subagents and keep the main thread responsible for the final. So as you
can see, it's spawning them. And each subagent gets a prompt. It's basically like me creating
a new conversation. You're a subagent one, integration. You're a subagent two, integration
data model. You're a subagent three. And they're working independently. And here it tells you all
four sub-agents are running. While they work, I'll inspect the current partial edit. And you can see
these background agents here. Okay, so they're working in parallel. They're working on their own
thing. They own different pieces of the app. And they're kind of working. And when they're done,
they come back to this main agent, right, this convo here, and tell it what happened, right?
They come back with a result. And so now it says the persistent sub-agent returned a cleaner data
shape. And here you can actually click on any one of these and see what's happening. You can click
here. You can come back. You can click on this one and see what it's doing. So this one is finished.
Some are finished. How about this one? This one is also finished. And so that's how it works. And
when they finish, they come back and then it decides what to do later. Maybe it's going to
respawn them. Maybe it's going to spawn something else. Maybe it's done. They did what they needed
to do. They finished their isolated task and their services are no longer needed. And again,
sub-agents is something that I use all the time. I use it all the time, especially in big repos,
because they help speed up the work by isolating different areas, different responsibility clusters
to different agents. And that's a huge productivity boost.
Now, in this section, we're going to bring all of the previous sections together by giving Codex
project instructions in an agents.md file. This is where you can write down the rules you want
Codex to follow every time it works in a specific repo. Which commands to run, which folders matter,
which patterns to preserve, how to verify changes, and when to use work trees for subagents. This is
useful because you do not want to repeat the same project rules in every prompt. If this project
should always run a specific check, use a specific design system, avoid certain files, create work
trees for risky experiments, or split large tasks into sub-agents, those instructions belong in
agents.md. It turns your preferences into reusable project context. And here's a prompt that you can
use which is going to draft agents.md for this project. Do not write the file yet. Include the
project purpose, the main folders, work tree, subagents, stuff like that. So we're going to
jump into plan mode. We're going to go ahead and run that. And here's the draft for this agents.md
tailored to the current project, right? Project purpose, main folders, verification steps after
changes. Serve the app locally, coding and design patterns to preserve. When codecs should use a
work tree. Use a separate work tree when these happen. When codecs should use subagents. Use
subagents when work can be split into clearly separate ownership areas such as these. What
codecs should avoid changing without asking? All of this. Now, the beautiful thing about this
agents.md file is that you no longer have to worry about asking codecs to spawn subagents
or create separate work trees, it will be automatic. It's like saving you from typing
those prompts every single time. So if you want to add a feature, well, you don't need to tell it,
hey, create a new work tree or make sure you spawn sub-agents. It's going to be automatic.
And so at this point, you want to review this proposal here and you want to save this as agents.md.
So I'm going to say save it as agents.
So now it's saved it as agents.md.
You can click here and you can see the whole file right here.
And this file will...
will be used only for this specific project. They're based on a repo. So now for my next prompt,
if it's a simple change, it's not going to create a work tree probably. And it will also not spawn
subagents. But if it's a more complex change, it should probably create a work tree and maybe even
spawn subagents. So let's go ahead and see if this works. So now let's go ahead and ask it,
make a simple change that changes the title for the main index.html to Awesome Kanban app.
Okay, I'm going to go ahead and run it directly. So now the title is Awesome Kanban app. Okay,
But if we ask it something more complex, right, you know, figure out a third party, you know, integration, design, you know, support API calls or support MCP or anything like that, it should probably use subagents to figure it out and implement the changes in its own work tree.
So let's see if this works. Add a robust API functionality for handling outgoing API calls
and incoming webhooks. Okay, I'm going to jump into plan mode to see if it has any questions for
me. See how it says agents.md explicitly says not to add a backend or proxy without asking.
Okay, so it did consult this. So we're going to add a backend. We're going to create tasks.
And let's see if it's going to create a work tree automatically and maybe even use subagents.
Another question, should the new backend become the source of truth for Kanban tasks?
Yes. Let's just go with recommended. Okay. We're going to expand this plan and we're going to see
if it's going to be using a work tree or subagents for any of these things. Okay. So I do not see
it's going to be using subagents. Update. So before we run it, let's ask it, do you plan
on using a work tree for sub-agents for this task. There you go. Yes, for implementation,
I'd use a work tree because this changes the project from a static-only app into a node
server app with API routes and persistent states. I'd also use sub-agents, but only for bounded
design review tasks. And so it's telling you right there that it will be using a work tree,
and it will be using sub-agents. And you can bet that this would never happen if we didn't
have this agents.md file. And so agents.md is super important. It's going to save you a lot of time
because it basically codifies repeatable tasks. So you never have to re-prompt the same thing
over and over again. Now, before we build real apps, there is one security habit you want to
establish early. Codex can help inspect configuration, but we should be careful with
secrets. An environment variable might be safe and public, like a front-end URL, or it might be
private, like an API key or deploy token. These should not be casually pasted into a prompt or
committed into the repo. The other important thing is that local config and deployment config are not
the same thing. A local.n file helps the app run on my machine, but Vercel does not automatically
copy that file into production. For a deployed app, the required variables need to exist in the
deployment environment too. So the right workflow is to ask codecs to identify what variables are
needed, classify them as public or private, and then advise you where each one needs to be configured.
Now let's say we're building on this app and we are adding external services. So one of those
services might be something like OpenAI, or another service could be OpenRouter. Well,
every time we connect to external services, we need to connect them using an API key,
and those API keys are needed for those services to track how much usage we have so that they can
bill us accordingly. And so in your app, you need to be storing those API keys because when you're
going to be making those requests, regardless whether that's an API token or some kind of
deployment token or pretty much anything else, you need to be very, very careful how you are
storing them. And so in this app, let's say we want to use OpenAI here. So I'm going to say
API stack and use the following key. And let's say we give it a sample API key. Sample API key
as a sample. We're going to jump into plan mode. We're going to select this API stack only. We're
going to be doing native fetch. All right, so it went ahead and created our first API stack here.
And right here, it mentions this file where it stores this key. And so if you want to use a real
key, you never want to paste it in chat. What you want to do is you want to open this file and modify
it directly. So that's what we're going to do. We're going to open this in the editor here,
and I'm going to paste this key right here. And this right here is my actual key. And so now
I have an open AI, I have an API stack, and I have a real key in this file here, okay? And now what I
need to do is I need to run a check and ensure that we are storing the keys the right way, and, you
know, they're going to be deployed correctly and all that. And so I have this prompt to do just that,
and it says here, inspect this project for environment variables and deployment config. Do
not print secret values, and then tell me all of these things. So we're going to run this. So now
it's telling us that environment inspection, required environment variables, required only
for post, open API front-end variables, right? We don't have any public because, you know, sometimes
your app can have both private keys and public keys, right? So if you're using something like
Superbase, Superbase has an Anon key or a secret key, or they call it something else now. And the
idea is the public key can be made available, but it has very, very strict permissions. Whereas
something like your OpenAI API key or your OpenRouter API key or something of that sort
needs to be very, very secret, right? Because with that key, you can make a lot of calls and
do a lot of things. And so here it says we have a private key. OpenAI key is private and must stay
server-side. It is used here, needed locally. Hosted service config, Vercel or another node
capable host configured as a private server environment variables, port, etc, etc. Okay,
that end of example is currently on track. So what we have, safest next step before deploying,
replace it with only this, only configure the real key in the deployment provider's private
environment variable settings. Okay, so I want to store the key locally for testing, and I want to
ensure that it will be deployed also later. And so we want that key locally so that we can test,
but we also want it to deploy. And that means we need to create a couple of files, one for local
settings and one for deployment settings. And it's telling us which is the wrong file for local
secret because examples are usually committed. So let's say we're doing a Vercel deploy. We're
going to switch that. And there we have it. Store the real key locally in an untrack, right? We need
to make sure that this is never committed to git it needs to be untracked so we're going to expand
this submit this do not use public these are not public keys replace dot end of example with
create dot end okay so it's it's going to be creating this dot end the secret is now ignored
in dot end and then i'm updating readme and agents to make the local and recel setup unambiguous
And that way we have the local key stored for local testing.
It's never going to be committed into Git.
And then we'll be able to send that key, also deploy that key onto Vercel because Vercel
is going to be running our app.
It needs access to that key as well.
It needs to be secret.
Okay, implemented the local Vercel key setup.
And so in this point, we've made the secret key management and not just secret key, any
kind of key management as part of our workflow.
and we can be assured that we have the key for local stuff and we're also going to be deploying
the key correctly for production stuff regardless of what kind of host you are using
to be writing code for the core stuff. But a lot of things that your app will be doing will be done
by existing code. You're not going to be building your app from scratch, right? You're going to be
using existing libraries, existing frameworks, stuff like that. And those are called dependencies.
And that is because your app depends on them to function. Without those things, your app will not
function. And you need to ensure that you have a process for managing these dependencies. And I
have here a prompt that you can use that will help you. Inspect this project before adding any
dependencies. Do not install anything yet. Tell me all of this. And so let's go ahead and run this
prompt. Right. And this is what it came back with. Dependency project inspection. Framework and
package manager. Framework non-detected. This appears to be a plain static JavaScript app
served by a custom node server. Now, of course, this will definitely not be the case when it
comes to your real apps. You're going to be using some kind of framework, something that will make
your app behave like a real app. Here, we just have a very, very plain app. Package manager,
non-detected, no, none of this. And of course, when you're going to be building your app,
you're going to be having all this as well. Available scripts, no NPM scripts exist because
there's no package manager, because there's no package.json. Current documented run command,
we just have this very, very basic. Definitely not the case when it comes to production apps.
OpenAI local and run command. So we have this. Relevant install dependencies. So we do have some
basic node built-ins. All of these OpenAI calls native fetch. Okay, so it's native. It's not using
the OpenAI SDK, which would have been a dependency. Can the task be completed without adding a package?
Yes, for the current OpenAI API stack and local serving, the project already calls OpenAI via
native fetch. If a new package is recommended, no package is recommended right now. A package could
be recommended later. If we use Express, Fastify, we start using the official SDK.env. Files likely
to change if preceding, right? API behavior, openA calls, frontend, et cetera, et cetera.
And so dependencies are important and you want to limit your dependencies. You don't want the system
to just add dependencies blindly. And so this is going to be super useful as you're building your
app so that you can streamline it. Because as I was just building this simple app, Codex asked me
whether I want to use OpenAI SDK or native fetch. And you always want to err on the side of native
stuff. If you can avoid a dependency or an SDK, that would be the right move. And that's exactly
what I did here. I just used native, right? I could have used an SDK, but I decided I'm just
going to keep it as simple as possible. And that's really the goal here. And this prompt and making
this part of your workflow is going to enable you to keep your app streamlined so that you have less
dependencies, less chance for something to go wrong, less bloat, etc., etc. So definitely add
this to your app building workflow and ensure that Codex knows about it by making this a part
of your agent's MD for a separate step. Now that the Codex foundation is clear, we are going to
start with something intentionally small. The first app is called HabitCard, and it is a tiny
habit tracker where users can add habits, check them all for the day, and see a simple streak or
count. This is a great starter project because the result is visual, easy to check, and small enough
that every step stays clear. Codex can plan the app, build the UI, show us the file changes,
open the browser, polish the result, and get the front end ready to deploy without also introducing
backend complexity. HabitCard gives us the core app building pieces without much product complexity.
a form, a list, a daily check-in state, simple feedback, and later local storage persistence.
It does not need authentication, payments, APIs, or a real database at first.
This first app is about getting comfortable with the full Codex loop on something we can understand immediately.
Now, here in Codex, the first thing that you want to do is you want to click here, and you can select Start from Scratch, but I like to have it set to a specific folder.
So I'm going to click on Use an Existing Folder, and I have here a folder prepared called Demo.
So I'm going to open this here, and now we have a new project that has been associated with a specific folder.
And here we can start a brand new conversation for the app that we are building.
Now, anytime I start building a brand new app, I always want to create a visual architecture.
Being a visual person, this gives me an understanding of the scope of an app, how the app looks, the user flow, and stuff like that.
And we can actually use Codex to create that visual architecture for us.
Now, I have here a prepared prompt that creates this visual architecture.
And we want to ensure that we use the built-in image generation that we have in Codex as well as ChatGPT to do it.
So I'm going to press forward slash, and I'm going to search for image gen.
Okay, and then we can say something like use image gen for the following.
And I'm going to go jump into plan mode, and I'm going to go ahead and execute this.
Okay, and it came back with a habit card architecture diagram.
And here it says create one raster infographic using this.
So everything looks good.
There's some diagram content, visual direction.
It's a wide composition.
Looks good.
We're going to say, yes, implement this.
Okay.
And that is our habit card.
That is our visual interface.
And right away, I can see what this app is all about, right?
We have add habit.
We have habit list.
We have today check-in.
And we have a streak count.
then we have an empty state we have local storage later and we have the Vercel deploy and so this is
a very very simplified visual architecture but it is very very important I want to see right away
what I'm dealing with what I'm working with how many pages you know how complex is the app how
simple is the app I see that this is not going to be you know a very complex app it's going to be a
fairly simple app, but we do have some interesting bits here, right? This empty state, we have some
local storage, we have a Vercel deploy, and so it's a fairly simple app, but still a fairly workable
app. Now, the next thing that I like to do is create the entity architecture, and this is where
we're going to be mapping the small set of entities behind the app. So even though the first version
is front-end only, it is useful to name the habit, the daily check-in, and the street count summary
before we add a local storage later. And this right here is the entity diagram. And I'm just
going to say use image gen for below. I'm going to go ahead and run that. And I can run it directly.
I don't really need to run it in plan mode because it's just generating a diagram. I'm not asking it
a complex, ambiguous coding question or giving it an ambiguous coding instruction.
And here is our NTC architecture. And unlike the visual architecture that we...
generated previously, here we're actually seeing the entities that will later become the actual
storage schema. Okay, so we have the habit, we have a habit check-in, we have a streak summary,
and then local storage as the backend.
So no backend, everything is stored locally
with local storage.
And this is also very, very useful
because unlike the visual diagram here,
I wanna see the actual schema.
I wanna see what kind of elements
or what kind of tables we might need
to translate this app schema into.
And as you can see, this is fairly simple.
Habit, habit check-in.
streak summary, we have these three main functions here, these three main features that were
translated into entities. Okay. And then we have, and for each entity, we have things like name,
created at date, completed count. Now at this point, we have both the visual architecture as
well as the entity architecture. And this is something that I like to do for pretty much
every single app that I build, because I want to get an idea of what I'm really dealing with,
right i want to have an understanding of the the scope of the app and right now i can see exactly
where we are i can see that this is a fairly simple app i can see the entities i i see the app
building i see the future of the app i see the app coming together now the next thing that we want
to do is we want to use the plan mode to ask codex what stack makes sense for this first app
The important part is that Codex should recommend the simplest path before it edits any files.
And as you might have guessed, we are going to be doing this in plan mode.
All right.
And here's the prompt that we're going to be using.
Do not edit files yet.
Inspect the current project and recommend the simplest stack for HabitCard, right?
And we ask him what it should come back with.
And we're going to press Shift-Tab to enable the plan mode, of course, because we want
it to come back to us if it needs to and ask any clarifying questions. We needed to clarify
everything before we go deeper into the building the app. Okay, I'm going to go ahead and execute
this. And let's see what it comes back with. And in this case, it did not come back with any
clarifying questions. Okay, so it's writing a plan. And the recommended front end stack is going to be
React TypeScript, right? It wants to use Tailwind CSS for fast, simple styling. This is testing
library, no React router. It's a simple single screen app, no global state library, okay?
Backend decision. No backend is needed for the first version, right? And that's what we told it.
We set bias toward a front-end only implementation first. And then it's also going to use browser
verification. Okay, open the app in the browser, verify all this. Okay, so let's go ahead and
run this. All right, so it worked for about 10 minutes, and it has implemented the habit card
as a front-end only React TypeScript app. This is where it is, and this is what it did, right?
It built the app shell and UI, habit logic, local storage, components for adding form, for the ad
form list card and empty state tests for app flow logic and storage and verification passed nine
tests production build succeeded and it also gave us a dev server that is running the app and so this
dev server is running on my machine right now and this allows us to quickly test things without
needing to deploy and test there and on the right hand side we have this card that is always available
and it shows us things like artifacts, background terminal, and basically things that were created
as part of this conversation. Okay, so we have the images that were generated. We have the index.html
for the app. We have the background terminal that is running here. And so I can click here,
and that's going to go ahead and go to the server that's running our app. So let's do that. And
that's going to go ahead and open. It's also going to open the browser right here in the right-hand
pane. Now, before we had no right hand pane, but if you click here, you can see that it opens up
here, right there. Another thing that you can do is you can open the browser directly. This is the
front page here, and I can add a habit, habit one. I can click here, and we have a habit here. I can
add another habit, habit two, or maybe gym, and that's creating these habits here. So I can check
it off, and that is done. Check it off. And so it's a very, very simple app, and if you want to see the
actual files that were created as part of this, you can simply right-click here and open in Finder.
And this is the React app that was created for this here. Once the UI works, we'll add a small
persistence step with local storage. Habits and today's check-ins can persist after refresh,
so the app starts to feel real without introducing a backend yet. And this is the prompt that we're
going to be using. Upgrade habit card. So habits in today's check-ins persist with local storage.
I'm going to jump into the plan mode here just in case. And I'm going to go ahead and run this.
Now it's actually telling us that inspection shows that habit card already implements the
requested front-end only local storage persistence. Okay. So no file edits are needed for this upgrade.
So we must have done this in one of the previous prompts. But if we hadn't done this,
then we would run this prompt. But still, let's go ahead and run it. And now it tells us that
persistence works through this storage using these keys and a lot of other details here. Okay,
so we can reload this. And now we have something called local storage. And what this means is that
this app does not have a backend, but this stuff is going to be stored on my browser. Okay, so
if I'm using this instance, it's going to be stored on this browser. If I run it in a different
browser, then it's not going to have the data. So whatever I do in that new browser is going to have
fresh data. And so this is a way to create, you know, storage just for testing mail. I mean, you
can use this in production as well for certain apps, for certain situations. It does have its
place, but it's very, very limiting compared to something like Superbase or something of that
sort. And so we can delete all this. We can do all that. We can start. And if I copy this,
run this app, and I load this app, there's nothing there because I'm using a brand new
browser instance. And I can create, I can do, I can check off, I can do this, I can do all that.
But if I go back to Codex, there's nothing here, right? It's not syncing. It's not using my account
and it's not using a unified backend
so that no matter which browser I use,
it will still store the data and keep track of everything.
That is not happening.
Now, once the app works locally, it's time to deploy it.
Even though HabitCard is simple,
this is the first moment where Codex helps move something
from local code to a real-life URL.
And so Codex can do the whole deployment process.
It can run the local checks, prepare the projects, connect or create the Vercel project,
deploy the frontend, and then verify that the live page actually loads.
And additionally, you want that first deployment to feel very concrete.
We're not just writing code and hoping it works.
We're taking a small app, shipping it, opening the deployed URL,
and checking the result like we would with a real project.
And here is my Vercel deployment prompt. Prepare HabitCard for deployment on Vercel
and verify it works as a small front-end only app. So at this point, we are just preparing it
for deployment. We're not yet deploying it, but still, this is an important step because this will
ensure that once we do deploy it, that it will work without any issues. I'm going to go jump
into the plan mode. And remember, we do have that Versal plugin enabled, and so it should
use it automatically with no issues.
I'm going to go ahead and execute this.
All right, so it went ahead and created a Vercel deployment plan.
HabitCard is already suitable for a front-end only Vercel deployment.
And this is what it's going to do.
And here is the deployment implementation.
Keep the app front-end only.
Do not add convex, which is a backend, APIs, auth database, server functions, or external
services.
None of that.
And local storage persistence is expected to be local to each browser and deployment
origin.
Data will not sync across devices or URLs.
Okay, let's go ahead and implement this plan.
three minutes later, it tells us that deployed HabitCard to resell and verified it live. Okay,
so this is the live URL. We can click here, and that's going to open our HabitCard app running
on the web, right? Accessible to everybody. And this, again, uses local storage. Okay,
so we can do that over here. And of course, you know, it's not going to be available in another
instance because it's all stored locally. And so at this point, we designed, architected, built,
tested, and then deployed a very, very simple web app that uses local storage as our backend. And
this proved the whole cycle for us. Now, in the next several modules, we're going to be doing the
same, but with more complex apps, slowly adding things like authentication, backend, and other
important components that you need for a real production app.
The second app we'll be building will be a mini team voting app where people submit
lunch or snack ideas and vote on the winner.
It's a bit more complex with more features, but still fairly simple overall.
SnackVote has a submit option form, a snack option list, vote buttons, a live leaderboard
and a winner card. This app will serve as a bridge between a simple front-end and the larger
marketplace app we'll build right after this. Instead of jumping straight into complex entities
such as customers, bookings, and permissions, we can first learn the backend pattern on a much
smaller app. SnackVote only needs snack options and votes. Someone can submit an option, other
people can vote, and the leaderboard updates as the vote counts change. That gives us enough
structure to understand live backend data without making the product itself hard to follow.
As always, in this first step, we'll be mapping the SnackVote interface visually. The app should
be simple enough to understand immediately. Create or join a voting room, submit a Snack
option, vote once, watch the leaderboard update, and see a deadline-driven winner state. Now here
in Codex, we're going to come here and we're going to create a new project from an existing folder.
We're going to click over here. Here, we're going to create a new folder. I'm going to type
snack vote, and we're going to click open. And now we have a brand new project configured here in
Codex. And here's our prompt for the visual architecture. We want a preface that we want
to use this image and we're going to jump into plan mode and execute this. That looks good. We're
going to go ahead and expand that. Go ahead and implement that. And here's our snack vote visual
architecture. And look at this beautiful diagram. So you can create or join a room. In the current
room, you're going to be seeing this members and the time left. You have here a snack list. You
have your voting buttons, you have a live leaderboard, and you have a closed winner state
with some voting deadlines here, here as well. And then we also have our Vercel deploy. And so
this looks like a fairly fun app with a lot of things going on. And so I can't wait to implement
this. And we're also going to be adding more and more features as we go along. Next, I want to go
ahead and create an entity diagram, an entity architecture diagram. So here's our prompt. We're
going to do this, and we're going to go ahead and execute that. And here's our entity diagram.
Okay, so a room contains multiple snack options and has one voting session, right? We have the
voting room, many snack options, and many votes, right? We have here some winner logic, the winner
logic snack option with the highest vote count when now is greater than or equal to closes at
right so after the deadline we have here a legend and here we have a sample kind of workflow a
pipeline build the ui first connect the to convex later convex is going to be our back end and we
are going to be leveraging things like real-time updates persistence and live vote counts and so
So now that we've generated a visual architecture diagram, as well as our entity diagram, the
next thing that we want to do is we want to ask Codex for some stack recommendations,
because there are lots of ways that we can build out this app.
And we want Codex to tell us the best options for this specific app.
Here's the prompt that we're going to be using.
And I'm going to switch into plan mode here.
And it's telling us, do not edit files yet.
inspect the current project and recommend the simplest stack for Snackville. And here's the
plan that it came back with. Here we have the stack recommendation. We're going to be using React,
TypeScript, Tailwind. And here it says back and later convex with TypeScript server functions and
generated client types. And so for the most part, this is very, very similar, if not the exact same
architecture stack that we use for the first app, except we're going to be adding more and more
features and also connecting a backend for the first time in this tutorial. Now here, instead
of clicking submit, I'm going to give it another prompt, and this prompt is going to start building
the app, writing the code. And here's the prompt, implement the first working SnackVote UI without
a database or persistence. Inspect the current project first, then build the smallest useful
SnackVote UI. And there's some verification steps as well. And we also explicitly tell it to not use
Convex, local storage, or an API, nothing of that. Just keep it to these specs right here. And we also
have some verification. So I'm going to go ahead and run this in plan mode in case it wants to ask
me something. So it doesn't have any questions for us. And that is because in this specific
conversation, we already fleshed out, you know, things like the architecture, the stack, and all
of that stuff. And so it kind of knows what it needs to do to build out this app. So we're going
to say, yes, implement this, because this is the step where we actually want the code written.
All right, so this has completed. And it says here, implemented the first working UI only snack
vote app here, created all of this, what works, verification completed, still needs attention
later. Okay, all of these things. And we'll talk about that a little bit later. And so now we have
a web preview. So we can click on open. And that's going to go ahead and open it right here in our
built in browser here. This is our app right here. And so we have snack and lunch options, we can
create, we can submit an option, add sample snacks, click here, and we have these snack options here
with some votes here. Leaderboard, right? So this is where...
Winner state, current winner,
leader, spicy ramen bowls.
And so if I vote on falafel wraps,
six, right?
So now it's six.
I can keep voting.
And that's a problem right away.
and it's in memory and one person can vote multiple times, which is an issue. We're going
to fix that a little bit later, but I can also add a snack or let's say sushi. I don't know,
sushi. Add this and we have sushi and I can also vote on that. So it's a big, big issue. But
for the most part, the logic works, the UI works. Now, once the snack vote UI exists,
we're going to replace the mock snack data with real convex data. And for those of you that are
not familiar, Convex is a backend that we're going to be using in this tutorial. It's an awesome
backend, super fast. And if you want to learn more information, I actually did a dedicated video on
it that you can find right there. And so once we add Convex, our app will stop being a static
interface and start behaving like a real database-backed product. And the path is very, very
simple codex, creates the convex schema, adds a query, adds mutations, connects it to the UI,
and then we verify the result in both the browser and the convex dashboard. And so when we submit
an option in the app, it should be written back to convex. When we look inside the convex dashboard,
that snack option should be there. And when someone votes, the UI should update live so that
we can see the front end and back end working together instead of treating the back end like
a black box. And when you head over to convex.dev, you can learn more about this back end. And this
is a great, great back end. It's very, very fast. And it works really great with agents, right? So
the back end building blocks for your agents. Okay. So I'm going to go ahead and log into my
free account. I'm using the free plan. I'm not paying for anything. And this is also an open
source backend, so you can also self-host it if you want. So I'm going to go ahead and log in.
All right, so here I am logged in, and as you can see, I have here two projects. Now, our app is
going to automatically create a brand new project for its data, for its functions, for everything.
And here, back in Codex, we're going to paste a new prompt that looks something like this.
Upgrade snack vote, so snack options and votes are stored in convex instead of local in-memory
state. Now, if I press Command, comma, and go to MCP servers, you can see that I do not have the
convex MCP server. And that is because we're not going to be connecting to convex via MCP. We're
actually going to be connecting to it using a much simpler method, and that is the CLI, which stands
for Command Line Interface. And actually, before I run this prompt, we are going to check to make
sure that we have a connection. Can you first check that we have the Convex CLI installed?
And if not, do install it. I'm going to go ahead and run it. Now, I already have Convex CLI installed,
but you can just tell Codex to install it. It's that easy. And so it's telling me that NPX,
which is a package manager, could fetch Convex temporarily, but the project does not have it
installed. I'm installing Convex into the project now as a dev dependency. Convex is installed
locally now. I'll verify the CLI results. And so you don't need to read lots and lots of
documentation, figure out how to connect to it. You just tell Codex that you want to connect to it.
It's that easy. So Convex CLI is installed locally in the project now. So now we can paste the
prompt, upgrade SnackVote. So SnackOptions and votes are stored in Convex instead of local in
memory state. So I'm going to go ahead and do this. And let's go into plan mode, see if it wants to
ask me something or clarify something. And so it's telling me one material setup choice is still
open. There is no existing Convex folder. So this app is not linked to a Convex deployment yet. And
that is correct. And that's what we want to do next. And now it's asking me which Convex backend
should SnackVault use for this first backed version. We want to create a new one, right? So
we're going to go with the recommended option. All right. And now we have a new plan to upgrade
the existing app from in-memory SnackOptions to live convex data. Okay. So it's going to do
everything. And it's going to essentially configure the backend to be convex, set up the schema,
set up the data, everything. And once it's done, we should be able to go to convex and see a brand
new project here automatically created. So I'm going to hit submit here. All right. So it says
it has created a fresh cloud project and synced the backend function successfully. And now you
see this cursor, it's testing out the UI. And so right now it's not running, so it should start it
out. And here it says the existing browser tab was sitting on the browser error. So it has restarted
it. And if we jump into Convex, you can see that we have a new project created. Now, I did
authenticate this account with Codex, so it knows that this is my account. And so if we click over
here, we should see some initial stuff happening, right? There's some data, functions, and it's not
done yet, right? It's still working. And while it's working, we can see what has been done. And
it's actually typing it. Look at that. Key press input. It's creating it. It's testing it right
here. You can actually see it happening. The snack was submitted through the browser and appeared
from Convex. I am voting on it. There it is. It's testing all the flows, which is pretty cool.
All right. Now it's telling us implemented the Convex-backed snack vote upgrade, changed all
of this. What changed? Verification, edge cases handled, and it is running. So we can test it
ourselves. And so here's the app. And now it's convex backed. And so now if we head to convex,
we should see the data. So as you can see, snack options, this has a vote of one. This is this
nachos. Vote one. And if we increase the vote, it should be two. And it's automatic. It's
absolutely automatic. Three, it's three. It does not need to do anything. And we can create a new
snack option, let's say sushi, submit. And if we come over here, we see sushi, zero votes. Now it's
winning. And so this is essentially the same app, except it's convex-backed. And we also have
functions. And with convex, you need to create functions to access your data. It's not like
with other systems where it's automatic. Here you need list, you need submit, you need a vote,
you need functions. And so the snack options table or document has three functions. No files,
no schedules, and there's some logs here so that you can see things are happening. Okay, so this
was a fairly successful migration. We went to no backend to a convex backend very, very quickly.
Now that SnackVault has real convex data, we can make it feel more like a shared group app.
Instead of one global snack board, users can create or join a simple voting room like Friday
lunch or team snacks. Each room should own its own snack options, votes, leaderboard,
and winner's state. This keeps the app more interesting while teaching a clean backend
concept, scoped data. We still do not need accounts, permissions, invites, or admin tools.
And here's the prompt that we're going to be using.
Upgrade snack vote so voting happens inside simple rooms.
And I'm going to run this in a plan mode.
All right, so it came back with a plan for us.
This is the room-based snack vote upgrade.
Upgrade the current ConvexBack app from one global snack board to simple rooms.
Going to expand that.
Yes, implement that.
So as it's running, I am seeing an error message here.
Did you forget to run npx convex dev?
Okay, so let's see if it's able to catch that and solve it before the next prompt.
It is done.
So it has implemented room-based snack.
Whoa, this is what it changed.
files, things, verification, limits. Okay, very important. Limits is actually very, very useful.
No auth ownership invites or duplicate vote guard yet. And we'll fix some of these a little later.
Room selection, room codes. Okay, so how does this work? Let's go ahead and refresh this.
All right, so we can create or join a room. And there are some rooms over here. So let's say we
type Friday lunch. And so now we've switched the room. Okay. Current room, Friday lunch. And now
we can do the same thing. We're now in the scope. It's all about scoping now, right? And so this is
a specific room. And I can say, I don't know, submit. There we have it in this room. And now
if I switch a room, let's say I switch to lunch ideas. So now it's brand new. There's nothing,
nothing there. And I can say something like, I don't know, tacos. And now we have tacos here.
And if we go into Codex, we should see that. So we have voting rooms here, and we have different
ideas here. And now if we go into snack options, we can see that they belong to a specific room.
We have the room IDs. These are the same, same room, then we have a bunch of different
room IDs there. Probably some of them created by Codex as part of testing, like lunch ideas,
Oh no, I created lunch ideas. These ones were created by Codex, these three rooms.
And we can remove them. I can select these and we can delete these. And if we go into functions,
we can see that for snack options, the same three functions, but for voting room, we have get,
create or join, a bunch of other functions that we have. And so it pretty much did everything.
It created the functions, it created the schema, it even created some test data while it was
tested.
We'll add one simple rule that makes the voting feel like a real product.
After all, a person should not be able to spam the same room with repeated votes.
And that is because we still do not have real authentication.
And so for this tutorial, a local or session-based voter identity is enough.
and that's what we're going to be doing right now. And here's my next prompt. We're going to
upgrade SnackVotes so each person can only have one active vote per room. Jump into plan mode,
run that. So here's the plan, one active vote per room. Add a lightweight session-based voting room.
Each browser session gets a session ID, and Convex stores one active vote per room ID and
session ID, right? So this needs to be unique. So if I voted in that room, my session ID was used to
vote. And so this needs to be unique. So for that room, my session can only happen twice. If there
is a chance for a repeat, it's not going to count it. Yeah, I can vote in other rooms, but per session,
per room can only happen once. We're going to expand this, looks good, and submit this. So it
done implemented one active vote per room okay change this what changed and it added this get
my vote added votes with table so let's go ahead and try this out open this here so let's say i go
to another room friend friday lunch i switch to that room and i have my burrito so i'm gonna vote
for this i just voted and i can't vote again you see that i can't vote again because if i go to
convex and I go into data and I go into votes, I should see a session ID with ROM ID. So let me go
ahead and delete all of these so that we can see which one is mine. And so now I can vote again.
You see it's back up. It's reactive. I'm going to hit vote. And now you see ROM ID and session ID.
These two, they can only appear once in this table. And so obviously now it knows that my
session ID and I'm trying to vote for this one and that's not going to work because I'm in this room.
I'm in this room here, Friday lunch, Friday lunch right there. Now, if I switch rooms, let's say I go
to another room. Let's say I go into Sunday brunch. Now I can vote, right? I can vote for anything. I
can say tacos, submit. I can vote here and let's say I create another one. I can change my vote.
So I can switch votes, but I cannot pad with multiple votes an item.
And so if I go back here, now there are two options, right?
Two different rooms, same session ID, but I cannot vote in the same room more than once.
So this works really, really nice.
And finally, we'll add a deadline so each room has a moment when voting closes.
Before the deadline, people can submit and vote.
After the deadline, voting locks and the app shows the winner or a simple tie state.
This adds time-based product state without becoming a scheduling system.
It is still a small group decision app, but now it shows how front-end UI and back-end data can derive open, closed, winner, and tie states from one field.
And here's the prompt that we're going to be using.
I'm going to switch into plan mode.
Run this.
Oh, it needs a product decision.
Okay, how should users set a room deadline in this small tutorial version?
Quick durations.
Okay, add simple buttons like 1 minute, 5 minute, 15 minute.
When creating opening a room.
Daytime input or fixed default.
Let's do quick durations.
That sounds good.
Let's implement this.
And it is complete.
Implemented simple voting deadlines.
This is what was changed.
Added quick deadline choices.
No deadline, one minute, five minutes, 15 minutes.
All of this.
And let's go ahead and see how this works.
All right.
So here we are.
And let's go ahead and create the room, Friday lunch.
And let's say it's five minutes.
Select five minutes.
Open the room.
This still says no deadline.
Let's try another room.
Let's say Sunday brunch.
I can select no deadline.
I can do 15 minutes.
Let's try 15 minutes.
See, it says no deadline.
Okay, that's a bug.
That's definitely a bug.
So let's see if it's able to fix it.
That's the first bug that has happened to us, as far as I remember.
And so we're going to say, create it, tried creating a room and selecting a deadline,
but it ended up creating...
And we don't really need plan mode for this. There's no clarifying questions here. It's a
simple bug. And we don't really want it to clarify. We know what the bug is. We just wanted to fix
it so there's really no ambiguity there it's like it's like i'm not looking to negotiate with codex
i know this is a bug and i wanted to fix it right there's no other ways there's nothing else
happening unless i'm wrong and in that case it's going to tell me that i'm wrong that it works but
there's no other paths here as far as i'm concerned now sometimes codex would output something like
this and it tries to go into plan mode. And so right now it thinks it's in plan mode, but it's,
it actually is not in plan mode. And so if I say something like do it, it's going to complain that,
that I did not leave the plan mode while I'm not in the plan mode. So this is a bug that I have
been experiencing from time to time. And it's annoying, but it's, it's easily fixable. You see,
it says I can't edit files because this thread is in plan mode, but we're not in plan mode.
And so the solution is to go into plan mode and type something. Okay, fix it. And then it's going
to say something like, well, you know, I can't do it. I'm in plan mode. And then you can leave plan
mode. Now it understands it. You see, now it's correct. Fix the bug where it's selecting a
deadline and opening an existing no deadline room still leaves the room with no deadline.
So we're going to submit this. All right. So it looks like it fixed it. And here it says in the
browser, I created a no deadline room, reopened it with 15 minutes, and it showed open plus closes in,
et cetera. So let's go ahead and test this out ourselves to ensure that it does really work.
So we have this and let's do Friday lunch. And we said 15 minutes. And now it shows it.
and let's say one minute. Room one, one minute. There we go. One minute. And let's try no deadline.
Room two, select no deadline, open no deadline. Okay, so this looks like this was finally fixed.
Now, once SnackVote has rooms, session-based voting, and a deadline, we are ready to deploy
the front-end app with Vercel and verify that the deployed app points to the right backend
environment. And this will round up this specific app build. And here's our prompt, prepare snack
mode for deployment on Vercel and verify it works with the convex backend. Okay, I'm just going to do
it in plan mode, run that. Here it's being very, very clever. One important deployment decision
remains whether the Vercel app should use the existing Convex dev deployment or it should
promote it to production. Okay and this is really really cool because this is something that I
wanted to cover once this was done. So if we go into Convex and you click over here you can see
all your deployments, your different deployments. So we are currently on the development deployment,
on the development cloud. We can also have a production deployment, preview deployments,
other deployments, stuff like that. So ideally, once we deploy it with Vercel, we wanted to use
the production convex, and that's what we're going to select, because this makes sense.
Production deployment uses the production convex. Development deployment uses the development
convex. This is our plan, prepare, snack vote for a production Vercel deploy connected to the convex
production backend. We're going to hit submit, and it's going to create a production. In fact,
they already did it, right? We can switch to this, and it's going to have a production environment
here created for us. All right, so it has deployed SnackVote to Vercel and verified it against
convex production, okay? So this is the live URL, what we're seeing here, deployment URL,
and the convex backend.
And if we go into convex,
you can see that it's currently pointing
to the production URL here.
And we have everything here in production.
So we have the dev instance
pointing to the dev deployment in convex
and the production instance in Vercel
pointing to the production instance here in convex.
So we have all the same functions.
We have all the same data.
Everything is there.
The data might be a little different,
but the schema is exactly the same and it works, right? So we can create a room, whatever, new room,
one minute, open it. And now 59 seconds, 58 seconds looks good. We can create another room,
room three, no deadline. And that has no deadline. So I'm currently in this room. I can create
a food option. I can vote. I can't vote anymore. One active vote per room. This is the leaderboard.
So it looks really good. And this time we've actually built a fairly cool and a fun app along with a backend that uses several different deployments depending on where the app is running. So for local deployment, we have the local, the dev convex deployment. And for the production, we're cell deployment, we're using the production convex deployment. Okay, so this was a slightly more complex app.
But there's still one more app that I want to build, and this app is going to be the most complex of them all.
It's going to bring a lot of these things that we've been talking about so far together.
And also, we're going to be introducing some new functionality, new features, and a lot of really cool things.
Now, for this last app in the course, we're going to be building FlexHelp.
And this is where we take the workflow from the first two smaller apps and apply it to a more realistic product.
A two-sided marketplace where helpers offer fixer services and customers book them.
The important thing is that we will still build it in controlled steps.
We're not going to ask Codex to build the whole marketplace at once.
We are going to architect it, design it, build the UI, then add feature by feature.
feature. And last but not least, we're going to be deploying the app, making it available to anyone.
As always, our first step will be creating the visual architecture. This gives us the shape of
the product, the customer flow, the helper flow, the main screens, and the path from browsing a
service to booking help. Now, here in Codex, we're going to click here and we're going to create a
brand new project. Now, I like to start it from an existing folder, and I'm going to create a new
folder. Flex help. I'm going to hit create and I'm going to click open and that creates a brand new
project. Now the first thing that we're going to be doing is we're going to be building a visual
architecture. The same thing that we did for the previous two apps and this is important because
this gives us the shape of the product, the customer flow, the helper flow, the main screens
and the path from browsing a service to booking help. And here's the prompt that I'm going to be
using. And I want to specify that we want to use image gen. We're going to jump into plan mode and
we're going to run this. And here we have the Flex Help Visual Architecture. And here's a better view.
And so here we have the customer, we have the shared marketplace screens, and we have the helper,
which are the two sides of this marketplace. We also have the convex and the versell here.
On the customer side, we have browse services, get the service detail, and then send a booking
request. The helper side, we have the helper dashboard and the status updates. And on the
shared marketplace screens, we have explore the marketplace, buy bookings, and...
bat, this app is a bit more complex than the previous apps that we were building. And that's
really the goal to finish off with a more complex, but also a more realistic, more production-ready
app. Next, we'll map the core entities. And this is where the product becomes more tangible,
because we can actually see the real objects in the app before Codex starts writing the schema
or code. And here's our prompt. We want to preface this with this image. All right, and here's our
entity architecture. Okay, so we have the user that could be a customer or a helper profile.
We have the booking here, booking status, service, category, review, and all of that
backed with convex data.
So at this point, we have a better idea of how the final app is going to look.
I see that we need a user entity, and that could be a customer or a helper profile.
And I see that booking is super important because everybody needs to have access to
booking, both customers and helpers, booking status, service, category.
And so right away, I see that this is a fairly sophisticated app, but I can see that it's not
a super complex or like a super complicated app that has a ton of different entities,
has lots of things happening. But still, as we are developing this app, we might be adding
various entities. And so that will increase the complexity as the development continues.
Now, the next step is before we start actually building the app is we want to ask Codex to
recommend the simplest stack for FlexHelp based on what we need to build, based on what we've
told it so far. This keeps the technology choices tied to the product instead of starting with tools
first. And this is super important because we want to start with the blueprint before
any code has been written. And here's the prompt to do that. Do not edit any files and spec
everything. And I'm going to be running this in plan mode so that I can decide whether I want to
accept its recommendations or just leave it in the conversation. I'm going to run this here.
This is what it's suggesting. The workspace is currently empty. The simplest course-friendly
stack is React, TypeScript, Convex for backend data, auth, Tailwind for UI, and Resell for hosting.
And this is exactly what we've been doing so far.
And here it's listing some primary routes.
Services, bookings, customer bookings, helper, helper services.
Here we have the data flow, the auth recommendations,
UI and component approach,
verse cell deployment path, stage build plan, everything.
So I'm going to exit out because this was only a read-only plan mode.
I don't want it to do anything just yet
because that's what we're going to be doing in the next step.
Now, from the visual architecture, the entity map, and the stack recommendation,
we have a pretty good idea of how the Flex Help app is evolving.
The next thing that we want to do is we want to get Codex to take a first pass
at turning that plan into a static product UI.
Now, this first version does not need any backend data.
The goal is to see how far Codex can get from the architecture alone to viable UI mockups.
And this is the prompt that I'm going to be using.
Build the first static FlexHelp UI design from the existing architecture and stack direction.
We're going to stay in the plan mode.
I'm going to go ahead and execute that.
And let's see how well it does.
And here's the plan that it came up with.
Okay, the goal is a polished visual prototype that matches the FlexHelp architecture.
Okay, and here it lists some details about the architecture.
And let's go ahead and run this prompt.
So it finished working.
And let's go ahead and see what we have here.
Okay, so this is our app.
And this is kind of how it looks like.
Okay, book practical help.
And we have some active requests.
We have booking entry, helper dashboard.
We have this.
Look at this.
It even works.
Service detail, a small plumbing repair, helper dashboard.
shell. And so this UI doesn't look too bad, but there is something that you need to know when you
design UI with Codex. They all look pretty much the same, or at least very, very similar. And that
is because Codex is not really an expert when it comes to designing pages. It's great for coding,
for solving all kinds of problems, but for actually designing stuff, it's not the most
ideal tool. There are a lot of other tools that do it a lot better. And so during this specific
app build, I want to bring in another tool and show you how we can have a more specialized tool,
actually design the UI, and then bring that UI back into Codex and get Codex to kind of implement
it. Okay. Now, when it comes to UI designs, there's lots of cool tools. There's Google Stitch,
there's Figma, and there's also a tool that I really like to use, and it is called Flutter
Flow Designer. It's a very, very lightweight tool, and it works really great with Codex.
And so if you head over to designer.flutterflow.io, you're going to be on this page here. And you can
use the web app version here, but what I really like to do is I like to use their desktop app,
okay? Here's the desktop app. And what's nice about the desktop app is that you have this
tab integrations. So if you click over here, you can connect designer to external agents and IDE.
So Claude Code, Gemini CLA, and Codex. And so I have this setup. So all you need to do is click
here. Now it's installed. And now this app here is going to serve as an MCP server. Okay. Because
if I go to Codex here and I press command comma, and I go into MCP servers, I also have this
Flutterflow Designer configured here. And if you want to set this up, you can simply ask Codex to
do it. It's going to research, it's going to figure out, and it's going to eventually set it up for you
so that you can have this Flutterflow Designer as one of your MCP servers here. Okay, so now that we
have this set up, what we want to do is we want to go into this Designer, and we want to click on
New Design. And here you can enter a prompt, ask you to design any kind of app UI for you, whether
it is a mobile app or desktop app. They also have, you know, explore styles feature, or you can have
an instant generation. Now, what you don't want to do is you do not want to type this prompt directly.
You want to ask Codex to generate a prompt for you, since it knows a lot more about the app,
that you can input here. And this is the same workflow regardless of whether you're using this
tool, Google Stitch, or pretty much any other tool out there. And so we're going to go ahead and we're
going to grab a prompt to do just that. And here's a prompt that we can use. Create a polished
Waterflow Designer concept for FlexHelp. FlexHelp is a two-sided marketplace, and we are telling it
what kind of screens to design. We give it some design requirements. We give it some guardrails,
stuff like that. And so we're going to input this prompt, and here we're going to stay on
Explore Styles, and that way we can have different styles show up, and we can decide which one we
like better. So I'm going to go ahead and run this. And here are the designs. So as you can see,
they're all very different. We have this, we have this, we have this, we have these ones. So,
and you got to admit that in my view, these look a lot better than what Codex did, right? So this
is what Codex did. In my view, these designs are a lot more interesting than Codex's design. Okay,
So I don't know which one you guys like.
This is a classic.
one you guys like this is a classical one this is nice let's take a look let's go ahead and use this
classical one so i'm gonna say use this style and it's gonna use the sound that is gonna generate
all the pages that we need so here we have seven pages that we need so now we have all the pages
Here we have customer home, we have service details, really nice page, booking request form, customer booking status.
We even have a map, helper dashboard, helper request management, and a user profile.
The next thing that we want to do is we want to tell Codex to fetch these designs and implement them, bake them into our app.
And so let's take a look.
So this is called Flex Help Marketplace, the name of the project here.
And so now what we're going to do is we're going to go back to Codex.
We're going to close out this section here.
And we're going to give it a prompt that's going to ask it to connect to Flutter Flow Designer.
Look at that specific project and grab those designs and bake them into our app right here.
And I have a prompt here to do just that.
So here's the prompt.
Update the FlexSelf Static UI to match the approved Flutter Flow Designer reference.
So this is the main prompt, but we also need to ensure that we tell it that we want to use the Flutterflow Designer MCP.
Use Flutterflow Designer MCP, and then project is, because there are multiple projects, so we want to copy this project here, this.
And we're going to go into plan mode just to make sure that everything is good, and I'm going to run that.
And here it says next, I'm opening a Designer MCP session, and once it does that, you can see, you can actually see the agent working.
This is our agent, our client, because Codex is acting as an MCP client connecting to this MCP
server. And as you can see, it's analyzing this page. And you can see this little Codex icon here.
And you can see it says here, one active agent. It's studying the designs. And then it's going
to pull the designs back here and build an actual UI using those designs. And the goal here is to
ensure that it builds a pixel perfect, or at least as close as possible to what we see here.
Okay, so let's see what it's doing. So now it came back with a plan. Update the existing React
static UI to visually follow the approved Flutter Flow Designer reference. So here it has
five pages, but over here we actually have more. We have seven pages. So I don't know if it missed
it or that it wasn't part of the prompt or some mix-up. So we want to make sure that it captures
all the seven pages. Ensure that it captures all the seven pages from Flutter Flow Designer project.
Okay, and still in the plan mode, just to make sure we get this right, because our app ideally
should have all of these pages. User profile helper, request management helper dashboard,
etc etc all of these make sense okay so it went ahead and it updated it and it's going to add
static page components for all seven pages okay submit this all right so it has implemented the
seven page designer reference update let's go ahead and see how it looks all right so this looks
a lot better in my opinion right we have settings we do have this ch customer home do we even see
that? I don't even see that here. But this customer home service details, click on book. So this menu,
we need to kind of remove this. So let me go ahead and sell it. What are those abbreviations? Let's
see. They need to be there and see what it says. But it looks a lot cleaner than the original UI,
at least to my eyes. And now we're doing a little bit of tweaking, cleanup plan. Okay. They were
placeholder text icons used to mimic the nav icon column. So we need to remove that and we should
probably remove any other placeholder icons. But right now it looks fairly clean. Static preview,
what is that? This also needs to be removed. So we're going to actually tell it, check for any
placeholders and see if you can match what it should be on the design. Pull the design elements
and replace these placeholders with the actual design.
All right, so let's fix it.
Now it looks a lot better.
We still see some other static preview.
That's okay.
Let's see if they go away once we have real data being fed.
So once we're happy with the UI,
we can start designing the backend.
Data model should match the screens
that we actually have here.
And so for FlexHelp,
the first schema should support service browsing,
helper profiles, booking creation,
and helper status updates anything beyond that can wait and here's a prompt that we can use
to connect our app to convex okay we're going to be using convex for this app as well so we have
here connect flex hill ui to live convex service and helper data let's go ahead and keep it in plan
mode all right so this is our plan this is the convex read path plan connect the customer facing
marketplace UI to convex for the first database-backed read path. The repo currently has
no convex setup to add convex from scratch, et cetera, et cetera. And we have convex here running.
We have these three projects, one that was created for the other app that we did. And so we're going
to be creating another project for this app as well. So it has implemented the first convex-backed
read path for the customer marketplace. And these are the files that has changed. This is what's
connected. And if we jump into our Convex dashboard, we can see we have a brand new project here that
wasn't there before. And if we jump here, we should see that we have a deployment here on my
own machine. This is a local deployment that Convex is running on, right? This is not on Convex. It's
on my own machine. And we also have a production, right? So with this deployment here, you go into
data, we can see that we have categories, we have helper profiles, we also have services, and then
we have a bunch of functions, right? Marketplace list, and then we have seed, creating seed data.
Now, if you go into production, we may not see anything there, right? There's nothing there
because we haven't deployed this app to production. There's no need for a production deployment. Now,
if you jump back to Codex and we refresh the app, this is now data that it's pulling from my local
convex deployment. Okay, so we have here Marcus. If we go back here, we should see Marcus, right?
Helper profiles, there's Marcus. And if I change Marcus, if I edit name and I change, let's say,
Marcus, right? And I go back here, now it's automatically Marcus E here. It automatically
updates. If I change that to James, guess what? Now it says James S. So as you can see, this is
now linked to our local Convex instance on my machine. Both of these are on my machine. Now,
the next thing that I want to do is I want to build out the booking flow because that's the key
in this app, right? The ability to book these services. And I have a prompt here as well.
We're going to be using this prompt right here. Okay. Add the customer booking flow to FlexHelp,
inspect all of this, and I'm going to set this to plan mode. And let's go ahead and run that.
That's our plan. We're going to be adding the first customer site booking creation path on top
of the existing convex back service listing. And there's some information there. We're going to
implement this plan. All right. So it has implemented the customer booking creation path.
And it also tested it out. As you can see, there's also a booking here as well. So let's go ahead and
see if this works. All right. So let's say I want to book James. Click over here. So I can't quite
pick anything here, but I can do request to book, send booking request, and I need an
We need autocomplete here as well. Fill in every field. Okay. So task, task. Okay. This I cannot
fill. Every fill. Okay. Customer schedule at 10 a.m. And this obviously needs to be, you know,
like a calendar picker, that kind of thing. Okay. And now we have the booking request. And I can
click on view bookings and I see my bookings. Okay. So this was done by the Codex while it was
testing. So now if we jump into Codex, we should see on my local instance here, we should see
bookings. And we see two bookings. Okay, right here. So the booking flow seems to work. There
are some rough edges here and there that we need to fix. But for the most part, it is coming
together. Now, once customers can create bookings, helpers need a place to see and manage them.
The helper dashboard should show incoming requests and make it obvious what action the helper can
take next. At the simplest level, the helper should be able to accept or decline a request.
After accepting, the helper should be able to move the job into progress and then mark it completed.
Those status changes are what turn the app into a workflow.
This is also a good place to show the power of live data.
When a status changes, the UI should update and the convex row should change.
That gives us a real end-to-end marketplace loop.
Customer request, helper action, back-end stay, and UI update.
And this is the prompt that we're going to be using. Add the helper dashboard workflow for
viewing booking requests and updating booking status. Okay, I'm going to switch into plan mode,
and we're going to go ahead and send this. So it's asking me that how should the helper workflow
handle the existing requested booking status? Keep requested. This is recommended. Preserve
existing created bookings. Show it as pending in the UI or rename to pending. Change the stored
initial status to pending and requires more data. So we don't want any migration. We just want to
go with the easiest option. And then how should the helper request visibility work before auth
is added? Helper selected. This is add a simple static helper switcher filter so each helper sees
bookings for their convex helper profile only. Simplest UI and backend, but less realistic. So
we want helper selected. Okay, we're going to select that. All right, there's the plan. Add the
first helper-facing workflow on top of existing convex booking creation path. We're going to
submit this. Here's our progress. All right, so we just implemented the helper booking status
workflow. These are the files that changed. This is what it did. So it updated it through pending,
accepted, in progress, completed. It viewed it under helper James, created booking this. So it
did all that. It did some tests. Let's go ahead and open it, and let's see what we can do. So this
is the helper booking status. By going to helper dashboard, have my incoming requests, right? So I
can accept it, I can start it, and I can complete it, okay? So that's the piece that is working. I
can also cancel it, and that is canceled, and that's it. I can't come back to it. I can't do
anything. Here we have recent activity, right? Completed, completed, canceled. And this is the
one that did, 148.116. This is the one that it has completed. This seems to work, right? And we have
canceled, we have completed. Even a simple marketplace has different responsibilities.
Customers create booking requests and view their own bookings. Helpers manage requests that belong
to them or are available to them. Admin or system logic may handle category moderation or platform
level controls later. The key point is that these rules should not only live in the UI. Backend
functions need to enforce ownership and permissions because the UI can always be bypassed.
This is where Codex needs to think carefully instead of just adding buttons. And so now what
we want to do is we want to add the roles, auth, and the access boundary layer. And here's the
prompt to do that. Add the first practical roles, auth, and access boundary layer around the existing
FlexHelp workflows. Okay? So we're going to go definitely in the plan mode. We're going to run
this and see what it says. And so it has a question for us. Which identity approach should this plan,
should this step plan for demo sessions add convex back demo users and or convex
or add real convex or sign and sign up more production shape but larger and
currently beta or this clerk use third-party auth provider let's go with
convex or how should customer helper roles be represented for version one
role plus profile so what is this each demo user has customer helper both and
and helpers linked to one helper profile for requests. Separate accounts. Customer and helper
are always separate demo users. Simpler boundaries, but less flexible. And sometimes when I'm not sure,
but I want the system to come up with a really solid answer, this is what I usually type. For
the second question, what's the most durable long-term option? Okay, that's the key here,
durable. And let's see what it says. The most durable long-term option is role plus profile.
Perfect. That's it. And for the first question, choose demo sessions for this course step. Okay,
so let's go ahead with demo sessions. Okay, so do demo sessions and role plus profile. Let's just
go with the recommendations. Expand it. All right, so now you can see that Codex is testing everything,
right? It's testing on the UI in the browser. And you see this cursor right here. The browser
flow now confirms a customer created booking appears for the linked helper and can be moved
into in progress. All right. So it has finished and it has implemented the demo roles and access
boundary layer over here. Okay. So marketplace browsing stays public. Booking creation requires
a customer or both demo user. Customer booking status only shows bookings owned by the signed
in customer. Helper request status updates require a helper or both demo user with a linked helper
profile ID. And so remaining limitation, this is still tutorial demo auth, not production
authentication. Real convex auth or clerk can replace demo session issuance later while keeping
the same role profile access model. And so this should give us some role separation, right? Some
kind of authentication on the backend. And here, if we jump into Convex, you can see we now have
users over here, right? These are the users and there's a role. So you can be either both or you
can be a helper or you can be a customer. And depending on which role you're in, you can do
various operations. Here we have sessions, we have various services, we also have functions that also
handle these roles. So you can list demo users, you can start demo session, viewer, list for helper,
list for customer, etc. And these functions, they are meant to work with specific roles,
so that authentication is baked in into these functions. Now, when something breaks, the wrong
move is to immediately ask Codex to rewrite a whole section. The better move is to give it the
error, ask it to inspect the relevant files, and make it explain the likely cause before changing
anything. That debugging loop is the same whether the problem is a browser error, a build failure,
a convex function error, or a UI state that does not make sense. Observe the issue, diagnose it,
patch it narrowly and verify the fix. And so let's give it a prompt that will deal with this
sort of issue regarding debugging, polish, verification, stuff.
stuff like that. We're going to be using this prompt over here. Debug, polish, and verify the
existing FlexHelp product workflow. Inspect the current app first, then identify the smallest set
of fixes and polish improvements needed to make the current workflow feel credible. Let's jump
into plan mode. Right away, it tells us that I see a few concrete polish fixed candidates already,
and it lists them here. Okay. And so the build passes and both local servers are responding.
So it's using an in-app browser now for a quick workflow probe. So the plan targets actual UI
issues rather than guesses. Okay, so let's wait to see what it finds. And this is the plan that
it came up with. Tighten the existing customer, helper, convex, and demo OAuth workflows without
adding new product scope. Okay, so it lists a bunch of things. And we want to quickly scan
assumptions. No new marketplace features will be added, no payments, nothing. Okay, that stays.
and here are some key changes. You can kind of scan through that. Let's go ahead and submit this.
Right. So it is done and it has implemented the debug polish pass and it actually fixed a lot of
interesting things. It fixed some placeholders. It did some testing. It switched to different
accounts. Actually cleaned up a lot of cool stuff. So if we take a look here, we can see that we can
book. We can request a book. We can describe the task. We can fill all of this out, send,
at the preferred date. And now it's showing in that I'm signed in as the customer, right? And
I can switch a demo user. Now I'm signed in as the helper, and now I'm signed in as both.
Customer access, choose a customer demo user to create a booking request. So it's coming along
really, really nicely. And the final build step is deployment. The app is not done until the front
and is live connected to the intended convex backend and smoke tested through the real product
workflow. So let's go ahead and grab this prompt and let's go ahead and paste it. So deploy the
existing FlexHelp app with Vercel and smoke test the connected convex backend. Okay, we're going to
jump into plan mode so that it can prepare everything, plan everything out. One thing that
I want to tell it that I didn't tell it, and I'm going to do that right now, is I want to make sure
it uses the Vercel package. Choose the Vercel plugin. And I'm going to press Command-Enter
so that it steers the conversation because we want the model to ensure that it catches that,
right? That we want to use the Vercel plugin. Which convex environment should the deployed
Vercel app use for the smoke test? We want to use production. And where should the front end
be deployed? New personal project. Exactly. This is a brand new project. We already have a bunch
of projects, right? So if we go over here, we have this project. Actually, we should have used the
existing project. We already have this project, but I think it's going to create a new project.
Let's see if we can sell it. I'm going to copy that. See if we can use the existing project.
No need to create a new project. And let me check. So this is actually plan mode. So we're okay.
Okay. Implement this. And here it's going to create a production. So if we go over here,
remember we're using this. We also have a production deployment setup. So it's going
to be using the production deployment. So we should see data and tables and functions and all
that good stuff as part of this deployment. Production convex is now seated and responding
with services and demo users. So if we go over here, we have everything now. Look at this.
Sessions, services, we have the data. All right, so it looks like it has deployed it,
and now it's doing a couple of smoke tests to make sure that everything works in production,
because now it's in production and it's also using the production convex deployment, right?
So we need to test things again because, you know, it's using new environments now.
All right, and it is done. Deployed Flex Help. This is the URL. This is the Resolve Project
deployment ID. Everything is live now, okay? And you can access it as well at this URL, okay? So
we have customer home and I am signed in as one of these demo users, customer or helper, right?
I can go into helper dashboard and let's say I go and I sign in as a customer and I go into
customer home, but I can't click here, right? This is helper access, right? Remember the roles,
right? It's being handled here. And so now as a customer, I want to book professional seasonal
garden cleanup. I'm going to book this request to book. I'm going to fill all of this out, 10 a.m.,
two hours, it's fixed, address, send booking. Okay, so we've booking requests submitted,
your request was saved, view my bookings. So we have all of these pending. And so now I'm going
to log in as Marcus. And Marcus is going to go into helper dashboard. And now he sees the booking.
And I'm going to say accept are complete. It's completed. And now if I come back as Anders again,
and I go into customers home, booking request for maybe summary right here, customer booking status.
Okay, there we go. Completed. And here we see completed. This one is completed. Actually,
this one from Marcus, it has been completed. And then there are some more requests here.
So the flow is working. The flow is working perfectly. Of course, there are so many other
things that we can do. We can use real OAuth. We can change the page. We can update things.
But right now, the core of the app works perfectly. And just as a little bonus, when you reach this
stage. There's more things that you can do, but one thing that, you know, right away that you can
ask Codex to do would be something like suggest top five high impact, low effort features,
functionalities. And I'm going to switch into plan mode. And we want to see if there's some
high impact features that we can add that do not require a lot of effort. And here they are,
top five high impact, low effort next features I'd prioritize. Functional marketplace search,
booking detail view, customer cancel pending request, et cetera, et cetera. And if you don't
want to implement these right now, what I'd like to do is save this list as dots to do MD as a
markdown file and prioritize each item on a scale of one to five, one being urgent. And so that way
I have a constantly evolving list of things that I can build in the future.
So I do not need to ask Codex all the time, constantly, you know, to suggest new features.
And I'm going to say submit, and that's going to go create this docs directory as well.
And this to do MD, which is the file that I usually keep to store new features.
And now we can open this file and take a look.
So this is priority one, two, three, four, five.
So now we have an app that is live, that is on the internet, that we have built, that works.
This workflow, this main workflow works as expected.
But of course, there's so many things that you can do to improve this app.
And in some of the later videos, I'm going to be showing you some more advanced Codex techniques
that you can use to make your apps even better and more robust.
because I've been using Codex for a while now, and I have some advanced tips and tricks that
I'd like to share you in some of the future videos. And so I really hope that you enjoyed
this mega Codex tutorial. Now, if you want to go ahead and build this app or modify this app or
whatnot, I'm going to be leaving all my prompts, every single prompt that I use to build this app
inside of our amazing Patreon community. And you can check it out and hopefully join. There are
lots of great people there. And of course, support this channel and support my work. And so
like this video, leave a comment, and check out our amazing Patreon community.