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 contexts 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
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 might 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 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, etc. And then
I have this interaction here, right? It
does something, I ask it to do something
else, etc., etc. Now, just below that is
where you're going to be entering your
prompt, okay? So, you're going to be
selecting the model,
uh 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,
okay? And a lot of people are not really
like using it. And 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,
right? 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, you
know, of your conversation, okay? So, if
you've created a 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,
right? 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 Coda for work threads. So, my
project context stays focused and clean.
There are two main ways to use Coda. 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, Coda 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 lives.
The file change view shows what Coda
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 Coda feel
less like a chat bot and more like a
working development environment.
Permission flow is also important.
Cortex should never feel like a black
box that silently changes 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
Cortex 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. 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, back-end 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 Cortex 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 Cortex 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 Cortex 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
contacts window here, right? Here you
can see how much of the context you have
used. Now, Korax says that it
automatically compacts its contacts. 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, okay? Next, we have here the
all-important model selector, okay? 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, okay? 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 1 and 1/2 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 or let me sleep on it." Or let me
think it over, right? The longer you
think, the more the more you figure
something out, and the the the the 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
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, and 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 Chat GPT
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 on quick coding tasks. We
have the gold 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 bucks a
month, and here you can finally start to
actually do something meaningful, right?
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 pro plan 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 Codex
for all kinds of tasks, and still not
reach limits. And so, during the time
where I'm when I'm, you know, building
heavy apps and and doing some serious
work, I might 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 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
people that work on very heavy projects
and, you know, there 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 a
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
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. All right, then this is
what we got back. As of this day,
ChatGPT plan is that include Codex,
okay? So this is the practical read.
Free, try Codex on quick tasks. Go
lightweight coding tasks. Plus a few
focus 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 Codex 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, ChatGPT 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, 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 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 convo 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 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 arch 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. So, 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 app architecture, right? So, we
want it to be a 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 sample arch stack under
wherever it's storing those skills. The
skill will guide Codex 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 created the skill app.
It contains skill.md and then
agents.for.openai.yaml.
Validation passed, etc. etc. 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, etc.
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
packaged 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 and
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 might 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 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,
etc., etc., 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 Codex an ability to to
connect to external systems, right? It's
kind of this higher-level structure,
okay? Whereas a 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 the skill right
here, right? This is 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, you know, use this Notion
spec to do this, or to do that, or, you
know, 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
Codex. That's kind of the purpose of a
skill, to make something an extension of
Codex. Right? And that's the main idea
with all of this, right? Another really
cool one is, like, for instance, Google
Calendar is another one, right? 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, right?
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 to Vercel and read their docs and
understand how to deploy and all of
that. I simply install this skill and
then I you know, I click here and now I
can say, you know, Vercel, order this
repo for Vercel deployment risk. Or
Vercel, which Vercel tools fit fit this
app app best. Or Vercel, deploy 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
ton a ton of skills. Vercel CLI, Vercel
agent, all of these. And obviously,
these skills are not just for deploying,
right? Because we also have payments. We
have best practices. We have all of
these other ones. So, these skills
essentially map to different parts of
Vercel, to different features of Vercel.
We're not just talking about, you know,
deploying your app, because this could
be just a skill, deployment, right? This
could be one skill that I may need. I I
may not need all of these other skills.
But why not? You know, Codex will figure
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
said, this allows me to basically bring
Vercel into my Codex workflow. That's
the beauty of these plugins, okay? 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, etc., etc. 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:00 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:00 a.m.
running this prompt. And And remember,
this is a special prompt. Here, you're
asking it to consult Git activity. And
so, the idea is you may have, you know,
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:00 a.m.,
right? So, instead of you needing to,
you know, jump into Codox 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:00 a.m.,
right? Scan recent commits since the
last run or last 24 hours for likely
bugs and propose minimal fixes. Okay,
that's another very, very useful
automation, right? Repo maintenance. You
have here growth and exploration, right?
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 1,000 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 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:00 or 10:00 a.m., okay? And
so, automations are very, very useful if
you need some kind of a repeatable
structure in your workflows. 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, Flow Upload Designer,
Flow Base, 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 going to 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, you know, 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 contacts 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 Supabase MCP server." 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 Supabase 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 Supabase instance in this example
via the configured MCP 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 focused change, verify the
result, and then report back in a way
that you can re-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-specified 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, scoped, 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 back-end 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 one. 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 cuz 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. We
never
the last thing that we want is for Codex
to assume something. We never want it to
assume anything. We always want to make
sure that we are on the same page. And
so, let's say I have a command over here
going, and I want to build an
architecture. I want to build some kind
of a an intricate architecture.
And, you know, I 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. So, 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. Okay? 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. You
share TypeScript domain logic with
separate Expo mobile, etc. 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 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 can work offline and
sync across devices. Cloud only, simpler
shared back and 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 a 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 question here
again. And here are the questions. I'm
going to say this, and now I want to say
this because I I I understood what it
was asking me. Got it. Your choices are
that means the architecture should
prioritize a shared TypeScript app a
brand 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 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 to 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. And there are two
main reasons that you may want to do
that. The first reason is that after a
while, this conversation here, this 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 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. 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
handoff 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's 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 that are not working
and where you are right now and telling
the model as part of that handoff prompt
to work on a different solution. And
because AI is is can be fairly random in
some ways, creating a new conversation
usually give 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 what answer we
get. Right. 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 you
don't 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. 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 handoff 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 detailed this handoff versus this
handoff right here. Now, this handoff
would definitely work, but this handoff
would work even better. 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.
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,
you know, bigger teams, I do not know
who was the person responsible for the
change. Now, in this convo, we have
another problem, okay? The current
working directory is missing. And 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
enabled 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 telling 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 I
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.
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 You don't really
need to store them in Git. These could
be like media files, or generated files,
code generated files that that can
always be regenerated. But for your
actual code, you always want to be
tracking them, right? So, we we have
this commit, and now this files 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 the
a type of branch. And so, now if we go
into changes, you can see that we can
select a 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 we
type give me Git status, it's going to
tell you that it's not It hasn't been
committed, right? It's modified, and
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 click select
review, and you can select the the 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, okay? Because we are
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,
right? 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 work trees. A work tree 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, new eye
direction, or refactor somewhere else.
This matters a lot with the genetic
coding. If you want to try two
approaches in parallel, or or keep a
clean version ready for recording while
another code expert keeps building, a
work tree gives you that separation.
Now, what's nice about work trees is
that they give you parallelism. So, if
you are working on multiple features in
your app, maybe you're using sub agents
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
worktree 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 worktree, 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 Codox to work in main without
creating any worktrees, or I can ask it
to create a new worktree 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, plan." But this time, we
want to make sure that it works in a
different worktree. So, what I'm going
to do is I'm going to say, "Work in a
new worktree, and then merge, clean up
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 worktree, commit there, fast forward
merge changes to main, and then remove
the worktree and delete the branch. And
that's exactly what it did, except it
did it very, very quickly because this
was a, 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 worktree, 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 don't need to constantly tell
Cortex, "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 merge. 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 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.
An agent explores the code base, another
works on a clearly bounded part of the
UI, another checks tests, or reviews the
result. 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
codebases, 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. create new tasks, etc., etc. 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 sub-agents to help me kind of
make sense of it, you know, 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 sub-agents, right? Do not
edit files yet. Recommend. We're going
to jump into plan mode. Preface this
with the feature. Add to party apps,
such as make.com, Zapier, etc. And so,
I'm going to 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.
Sub-agents 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
sub-agent delegation. Integration
settings, integration data model, web
hook event dispatcher. So, I'm going to
copy this plan, and then I'm going to
preface it by telling it spawn
sub-agents 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
sub-agents and keep the main thread
responsible for the final." So, as you
can see, it's spawning them. And each
sub-agent gets a prompt. It's basically
like me creating a new conversation.
Your sub agent one integration, your sub
agent two integration data model, your
sub agent 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 combo here,
and tell it what happened, right? They
come back with the 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 respond,
and 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 agent 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 or
sub agents. 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, sub-agents, 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
codex should use a work tree. Use a
separate work tree when these happen.
When codex should use sub-agents. Use
sub-agents when work can be split into
clearly separate ownership areas such as
these. What codex 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, you know, asking codex to spawn
sub-agents 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 You can click here, and
you can see the whole file right here.
And this file 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 sub-agents, but if it's a
more complex change, it should probably
create a work tree and maybe even spawn
sub-agents. So let's go ahead and see if
this works. So now, let's go ahead and
ask it make a simple change that 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, like, 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
sub-agents 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.mdx
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
sub-agents. Another question, should the
new backend become the source of truth
for Kanban tasks? Yes, let's just go
with the 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 sub-agents for any of these
things. Okay, so I do not see it's going
to be using sub-agents. Update. So
before we run it, let's ask it, do you
plan on using a work tree or 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 subagents, 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
subagents, 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.env 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 Codex 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 Open Router.
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. 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 OpenAI, 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 OpenAI 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 open router 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 PK is private and must stay
server-side. It is used here, needed
locally. Hosted service config or cell
or another node capable host config as a
private server environment variables,
port, etc., etc. Okay, dot env examples
cuz currently untracked. So, what we
have safest next step before deploying,
replace it with only this. Only config
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 it. 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
untracked. 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 env example with create dot
env. Okay, so it's it's going to be
creating this dot env. The secret is now
ignored in dot env. And then I'm
updating readme and agents to make the
local and Vercel 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 on 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 the secret key management and not
just secret key, any kind of key
management is part of our workflow and
we can be assured that we have the key
for local stuff and we also going to be
deploying the key correctly for
production stuff, regardless what kind
of host you're using.
Now, when you're developing an app,
you're going 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.
Oh, 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 env run command. So,
we have this relevant install
dependency. 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 proceeding, right? API
behavior, OpenAI calls, front end, etc.,
etc. 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 then ensure that Codex
knows about it by making this a part of
your agent's MD or a separate step.
Now that the Cortex foundation is clear,
we are going to start with something
intentionally small. The first step is
called Habit Card. And it is a tiny
habit tracker where users can add
habits, check them off 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.
Cortex 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 back end complexity. Habit
Card 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 Cortex loop on something we can
understand immediately. Now, here in
Cortex, 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 demos. 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 as well as Chat
GPT to do it. So, I'm going to press
forward slash, and I'm going to search
for Imagen. Okay, and then we can say
something like use Imagen for the
following. And I'm going to go jump into
plan mode, and I'm going to go ahead and
and execute it. 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 there's
some diagram content, visual direction.
That'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 Versel 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 Versel 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 streak 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
ImageGen for below. 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 a
an ambiguous coding instruction. And
here is our entity architecture. And
unlike the visual architecture that
we've 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
back end. So, no back end, everything is
stored locally with local storage. And
this is also very, very useful because
unlike the visual diagram here, I want
to see the actual schema. I want to see
what kind of, you know, elements or what
kind of, you know, 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 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 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 Habit Card, right? And we ask it
what 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
need it 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 the testing library. No
React Router. It's a simple single
screen app. No global state library.
Okay? Back end decision. No back end is
needed for the first version, right? And
that's what we told it. We said 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 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 add 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 and go to the
server that's running our app. So let's
do that. 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 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 it's
creating these 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
and 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 me. 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
Supabase 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
back-end, so that no matter which
browser I use, it will still store the
data and keep track of everything. That
is not happening. Once the app works
locally, it's time to deploy it. Even
though Habit Card 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
front-end, 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 Habit Card
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
Vercel 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. Okay, Habit
Card is already a suitable for a
front-end only for sale deployment,
okay? 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
back-end APIs or 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. And 3
minutes later, it tells us that deployed
Habit Card to Vercel and verified it
live, okay? So, this is the live URL. We
can click here, and that's going to open
our Habit Card 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
back-end, 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,
back-end, 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. Snack Vote 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 back end pattern
on a much smaller app. Snack Vote 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 back end
data without making the product itself
hard to follow. As always, in this first
step, we'll be mapping the Snack Vote
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 to
preface that we want to use this image,
and we're going to jump into plan mode
and execute this. And 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. 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 can You
have here a snack list. You have your
your voting buttons.
You have a live leaderboard, and you
have a closed winner state. Okay, 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 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 it to
Convex. Later, Convex is going to be our
backend, and we are going to be
leveraging things like real-time
updates, persistence, and live vote
counts. And 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 Snack
Poll. 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 backend later Convex with
TypeScript server functions and
generated client types. And so, for the
most part, uh 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 back end 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 Snack Vote UI without
a database or persistence, okay? Inspect
the current project first, then build
the smallest useful Snack Vote 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 winning.
Winner state, current winner leader,
spicy ramen bowls. And so, if I vote on
falafel wraps, uh 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. 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 that are not familiar,
Convex is a back end that we're going to
be using in this tutorial. It's an
awesome back end, 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 back
product. And the path is very very
simple. Code X 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 in to my free account. I'm using
the free plan. I'm not paying for
anything. And this is also an
open-source back end, 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 Votes to 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're 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, okay? Convex is
installed locally now, okay? 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.
Okay, so now we can paste the prompt.
Upgrade snack votes so snack options 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 set of
choices to open. There's 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 snack vote 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
snack options 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. This snack
was submitted through the browser and
appeared from Convex. I'm voting on it.
There is this testing all the flows,
which is pretty cool. All right, now
it's telling us implemented the Convex
back snack vote upgrade, changed all of
this, what changed, verification, edge
cases handled, and it is running. So, we
can test it out 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 the snack tools, 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 back end to a
Convex back end very, very quickly. Now
that snack vote has real Convex data, we
can make it feel more like a shared
group app. Instead of one global
snackboard, 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 state. This keeps the app
more interesting while teaching a clean
back-end 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 Convex back app from
one global snackboard to simple rooms.
Can I expand that? Yes, implement that.
Now, 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 vote. 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 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 launch 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 that 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, it's the same
pre-functions. But for voting room, we
have get, create, or join, bunch of
other functions that we have. And And so
it pretty much did everything. It
created the functions, it created the
schema, it even, you know, created some
test data while it was testing. 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 snack votes, 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 rule.
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's 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 is 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 that room and I have my burrito.
So, I'm going to 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 room 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 it's it's uh
reactive. I'm going to hit vote.
And now you see room ID
and session ID. These two, if they can
only appear once in this table. And so,
obviously now it's 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 so 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 I
change my vote. Yes, I can switch votes,
but I cannot pad, you know, 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
minutes, 15 minutes when creating
opening a room, date time 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, 1 minute, 5 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 a room, Friday lunch, and let's
say it's 5 minutes. Select 5 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
Let's 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 created tried
creating a room and selecting a
deadline, but it ended up creating
a room with no deadline. And we don't
really need plan mode for this. There's
no, you know, clarifying questions here.
It's a simple bug. And we don't really
want it to clarify. We we know what the
bug is. We just want it 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 want it 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 uh 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. And now it understands it.
You see, now it's correct. Fixed 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, etc. 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 1 minute room one, 1 minute. There
we go. 1 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 back-end environment. And this
will round up this specific app build.
And here's our prompt, prepare SnackVote
for deployment on Vercel
and verify it works with the Convex
back-end, 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, so we we are currently under
development deployment, under
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 want it 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. And this is our plan
prepare snack vote for a production
result 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 snack vote 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. Okay, 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, right? 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, 1 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 is running. So, for
local deployment, we have the local, the
dev convex deployment, and for the
production Vercel 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 fixers
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 the design, and build the UI,
then add feature by 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. FlexHelp.
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 ImageGen. 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 Versel 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, my bookings, and booking
details. So right off the 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 for code. And here's
our prompt. We want to preface this with
this ImageGen. 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 you know 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 can 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. 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,
off, Tailwind for UI, and Vercel for
hosting. Okay, and this is exactly what
we've been doing so far. And 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, Vercel
deployment path, staged build plan,
everything. Okay? So, I'm going to exit
out because this was only a read-only
plan mode. Okay? 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 FlexHelp 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 back-end data.
The goal is to see how far Codex can get
from the architecture alone to viable UI
mock-ups. 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. 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's 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
FlutterFlow 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 app integrations. So, if you click
over here, you can connect designer to
external agents and IDEs. So, Claude
Code, Gemini CLI, and Codex. And so, I
have this set up. 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 a new design, and here you
can enter a prompt ask it 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 Stage, 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 FlutterFlow 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 give
it some guardrails, stuff like that. And
so, we're going to input this prompt,
and here we're going to stay on the
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
classical one. This is nice. Let's take
a look. Let's go ahead and use this
classical one. So, I'm going to say use
this style, and it's going to use this
style, and then it's going to 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 FlexHelp 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 FlutterFlow designer, look at
that specific project and grab those
designs and then bake them into our app
right here. And I have a prompt here to
do just that. So, here's the prompt.
Update the Flex sub static UI to match
the approved FlutterFlow 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. 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 cuz Codex is
acting as an MCP client connecting to
this MCP server. And as you can see,
it's 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 FlutterFlow
Designer reference. So, here it's it has
five pages, but over here we actually
have more. We have seven pages. So, I
don't know if I if it missed it or that
I did not it was 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 FlutterFlow Designer
project. Okay? And still in the plan
mode just to make sure we get this right
because our app ideally should 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. All right, we
have settings. We do have the 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. Do they need to be there? Let's see
what it says. But it looks a lot cleaner
than than the original UI, at least to
my eyes. And now we're doing a little
bit of tweaking, clean-up 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 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
pull the design elements and re-replace
these placeholders with with the actual
design. All right, so it has fixed 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 to
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
let's help 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 back
read path. The repo currently has no
Convex setup. So, add Convex from from
scratch, etc., etc. 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. All right, so it has
implemented the first Convex back 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 we 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 you 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.
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-side 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 address. Okay, so let's
say do, I don't know. We need
auto-complete here as well. Fill in
every field. Okay. Okay, so task, task.
Okay, this I cannot fill every field.
Okay, customer, schedule, say 10:00 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 state, 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 require a
small 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 back end, 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 pack.
We're going to submit this. Here is our
progress. All right, so he just
implemented the helper booking status
workflow. And 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. I'm 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 alteration or platform level
controls later. The key point is that
these rules should not only live in the
UI. Back-end 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 off and the access boundary layer.
And here's the prompt to do that. Add
the first practical roles off and access
boundary layer around the existing flex
help 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
for Convex or add real Convex or sign
and sign up more production shape but
larger and currently beta or this clerk
use third-party or provider. Let's go
with Convex or how should customer
helper roles be represented for or
version one? Role plus profile. So what
is this? Each demo user has customer
helper both and helpers linked to one
helper profile for request. 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. Now 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 the for this core
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 book
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 ID 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
uh 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 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., etc. And these
functions, they are meant to work with
specific roles, right? So, that
authentic- -ation is 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 like that.
We're going to be using this prompt over
here. Debug, polish, and verify the
existing flex help product workflow.
Inspect the current app first, then
identify this is 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 fix candidates already and it
lists some 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 app 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's
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 task. 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, add 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 end
is live, connected to the intended
Convex back end, 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 Flex 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.
Use the Vercel 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 tell 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 set up. 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
seeded and responding with services and
demo users. So, if you go over here, we
have everything now. Look at this.
Sessions, services. We have the data.
All right, so 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
FlexHelp. This is the URL. This is the
Vercel 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'm signed in as one
of these demo users, customer or helper,
right? I can go into helper dashboard,
and let's say I go 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 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:00 a.m., 2 hours, it's fixed
address, send booking. Okay, so with
booking request 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 or complete, it's
completed. Now, if I come back as Anders
again, and I go into customer's 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, for Marcus, it has
been completed. And then there's 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
auth, 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 is some high amp 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 prioritize. Functional
marketplace search, booking detail view,
customer cancel pending requests, etc.,
etc. And if you don't want to implement
these right now, what I like to do is
save this list as dots.todo.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, you know, to to
suggest new features. And I'm going to
say submit and that's going to go create
this dots directory as well and this
todo.md, which is the file that I
usually keep to store new features. And
now we can open this file and say,
"Codex, so this is priority one, two,
three, four, five." So now we have a 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 used 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.