00:00:00
b.u helps you build fullstack apps in
00:00:02
the browser today's video I'm going to
00:00:04
dive into the code behind it and show
00:00:05
you how they make this magic happen here
00:00:07
you can see it's already running I've
00:00:09
asked it to build me a remotion app so
00:00:11
it's doing an mpm install npm start this
00:00:13
is all running in the browser so you can
00:00:15
also run no JS code and front end code
00:00:17
and look what we have over here this has
00:00:19
already gone and built it with
00:00:20
JavaScript code that's amazing a lot of
00:00:23
videos will show you what you can do
00:00:24
with b and I am going to do that today
00:00:25
but really the core of this video is
00:00:27
diving into the code behind the project
00:00:29
the code for this project is open source
00:00:31
it's available on GitHub so I'm going to
00:00:32
dive in and show you how it really works
00:00:34
behind the scenes we're going to learn
00:00:36
about the technology that makes this
00:00:37
happen called Web container we're going
00:00:39
to learn about xterm to run a terminal
00:00:41
in the browser and we're also going to
00:00:43
dive into the AI prompts behind it last
00:00:45
week I dived into the code behind a
00:00:46
similar project called sourcebook it's
00:00:48
an open source self-hosted AI powered
00:00:50
app builder now Source book is very cool
00:00:53
and how it works is it will actually
00:00:54
save the files to disk on your own
00:00:56
computer and run them like Thea node so
00:00:58
you have to have node installed on your
00:01:00
computer for it to work Bol is really
00:01:02
cool in that it actually runs fully in
00:01:04
the browser it doesn't care what's on my
00:01:05
computer it's not installing anything
00:01:07
and the video before I actually did on
00:01:08
triggerd which is also worth a look and
00:01:10
that's interesting because it's an open
00:01:12
source background job platform and there
00:01:14
as well they have to run code on your
00:01:16
behalf so here is the TS code they would
00:01:17
have to run on your behalf on their
00:01:19
servers so across these three videos
00:01:21
you're seeing three different approaches
00:01:22
from different teams as to how to run
00:01:24
code for users on their behalf all three
00:01:27
projects are open source so take a look
00:01:28
at the links in the description below
00:01:30
and subscribe if you want to see more
00:01:32
open source projects like this and how
00:01:33
they're built lastly I'm working on
00:01:35
inbox zero which is an open source email
00:01:37
app it helps you manage your email more
00:01:39
efficiently with AI it's got over 9,000
00:01:41
people using it and it's fully open
00:01:42
source as well love your support by
00:01:44
giving it a star on GitHub I'm going to
00:01:46
show you a bit more using bols here you
00:01:48
can see I've done another prompt do a
00:01:49
car video and it's gone and added this
00:01:51
car to the video and I've also asked it
00:01:54
to go and add a plane as well so you can
00:01:56
see all the steps it's taken over here
00:01:58
it's added a plane a road a car and it's
00:02:00
really cool it just did this all on its
00:02:02
own immediately if I want to dive into
00:02:04
the code behind it here you'll see this
00:02:05
is the plane this is just react code
00:02:08
it's using in the library here is
00:02:09
remotion all running in the browser it's
00:02:11
amazing and again we're using the
00:02:13
remotion for the car and for the road
00:02:15
and that's what it came up with you'll
00:02:17
also notice over here I have a terminal
00:02:19
running at the bottom of my screen so
00:02:21
it's done mpm install mpm start all
00:02:23
running in the browser this uses xterm
00:02:25
that we'll see shortly this editor over
00:02:27
here is using Code mirror and I can even
00:02:29
get it to deploy I could type deploy
00:02:31
here or I could deploy here to netlify
00:02:34
so let's dive into the code behind it
00:02:35
it's all available on GitHub at stack
00:02:38
blitz. new and over here I've cloned it
00:02:41
to my own computer the app itself it
00:02:44
uses V we're also using Uno for the CSS
00:02:47
this is what an UNO config looks like I
00:02:49
actually haven't used it myself but it's
00:02:51
a similar idea to tailwind and at least
00:02:53
back in 2021 you can see in this article
00:02:56
how quick Uno really is Tailwind CSS
00:02:59
version three took 1 second to do a
00:03:01
tsare and it took Uno only 13
00:03:03
milliseconds which is insane I
00:03:05
personally don't plan on moving away
00:03:06
from Tailwind it works really well with
00:03:09
so many things in the ecosystem but I
00:03:11
think you can get Uno to work with
00:03:12
Tailwind very well and then like
00:03:14
libraries like Shaden as well so I
00:03:16
haven't tried that but at the end of the
00:03:17
day if it supports the same CSS classes
00:03:19
it should be fairly compatible with
00:03:21
other libraries out there so jumping
00:03:24
into the app we actually using remix for
00:03:26
this the app isn't actually super big
00:03:28
you'll see there aren't that many any
00:03:30
API endpoints if you're familiar with
00:03:32
nextjs or in remix it works a little
00:03:34
different this would be at API chat as
00:03:37
we'll see later some important pieces we
00:03:39
have these stores so we have Nano stores
00:03:42
Nano stores is a tiny State manager for
00:03:44
react re native preact and so on and
00:03:47
vanilla JavaScript it's small it's fast
00:03:49
tree shakable good types Script support
00:03:51
and it looks something like this if
00:03:52
you're familiar with J your zand or
00:03:55
other libraries so you'll see some
00:03:57
similar ideas here but this is used
00:03:58
throughout the app used store and these
00:04:00
atoms you can see a chat store is being
00:04:03
created or a file store over here and it
00:04:05
can be used with use store so let's dive
00:04:07
straight into things I can see over here
00:04:09
I want to know what happens when I start
00:04:11
typing some text here and I hit enter
00:04:12
this is going to send the message to the
00:04:14
server or do some action so let's take a
00:04:16
look at where this comes up in the app
00:04:18
if I search for in the app I'll see uh
00:04:20
how can Bol help you today it comes up
00:04:22
over here which is great and I can see
00:04:24
when I do on key down on enter that's
00:04:26
basically what I want that I'm doing a
00:04:28
send message so let's see see how that
00:04:30
works go to base chat and that's used
00:04:32
over here which eventually brings us to
00:04:35
this part here you can see the workbench
00:04:37
store this is one of those stores that I
00:04:39
mentioned again using Nano store so the
00:04:41
entire State for the app is stored in
00:04:43
lots of little nanostore atoms and then
00:04:46
the important part is where we actually
00:04:48
call a pen this is the action and what's
00:04:50
that calling that's from use chat and
00:04:52
this is from the versel AI Library you
00:04:55
can see up here AI react so what this
00:04:58
goes and does is it's going to go and
00:05:00
send a call to our server over here API
00:05:03
chat here's a bit of documentation about
00:05:05
uh the AIS SDK by the way so you can see
00:05:07
we're just importing AI react just like
00:05:09
we've done ourselves we're doing use
00:05:11
chat and then over here you can see the
00:05:12
messages that come back so we're just
00:05:14
looping through them and showing them on
00:05:16
screen and when we do submit we're
00:05:18
calling handle input change so in our
00:05:21
case we did a pen to add messages but
00:05:22
over here we're just um using handle
00:05:24
input change and that basically sends it
00:05:26
back to the server and the server will
00:05:28
call the AIS needs and then it will
00:05:30
stream back responses and it will just
00:05:32
appear here in messages this is what the
00:05:34
back end might look like for it you can
00:05:35
see we're calling open AI a post request
00:05:38
and we're just streaming text back so
00:05:41
very simple to use and that's exactly
00:05:43
what's happening over here so let's take
00:05:44
a look at this endpoint API chat this is
00:05:47
using in action this is how things work
00:05:49
in remix but that's basically the
00:05:51
equivalent of doing a post in nextjs you
00:05:53
can see the action so we get the
00:05:55
messages in these are the messages that
00:05:57
the user has already sent at the
00:05:58
beginning it's just going going to be
00:05:59
one message and we have some streaming
00:06:01
options but the important part is that
00:06:03
we're going to start streaming some text
00:06:05
using Ai and then over here you can see
00:06:07
we have the response which is stream.
00:06:09
readable so it's going to stream the
00:06:11
results back for us so let's go into
00:06:14
stream text and you can see this is
00:06:16
basically just calling stream text which
00:06:18
is being renamed it's stream text from
00:06:19
the AI Library again which is exactly
00:06:22
what we saw over here in this simple
00:06:23
example and so we're getting the model
00:06:25
the system prompt this is important this
00:06:27
is basically where all the logic is
00:06:28
happening right now now and we're
00:06:30
passing in the messages you can actually
00:06:32
just do it like this I made a PR to
00:06:34
update that today as well but this is
00:06:36
part of the old AI SDK code you don't
00:06:38
actually need to do this anymore to
00:06:40
convert message formats the anthropic
00:06:42
model we're just calling it from AIS SDK
00:06:44
another PR I made was to update this to
00:06:46
the L latest version of Sonet we'll see
00:06:48
if they accept my PRS and then get
00:06:50
system prompt is really what is
00:06:52
important so this is the prompt that
00:06:54
we're sending to the AI well this is a
00:06:56
system prompt we're also sending the
00:06:58
user messages of course and you can see
00:07:00
it's a few hundred lines here I do want
00:07:01
to go through this a little bit if
00:07:03
you're building your own llm app so this
00:07:06
could definitely give you some good
00:07:07
ideas so you are bolt an expert AI
00:07:10
assistant an exceptional senior software
00:07:12
developer with vast of knowledge across
00:07:14
multiple programming languages
00:07:15
Frameworks and best practices so here
00:07:18
you can start to see we've got these XML
00:07:20
blocks which is the recommended way to
00:07:22
do things with anthropic is basically
00:07:23
splitting up the prompt into like lots
00:07:25
of different sections and the llm can
00:07:27
understand that very well so here are
00:07:30
some system constraints remember this is
00:07:32
all part of the overall system prompt
00:07:33
but within the system prompt we also
00:07:35
have system constraints you're operating
00:07:37
in an environment called Web container
00:07:39
an in browser no JS runtime that
00:07:41
emulates a Linux system to some degree
00:07:43
and by the way this prompt is really
00:07:45
good because it actually explains to us
00:07:46
how the project Works itself we're
00:07:48
explaining it to the AI but it also
00:07:49
helps us understand what's actually
00:07:51
going on it's sort of like a Rey for us
00:07:54
so however it runs in the browser and
00:07:56
doesn't run a full-fledged Linux system
00:07:58
and doesn't rely on cloud VM to execute
00:08:00
codee all code is executed in the
00:08:02
browser that's super cool and I'm going
00:08:04
to show you web container as well in a
00:08:06
minute or two it does come with a shell
00:08:09
that emulates the is the shell there is
00:08:11
called jsh Gish I guess the container
00:08:14
cannot run native binaries since those
00:08:16
cannot be executed in the browser that
00:08:18
means it can only execute code that is
00:08:20
native to a browser including JavaScript
00:08:23
web assembly and so on the shell comes
00:08:25
with python and Python 3 binaries but
00:08:27
they are limited to the python standard
00:08:29
Library
00:08:29
only additionally there is no g++ or any
00:08:33
C or C++ compiler available web
00:08:35
container has the ability to run a web
00:08:37
server but requires to use an mpm
00:08:39
package so for example V or server or
00:08:42
serve HTTP server or use the nodejs apis
00:08:45
to implement a web server now we say but
00:08:48
prefer using vit instead of implementing
00:08:50
something yourself uh git is not
00:08:52
available for writing no JS scripts
00:08:54
instead of shell scripts as the
00:08:56
environment doesn't fully support shell
00:08:58
scripts so use no JS for scripting tasks
00:09:00
whenever possible when choosing
00:09:02
databases or npm packages prefer options
00:09:04
that don't rely on Native binaries for
00:09:06
databases prefer lib SQL sqlite or other
00:09:09
solutions that don't involve native code
00:09:11
web container cannot execute arbitrary
00:09:13
native binaries but that is super cool
00:09:16
because you can Rite a sqlite database
00:09:19
in your browser you can use drizzle for
00:09:22
that I'll actually show you an example
00:09:24
here is an example of running drizzle in
00:09:26
the browser so you can see we've run the
00:09:27
migration script over here inserted Ono
00:09:30
this is part of Stack Blitz but stack
00:09:32
Blitz is a team that created bolt. new
00:09:34
so like I'm sure a lot of the underlying
00:09:36
code is basically exact same definitely
00:09:38
using web container here as well here
00:09:40
you can see the table we've created and
00:09:42
we're running this migration and so on
00:09:44
and here you can see we've log the
00:09:45
results after doing query users. menu so
00:09:48
that's extremely powerful that that runs
00:09:50
in the browser and that's what our AI is
00:09:52
dealing with basically these are the
00:09:53
available sh commands cat CP Echo host
00:09:56
name and so on so that's all about the
00:09:58
system constraints where working in now
00:10:00
code formatting info use two spaces for
00:10:03
code indentation I hope the AI isn't
00:10:05
offended by this doesn't start to argue
00:10:07
and says it prefers tabs instead of
00:10:09
spaces but you can make the output
00:10:11
pretty by using only the following
00:10:12
available HTML elements so here are some
00:10:15
HTML elements it can use a and H2 and so
00:10:18
on so that means when it's streaming the
00:10:20
text response to us the message it can
00:10:22
create it can use those tags like if it
00:10:24
wants to show us a header for example
00:10:25
now diff spec this is telling us how the
00:10:27
diffs work so for user made file
00:10:30
modifications a modifications tag name
00:10:33
section will appear at the store of the
00:10:35
user message it will contain either diff
00:10:37
or file elements for each modified file
00:10:40
so if we get this tag basically a diff
00:10:42
tag like this it will contain a new
00:10:45
UniFi diff format changes and if we have
00:10:47
a file then it will contain the full new
00:10:49
content of the file so what that means
00:10:52
is if I just jump into our let's say
00:10:53
hello world example and go here for
00:10:56
hello world if I start to type over here
00:10:58
so now when I send the message back to
00:11:00
the server it's going to give this back
00:11:02
as a diff but if I go and do a whole new
00:11:05
file so it's going to pass the whole
00:11:07
file to the server and it's going to be
00:11:09
within these file tags the system
00:11:11
chooses file tags if the diff exceeds
00:11:13
the new content size otherwise diff and
00:11:17
basically this is what a diff section
00:11:19
would be and this is what a file section
00:11:20
would be so this is like a get diff so
00:11:23
here you can see we've removed this line
00:11:25
console.log hello world and in place
00:11:27
instead we've replaced it with hello
00:11:28
Bolt
00:11:29
you can see we've added this line and
00:11:31
we've also added this to the end of it
00:11:34
and how this works is basically um you
00:11:36
got at at at at at like sort of the
00:11:39
start and the end and then we have like
00:11:40
minus X so X is the original file
00:11:42
starting line a modified file starting
00:11:45
line so in this example it's two and two
00:11:47
we're just replacing code in the same
00:11:49
place basically the original file line
00:11:51
count so over here we basically have
00:11:53
seven lines and the new file count is 10
00:11:55
lines so if you see we had seven lines
00:11:58
and we removed two lines over here and
00:12:01
over here so now we have five lines and
00:12:03
then we've gone and added 1 two 3 four
00:12:05
five so yeah we've got 7 - 2 plus 5 we
00:12:09
get to 10 lines so that's that example
00:12:11
over here and we're just explaining to
00:12:13
the llm how it works so that's the diff
00:12:15
spec now we have artifact info bulk
00:12:18
creates a single comprehensive artifact
00:12:20
for each project the artifact contains
00:12:22
all necessary steps on components
00:12:24
including shell commands to run
00:12:25
including dependencies to install using
00:12:28
a package manager and mpm files to
00:12:30
create and their contents holders to
00:12:32
create if necessary so I'm just going to
00:12:34
scroll down to the bottom and show you
00:12:35
what that actually looks like so here's
00:12:38
the example as example user query can
00:12:40
you help me create a JavaScript function
00:12:42
to calculate the factorial of a number
00:12:44
and user query assistant response
00:12:47
certainly I can help you create a
00:12:48
JavaScript function to calculate the
00:12:50
factorial of a number so this is just
00:12:52
plain text it's responding with and then
00:12:54
it starts to respond with a bolt
00:12:56
artifact and so that is contained in
00:12:58
here and the bolt artifact contains lots
00:13:01
of Bolt actions so here you can see
00:13:03
we're creating a file and this is the
00:13:05
code of the file factorial function and
00:13:07
then over here we have an action which
00:13:10
is running a shell command which is node
00:13:11
index.js so we create the index.js file
00:13:14
and then we run it with node index.js
00:13:16
and what's cool is that we can
00:13:18
intertwine both normal text and also
00:13:20
these tags so we later on the front end
00:13:23
we'll be able to pass out the artifacts
00:13:25
and the actions from the other text and
00:13:27
that basically goes into something like
00:13:29
this so importing your stack Blitz
00:13:31
project into Bol over here this is just
00:13:33
regular text at the beginning and then
00:13:34
this is the artifact and these are
00:13:36
different actions within the artifact
00:13:37
and we can Mark if it's been done or not
00:13:39
and so on and then here's some ending
00:13:41
text here's another example let's build
00:13:43
a snake game certainly I'd be happy to
00:13:46
help so we have some Bol artifact which
00:13:48
is snake game here you can see we're
00:13:50
adding a package Json file now we're
00:13:52
doing mpm install and this is a shell
00:13:54
command now another B action let's
00:13:56
create an index.html and then finally
00:13:58
another shell command which is mpm run
00:14:00
Dev and here you can see we did mpm
00:14:02
install of vit and finally some text now
00:14:04
you can play the snake game one more
00:14:06
example make a bouncing ball it's the
00:14:08
same thing go and write package Json add
00:14:11
lots of different files and then npn
00:14:13
runev now that's basically the core of
00:14:16
what this prompt does I will cover a
00:14:18
little bit more on artifact instructions
00:14:20
but these different commands and actions
00:14:22
are what what the AI has to do on our
00:14:24
behalf basically so it says look
00:14:26
comprehensively at the whole project
00:14:28
wrap tags bolt artifact bolt action
00:14:32
current working directory we passing
00:14:34
that in from the top over here from my
00:14:36
function and by default that's just
00:14:37
going to be home project now regarding
00:14:40
the shell always you run the yes command
00:14:42
so it just automatically go on to the
00:14:44
next step always install necessary
00:14:46
dependencies first ens sure code is
00:14:49
clean readable and maintainable never
00:14:51
use the word AR artifact that might be
00:14:53
confusing to users I like here we've got
00:14:56
important important then Ultra important
00:14:58
do not be bothast do not explain
00:15:00
anything unless the user is asking for
00:15:01
more information that is very important
00:15:04
so I'm guessing they were playing around
00:15:06
with this and they really had to
00:15:07
convince the ai ai not to talk too much
00:15:10
and so this is how they got that to work
00:15:12
with these Ultra important tags and then
00:15:13
the other one think first and reply with
00:15:15
the artifact that contains all necessary
00:15:17
steps to set up the project files shall
00:15:19
commands to run it is super important to
00:15:21
respond with this first and then we go
00:15:23
on to see all the examples now I spent
00:15:26
quite a lot of time going over the
00:15:27
prompt and I typically wouldn't do this
00:15:29
but the reason I did this here is
00:15:31
because this is literally the only
00:15:32
prompt in the project which is crazy so
00:15:34
like every time you're messaging all the
00:15:36
messages come into this prompt the AI
00:15:37
responds you know we might send it user
00:15:39
modifications it's just responding with
00:15:41
all the actions and we're just going
00:15:42
back and forth on that conversation with
00:15:44
this single prompt and that's capable of
00:15:47
building full stack apps which we saw in
00:15:49
the browser which is incredible so after
00:15:52
all of that you can see we're at stream
00:15:53
text this is where we left off and so
00:15:56
now jumping back to chat action you can
00:15:57
see we get the results we stream it back
00:15:59
to the client that's being used over
00:16:01
here and that basically sets messages
00:16:03
now messages we're going to go and pass
00:16:05
them and that's done we've used message
00:16:07
passer but let's see where messages are
00:16:09
used so over here you'll see pass
00:16:11
messages so it's a use effect so
00:16:13
whenever messages changes we're going to
00:16:15
go and pass messages which is from user
00:16:17
message passer so let's dive in and pass
00:16:20
messages is going to go and do pass
00:16:22
which runs this from streaming message B
00:16:25
now remember as well we're getting in
00:16:27
the text in chunks so it's sort of like
00:16:30
chat GPT where it just streams the
00:16:31
response so we could have like half an
00:16:33
artifact being sent back to us because
00:16:36
full response hasn't happened yet and so
00:16:38
we need to be able to handle that case
00:16:40
properly and I'm not going to spend too
00:16:42
long on the passing logic but that's
00:16:44
basically what's happening in here and
00:16:46
we'll actually be able to jump to the
00:16:48
test file to get a better idea but here
00:16:50
you can see we're like looking for these
00:16:51
opening and closing tags and here you
00:16:53
can see we're extracting an attribute or
00:16:55
title or ID we're marking when an
00:16:57
artifact has been opened so when there's
00:16:59
an open tag or a closed tag we've got
00:17:00
callbacks for all of that and this is a
00:17:02
test file for how that actually work so
00:17:05
very basic level if we're just passing
00:17:07
regular text hello world it's just going
00:17:09
to give us back hello world and it
00:17:11
should allow normal HTML tags as we saw
00:17:13
before so hello world again it just
00:17:15
gives us back hello world now some
00:17:17
examples when we don't have any
00:17:18
artifacts so F F Bar F Bar with a p and
00:17:21
so on so there are no artifacts here and
00:17:23
here we have incomplete artifacts so
00:17:25
we're still being streamed the result
00:17:27
and so here you'll see Food Bar bolt a
00:17:29
just gives us that same thing back but
00:17:31
over here when we've got Fubar bolt a
00:17:33
and you can see this is a start of an
00:17:35
artifact so it's actually been removed
00:17:37
and this is now the expected output and
00:17:39
you can see examples when we have real
00:17:41
artifacts what it should do so some text
00:17:43
before some more text and then over here
00:17:45
we have a bolt artifact in between and
00:17:48
that's been removed from this text but
00:17:50
we've done an on artifact open and on
00:17:52
artifact close cuz yeah we have one of
00:17:54
each and we don't have any action so z0
00:17:57
and then if I dive down here you'll see
00:17:58
a more complete example again we've got
00:18:00
before and after at the end of the line
00:18:02
and we've got one bolt artifact so an
00:18:04
open and a close that's what we're
00:18:06
expecting here you can see in Bol action
00:18:08
so it's an npm install and here we have
00:18:11
another bolt action which is a file with
00:18:13
some content and then we close the Bol
00:18:15
artifact and so if we jump to streaming
00:18:17
message passer you'll see how these
00:18:19
callbacks are used if it wasn't fully
00:18:21
clear just now so whenever the on
00:18:23
artifact open is called so we're doing
00:18:26
workbench do basically add artifact and
00:18:28
add this data on close we're basically
00:18:31
marking it as closed now when actions
00:18:33
are opened what we'll do is add action
00:18:35
but not if it's a shell type of action
00:18:37
because we need the command to be fully
00:18:39
complete before we can run a shell
00:18:40
command we can't do like MP and run that
00:18:43
it has to be npm install the full
00:18:46
command for it to work but here you can
00:18:47
see we do run it when we do on action
00:18:50
close so if it's of type shell now we
00:18:53
can add the full action and then also
00:18:54
now that it's closing we can run the
00:18:56
action so what is workbench store here
00:18:59
you'll see we're creating this workbench
00:19:01
as I mentioned before we're using Nano
00:19:02
store atom and map you can see we're
00:19:05
creating an an artifact map over here as
00:19:07
part of our workbench store and whenever
00:19:10
we do add artifact we're basically just
00:19:12
adding artifacts to here as you can see
00:19:14
down here add artifact so we did this.
00:19:17
get artifact if we've already got it
00:19:19
otherwise just return and if not then
00:19:20
we're doing set key and we're adding the
00:19:22
artifact with its message ID here we can
00:19:24
update an artifact here we can add an
00:19:27
action and run an action and we this
00:19:29
basically calls another class called
00:19:31
action Runner and here you can see we're
00:19:33
adding the actions similar idea to
00:19:35
before if we've already added it just
00:19:37
return otherwise go and create this
00:19:39
action which is in pending State and
00:19:41
down here we can see run action so we're
00:19:44
updating the action to be executed true
00:19:46
and then the important part is execute
00:19:48
action you can see we're setting current
00:19:51
execution promise so basically we're
00:19:53
waiting for the previous promise to
00:19:54
complete and then we can go and do the
00:19:56
next action so execute action we update
00:19:59
the action so we're running right now
00:20:01
and then there are two types of action
00:20:02
we mentioned can be either a shell
00:20:04
action or a file action so look at run
00:20:07
shell action so this takes web container
00:20:09
and remember what we saw in the prompt
00:20:11
about like our own version of Z or bash
00:20:15
so we've got jsh basically and this is
00:20:17
going to go and run this command in the
00:20:19
web container because it's a shell
00:20:21
command and then the other type of
00:20:23
action is run file action so we don't
00:20:25
need to run anything there but we take
00:20:26
the web container again and will do make
00:20:29
directory recursive created the folder
00:20:32
and then we will go and do WR file and
00:20:34
store the file in the web container now
00:20:36
what is the web container you might may
00:20:38
ask so let's spend a few minutes
00:20:40
understanding that basically all this
00:20:42
code over here that's great we can show
00:20:45
text in the browser but how do we
00:20:46
actually go and run it over here this
00:20:48
could be running on a server and then
00:20:49
being sent back to us but no it's fully
00:20:51
running within the browser and so how
00:20:53
does all of this work how can I run no.
00:20:55
JS in the browser and that's where web
00:20:57
container comes in in so this is the web
00:21:00
containers homepage they have
00:21:01
environments in your web app this is an
00:21:04
example of it running in the browser so
00:21:06
we're just importing chalk from the
00:21:08
chalk library and if I want to run it
00:21:10
node index.js you can see here we've got
00:21:13
this magenta line and then here we've
00:21:14
got this green line process. version and
00:21:16
this all ran right here locally in the
00:21:18
browser I don't need any internet for
00:21:19
that to work how are your web app with
00:21:21
the web container API this is how we set
00:21:23
it up like in 10 seconds we do we buil a
00:21:26
web container so that's that line over
00:21:28
here then we go in Mount our project
00:21:31
files that's basically just our
00:21:32
JavaScript files and package Json and so
00:21:34
on then we can also do things like
00:21:36
spawner command like npm install or you
00:21:38
can also do it via jsh and then we can
00:21:41
also run npm runev in the browser with a
00:21:43
command like this another spawn command
00:21:45
and then this is what the project files
00:21:47
look like over here these are the files
00:21:48
we pass in and it can just go and run
00:21:50
that in the browser so it deer dive into
00:21:52
how to use web container here you can
00:21:53
see some app that we're building in the
00:21:55
browser you have a code editor on the
00:21:57
left and you have App working on the
00:21:59
right this is an Express server and you
00:22:01
have the web container being shown in an
00:22:02
if frame over here now this this
00:22:05
tutorial it doesn't use a react or
00:22:07
viewer or anything it's just old school
00:22:08
HTML so we're going to get query
00:22:10
selector in HTML and just completely set
00:22:12
our app to zero we're going to add a
00:22:15
text area and an if frame to our page
00:22:17
that's the inner HTML of our page do a
00:22:19
bit of styling and then we get this
00:22:22
we're going to grab references to our if
00:22:23
frame and to our text area and now we're
00:22:25
going to go and set up web containers so
00:22:28
we're going to install the web container
00:22:29
API Library we're going to wait for the
00:22:31
page to be loaded and then we're going
00:22:32
to do web container. boot and if I
00:22:34
search for that in our project you will
00:22:35
find it as well that's exactly what
00:22:37
we're doing we're importing web
00:22:38
container and then doing web container.
00:22:40
boot and this is returning a promise
00:22:42
basically when the web container is
00:22:43
ready to be run and then you can see um
00:22:45
we are passing in web container
00:22:47
basically to the action Runner and it
00:22:49
gets the web container promise so then
00:22:52
anytime we're using it we're just
00:22:54
waiting for the web container to be
00:22:56
ready and then we're going and doing our
00:22:58
Command so over here run shell action
00:23:00
and we're using the spawn command cool
00:23:02
so we've booted it up now let's go and
00:23:03
create some files so we have an Express
00:23:06
file index.js and we're also creating a
00:23:08
package Json file which uses nodemon to
00:23:11
run it and now we want to get these into
00:23:13
web container so we're just going to put
00:23:15
this into a files object you can see we
00:23:18
have all the code and that's it now
00:23:20
we're going to import those files and
00:23:21
then we are going to go and load those
00:23:23
files so all we do is do Mount files and
00:23:24
we have them now how do you install
00:23:26
dependencies in web container as well
00:23:28
you can just use the spawn command as we
00:23:30
saw so spawn npm install the syntax is
00:23:33
basically first you do something like CD
00:23:34
and then you post the arguments
00:23:36
afterwards and so this LS command would
00:23:38
turn into this with two items in the
00:23:40
second in in the array here's an example
00:23:43
of mpm install so install dependencies
00:23:46
that will help us for the package Json
00:23:48
we have and so now after we've booted up
00:23:50
the web container we can also do install
00:23:53
dependencies and we can also stream
00:23:55
output from this command as well which
00:23:57
is going to be important so here we do
00:23:59
output pipe two and new stream and here
00:24:01
all we're doing is console logging it
00:24:03
but you'll see the output of what's
00:24:05
happening over here on the in your
00:24:07
terminal it's not yet showing on screen
00:24:09
but we can get it to show on screen if
00:24:11
we want now let's actually go and run
00:24:12
the Deb server so as you might expect we
00:24:15
can just do spawn again and we can do
00:24:16
mpm Run start and this is important
00:24:19
because once the server is ready we're
00:24:21
going to get this server ready event
00:24:24
emitted and we can get the URL for this
00:24:27
container and and so we can set the
00:24:29
iframe source to that URL and I want to
00:24:31
show you that's actually what's
00:24:32
happening in our app as well so you'll
00:24:34
see over here base URL we're getting it
00:24:36
from active preview we're setting the
00:24:38
iframe url iframe url you'll see it down
00:24:41
here and this iframe that's the iframe
00:24:43
over here so everything you see in this
00:24:45
section and this app that's running for
00:24:46
me this is the iframe now if I jump back
00:24:48
you'll see active preview we're can to
00:24:50
get it from the preview this is from the
00:24:52
preview store workbench store. previews
00:24:54
let's jump into previews you can see
00:24:57
we're just getting the pr prev from the
00:24:58
previous store previous store is over
00:25:01
here and it's listening on that same web
00:25:03
container on like for the port event
00:25:05
basically and when the port is ready
00:25:07
we're going to go and set the base URL
00:25:09
and that's basically what the iframe URL
00:25:12
we just saw is and how it all works so
00:25:14
over here we've done web container on
00:25:15
Port here we're actually using the
00:25:17
server ready vent but it's very similar
00:25:20
idea and we're just setting the iframe
00:25:23
source URL and here you can see it pop
00:25:25
up on the right now let's actually go
00:25:26
and run the dev server start which is
00:25:29
just npm start and you can see that we
00:25:32
have it so when a request comes into
00:25:34
slash basically to our homepage we get
00:25:36
welcome to a web containers app and it's
00:25:38
working in the browser here's our no JS
00:25:40
code and here is the app running now you
00:25:43
can also go and write files to the web
00:25:45
container so here's fs. WR file to go
00:25:48
and make an edit to the index.js file
00:25:50
we're going to listen on changes to the
00:25:52
text area to write to that file and here
00:25:54
you can see we had a blue part and it
00:25:56
appears in our ey frame as well and it's
00:25:58
using node modon so you can see here the
00:26:00
console logs at the bottom it's just
00:26:01
updating it in real time now what if we
00:26:03
want to show a terminal in the browser
00:26:05
itself and and we actually have that
00:26:07
over here as well this is a terminal
00:26:09
right and we can see we're running at
00:26:11
Local Host 3000 so how is this built and
00:26:13
so this uses something called xterm and
00:26:16
this is xterm JS over here so if I do LS
00:26:20
a bunch of fake files that's cool so
00:26:22
this is a terminal running in the
00:26:23
browser and if you want to use it just
00:26:24
do mpm install xterm xterm and you're
00:26:27
see in our project as well we using as
00:26:29
our terminal so the terminal over here
00:26:31
as xterm we're doing a new xterm here's
00:26:33
the font here's the color and so on
00:26:35
we're adding some addons to make it fit
00:26:37
but now we've understood how this is
00:26:39
showing up so let's continue our
00:26:40
tutorial we've installed xterm we we're
00:26:44
going to add it to the bottom of the
00:26:45
page over here oh right now it's just an
00:26:47
empty div so we haven't put anything in
00:26:49
it yet and then terminal element we're
00:26:52
going to create an instance of terminal
00:26:54
that's happening here we're going to
00:26:55
open the terminal and we're going to use
00:26:58
the terminal element and that's going to
00:26:59
pop up the terminal and here we are the
00:27:01
terminal we wanted we can style the
00:27:03
terminal a bit as well so using just
00:27:06
import X term. CSS and now we have a
00:27:08
fully styled terminal that fits the page
00:27:10
and now we're going to want to do send
00:27:12
output to the terminal so install
00:27:14
dependencies and start Dev server we're
00:27:16
going to pass in a terminal and then
00:27:18
with the output we get we're going to be
00:27:20
able to write it to the terminal and so
00:27:22
right now when we do the install process
00:27:24
we can have this writable stream and
00:27:26
inside it instead of console logging it
00:27:28
to the Chrome console we can instead
00:27:30
right to our terminal and just by adding
00:27:33
that line now if we run it you will see
00:27:35
the stuff coming up in the terminal now
00:27:37
when we change the text area because
00:27:38
we're using nodon you'll see that down
00:27:39
here in the terminal once again we'll
00:27:41
see nodon restarting and we'll have the
00:27:43
text logged live to us it's alive
00:27:45
because this is console logging within
00:27:47
our own app now so far we don't have any
00:27:50
interactivity with our terminal so what
00:27:52
we're going to do now is allow users to
00:27:54
run commands like mpm Run start orpm
00:27:57
install themselves so imagine we remove
00:27:59
the old code we had where we'd
00:28:00
automatically run those commands for the
00:28:02
user and instead we're going to spawn a
00:28:05
js8 instance so this is going to be our
00:28:07
shell process now jsh we mentioned it
00:28:10
earlier in the video and we can actually
00:28:11
go and run commands through it so
00:28:14
instead of having to do like spawn npm
00:28:16
install now we do spawn jsh and then we
00:28:18
go and pass in the action so here we do
00:28:20
jsh and then something like mpm install
00:28:23
to get it to work and so we've started
00:28:25
the shell process and we're going to
00:28:27
Output everything that it gives us we're
00:28:30
going to Output it to the terminal with
00:28:31
terminal. right and then we'll start the
00:28:34
Shell at the bottom of our script so
00:28:36
cool we have something running over here
00:28:38
and you can see our home directory but
00:28:41
we still don't have the option to write
00:28:43
anything into the terminal and it for
00:28:45
actually to get to the Shell so let's
00:28:46
make that happen we're going to get the
00:28:48
shell process input and we're going to
00:28:50
write to that input so anytime we write
00:28:52
to the terminal is going to be sent to
00:28:54
the shell and now when we start typing
00:28:56
commands like npm install in PM start
00:28:59
it's going to send it to our Express
00:29:01
nodejs server and go and actually run it
00:29:03
and here we can see the final demo of it
00:29:05
actually working and this is quite meta
00:29:08
because you're running it in stack blitz
00:29:10
so this is its own web app but this
00:29:12
whole thing is running in stack Blitz
00:29:14
which is its own like web app running
00:29:16
out web app anyway so we've done mpm
00:29:19
install and you can see the results now
00:29:21
we're going to do mpm run Dev was it or
00:29:24
mpm start and see we're even getting the
00:29:26
errors and here we started node modon
00:29:28
app is live it's all working as we said
00:29:30
we're restarting nodon update getting
00:29:32
the logs here in real time just imagine
00:29:35
this is a full web app so I can go make
00:29:37
changes over here you can see noon
00:29:39
restarting and our console updating over
00:29:41
here and let's say I want to change the
00:29:42
homepage to something else that's also
00:29:44
happening so this is Express njs server
00:29:47
this is our web app showing on screen
00:29:49
and that's basically how new works as
00:29:51
well so I actually think that covers the
00:29:53
core of this project and how you could
00:29:55
actually have gone and built this
00:29:56
yourself fairly quickly I mean there's
00:29:58
some amazing technology behind it the
00:30:00
tackl team has been working on web
00:30:01
container for years now and so that made
00:30:03
this all possible but it's all open
00:30:04
source and you can use all this stuff in
00:30:06
your own projects as well and you
00:30:07
probably could have built bot. new
00:30:09
yourself as well so if we wrap that up
00:30:11
over here you'll see the terminal that
00:30:12
we have we have the code editor this is
00:30:14
using Code mirror as the editor you can
00:30:16
just npm install code mirror and you'll
00:30:19
have something like this or make it a
00:30:21
lot prettier like this with a file
00:30:22
system and so on over here you'll see
00:30:24
the preview which is literally just an
00:30:25
if frame everything in this section is
00:30:28
the preview of the app we're running and
00:30:29
here's the code behind it and here's the
00:30:30
terminal that all gets orchestrated
00:30:33
using web container it can go and run
00:30:35
all the files that we have over here we
00:30:37
just add them to web container and so
00:30:39
the full flow when I enter some text
00:30:41
here and I hit enter it goes and sends
00:30:43
something to API chat now we're busy
00:30:45
calling anthropic and it's streaming
00:30:47
results back which you can see happening
00:30:49
over here it's updating code files
00:30:51
happening one by one you can see each
00:30:53
Bol action is basically happening over
00:30:55
here it's updating this big art artifact
00:30:58
file that we have with lots of different
00:31:00
commands update create create create and
00:31:02
so on right now we can't see any code
00:31:04
running but it will run in a second here
00:31:06
we have an action it's finally going I'm
00:31:08
not even sure what I asked it to do this
00:31:10
time but wow you have a car running on
00:31:11
the road oh and there you have a plane
00:31:12
flying that's awesome we saw how we pass
00:31:15
all these different actions and then the
00:31:16
shell command and then that went and ran
00:31:18
as well this is all just being displayed
00:31:19
in the UI code has been updated preview
00:31:22
is shown all the files are being
00:31:23
streamed into a web component or they're
00:31:26
being a command like this is is being
00:31:28
streamed into jsh to be run I hope you
00:31:30
enjoyed the video I really enjoyed
00:31:32
diving into the code behind bolon new it
00:31:34
continues to blow my mind how strong AIS
00:31:38
are today in this video as well web
00:31:40
container is also extremely powerful
00:31:42
that we're running no JS in the browser
00:31:44
so that's the end of the video by the
00:31:46
way here's one more example if you're
00:31:47
interested here you can see a full mail
00:31:48
client that's been built for me which is
00:31:50
really nice and yeah it like just works
00:31:53
great first time this isn't one of their
00:31:55
preset examples it's just something I
00:31:56
asked it to do in like one command if
00:31:58
you enjoyed I'd love it if you subscribe
00:32:00
the Channel's called learn from open
00:32:01
source every week we go over a different
00:32:03
open source project enjoy till next time