Learn how build a fullstack realtime chat app with Svelte and Pocketbase, then deploy it to a Linux server for just $5. Let's find out if the Spock stack can scale...

💵 Get started with Linode at https://www.linode.com/fireship ($100 Credit good for 60 days as a new user)

#webdevelopment #project #linux 

💬 Chat with Me on Discord

https://discord.gg/fireship

🔗 Resources

- Chat App Live Demo https://pocketchat.fireship.app
- Fireship Pocketbase Tutorial https://fireship.io/lessons/pocketbase-chat-app
- Full Source Code https://github.com/fireship-io/pocketchat-tutorial
- Pocketbase Docs https://pocketbase.io/
- Pocketbase First look https://youtu.be/Wqy3PBEglXQ

🔥 Get More Content - Upgrade to PRO

Upgrade at https://fireship.io/pro
Use code YT25 for 25% off PRO access 

🎨 My Editor Settings

- Atom One Dark 
- vscode-icons
- Fira Code Font

🔖 Topics Covered

- Build an app with Svelte
- What is Pocketbase?
- Can Pocketbase scale?
- Deploying Pocketbase to Linode
2024-02-04T13:28:32.530Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
c2c774a0-aaa0-41ba-a908-c1d9a738d3de
c916629514c6b3dfd877cc41239739c4ed477f230c4c16cebe399b854243dd16
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
What you're looking at is the actual side projects directory on my computer.
None of these side projects have gone on to become the next Facebook yet, but I have not failed.
I've just found hundreds of apps that don't work.
If you're a developer slash entrepreneur, it's extremely important not to over engineer things.
Andy Jassy once said, invention requires 2 things.
1, the ability to try lots of experiments, and 2, not having to live with the collateral damage of failed experiments.
In today's video, we'll build a full stack chat app using pocket base and Svelte, then deploy it to a Linux server on Linode for just $5.
I call this the Spok Stack and prepared to be amazed at how quickly it can get things done.
Stupidly, I made this demo public, so you can actually try it out on the Internet right now.
This is not my first rodeo, and I know you guys will spam it with the most horrific comments imaginable, but this time messages can be moderated with community reactions.
If a comment gets pooped on 5 times, it disappears from the UI.
The back end magic behind this application is a relatively new tool called Pocketbase, which is like a free and open source ierbase written in Go that provides user authentication along with a real time database powered by SQLite.
But unlike any other base not out there.
It compiles everything to a single executable, and that means to self host it, all you need is one little server, which costs less than your grande soy milk macchiato.
Is the ultimate sophistication.
But today, we'll find out if the simplicity of pocket base can actually scale.
To kick things off, we're going to start things in reverse by deploying pocket face to a Linux server in the cloud.
Luckily for us, Linode has sponsored this video, which means I get to make it rain with a $100 in free credits for everyone watching in this video.
For those that don't know, Linode is one of the original cloud providers that's been around since 2003.
Their platform is a perfect fit for this project because like Svelte and Pocketbase, it's famous for simplicity.
Unlike big cloud providers, you can get a Linux server up and running with a few clicks with flat predictable pricing that won't cause collateral damage later.
After you register, go to the dashboard and click the button to create a new Linode, then then choose an image with your preferred Linux distro.
I'm going with Debian, but the real Chads out there will use Arch, by the way.
Then choose a region and the size of your machine.
And finally, give it a password and click create.
Step 1 is complete.
We now have a Linux server running in the cloud.
I told you that would be easy.
Let's go ahead and make a note of its key address to access it on the Internet.
Now, in step 2, let's deploy Pocket Base to it.
1st, download and unzip Pocket Base from the website.
I'm also using Debian on my local machine, so we'll download the Linux version.
Unzip it to get this single pocket based executable.
You can run it by running pocket based serve, but I wanna run it in the cloud on my Linode server so I can access it from anywhere just like a platform like Fire database.
Let's open up the terminal and use secure shell to access the Linode IP address as a root user.
It'll require the password you created earlier, and Now we have access to the mainframe.
We're currently in the root directory, so let's go ahead and create another directory called p b.
And now we just need to upload the Pocket Base to this directory.
We could do it with r sync or an application like Filezilla, but I think the easiest approach is to use secure copy, which will simply copy the local file over to a remote directory we just created.
Run this command from a separate terminal on your local machine.
Once that's done, we can go back to the terminal on the Linode machine and run the pocketbase serve command.
And to make it accessible over the Internet, we'll use the HTTP flag followed by our IP address and port 80.
Congratulations.
You just self hosted your own back end that you can now access over HTTP with the IP address.
It serves a REST API as well as an admin dashboard that you can access with the underscore URL.
However, there's a few more things I wanna show you to make it fully production ready.
The first thing I would do is bring my domain over to Linode.
No.
It has a fully featured DNS manager, and Pocket Base uses Let's Encrypt to automatically generate an SSL certificate to serve your back end over HTTPS.
All you have to to do is add this extra flag to the serve command.
Now the next thing I would consider doing is mounting a volume to the pbdata directory.
Not read.
This is where Pocketbase stores all of your data.
A volume is just its own file system that can be moved around to different servers.
On Linode, we can easily attach an extra 20 gigabytes for just $2.
And then finally, I would recommend setting up a system d service to automatically restart Pocket Base whenever the server reboots.
And now it's time for step 3, where we model the data for our chat app.
Navigate to your Pocket Base dashboard and create an admin user.
From here, we can go to the database and by default, it has a collection for users.
These are the users of your application, which contain fields like username, email, users of your application which contain fields like username, email, password, and so on.
What we need is a way to create a one to many relationship between users and chat messages.
Create a second collection called messages and give it 2 fields.
The first field is text for the message content itself, and you can add some optional server side validations here like min length and max length, while the second field, user, creates a relationship that says a message belongs to a no user.
Under the hood, Pocket Base creates a foreign key for the user ID on the messages table in the SQLite database.
Go ahead and click create to update the schema.
And now, you should be able to create new records in the database.
That takes care of our data modeling.
Now let's make it secure.
Every collection in pocket base can have API rules.
These rules determine who can access your data from a front end application.
By default, the messages collection can only be accessed by admin users.
However, we want anybody to be able to view the messages, so let's go ahead and hit the unlock button for list and view.
Users also need the ability to create new messages, but it's critical that they only create messages associated to their own user ID.
We can enforce that rule by ensuring that the user property is equal to the request auth user ID.
And just like that, we've eliminated tons of complexity that we would need in our back end code otherwise.
Not.
Save the changes, then head over to the users collection.
For users, we already have a bunch of rules built in, but we wanna give users the ability to view each other's profiles, So let's go ahead and remove the rules for view and list to make this data public.
Now that we're somewhat secure, we can start building out the front end with Svelte.
As you may know, I use Svelte to build the Fireship IO website, but it's also been used by the pocket based developers to build their admin UI as well.
It's a great fit for this project because not it's really good at building real time UIs, thanks to its built in reactive stores.
Generate a new project with Vite, then select the Svelte option, and we'll also go with TypeScript.
Not.
Open the project, run npm install, then npm run dev to serve it locally.
Then in the code, delete all the boilerplate and create a new file called pocket base in the lib directory.
Whenever building a new app, I usually start by thinking about user authentication.
What we'll do in this file is provide a way to listen to the current user in real time from anywhere in the application.
To handle that, we'll install the pocket based JavaScript SDK with NPM.
Once installed, we can then import it in this file as well as writable from Svelte store.
Now to connect to our back end, all we have to do is initialize pocket base with the URL it's hosted at, which in this case be the Linode IP address.
From there, I'm creating a variable for current user that's equal to a writable store.
Its default value is the pocket base auth store model, which is equal to null when the user is not logged in or equal to that database record of the currently logged in user that contains fields like the user ID, user name and so on.
Now the value of this model will change when the user signs in and signs out, and we can listen to those changes by registering a callback for the on changed event.
When this event fires, we can update the Svelte store with the current model.
That gives us a way to subscribe to the current user.
Let's put it to use by creating a login dot spelled component.
Inside this component, we'll log in a user with email and password.
What's awesome about that store we just created is that been subscribed to the current value anywhere in the application reactively by putting a dollar sign in front of it.
For example, we might say, if current user, render the text signed in as current user dot username.
Now the question becomes, how do we sign in a user?
Well, let's start by creating variables for username and password, then create an HTML form that has 2 inputs for those values.
In Svelte, we can easily bind that variable to that form value with the bind value directive.
Now we can access the current form value in our script.
Let's create an async function called login that awaits a call to the pocket based collection of users then calls the auth with password method using the username and password as arguments.
And that's all the code it takes to authenticate a user.
However, we don't have a user yet, which means we'll also need another function named sign up.
In this function, we'll set up some initial data for a new user like the username, password, And we can also pass a name and email address here as well or whatever custom fields you configured in Pocket Base.
We can then take that data and create a new record in the user's collection.
Option.
Once created, we call login with that same user data, and that's all it takes to sign up.
But it'd be a good idea to wrap this in a try catch block and render an error message if a bad username or password is used.
We also need a sign out function, which is accomplished by calling auth store clear.
Now let's go into the HTML and bind these functions to buttons, which is accomplished in Svelte with on click.
And as one final touch, I'm also going to listen to the on submit event on the form and prevent the default action so it doesn't refresh the page when submitted.
Now now.
Let's open the app dot Svelte file and declare the login component there.
If we view the app in the browser, we should now see this login form.
And And when you enter a username and password and click sign up, the UI should automatically rerender to show the current user's username.
And now we're finally ready to build the fun part, the a real time chat messages feature.
Let's go ahead and create a new component called messages.
We can import the on mount and on destroy lifecycle hooks from Svelte as well as pocket based.
Our first goal here is to fetch the most recent messages, which we can represent initially as an empty array.
From there, we can fetch the messages when the component is first initialized with on mount.
This code will run once at the beginning of the component life cycle to make a query to the messages collection.
Use git list to fetch a paginated list of messages that starts on page 1 and has 50 messages per page.
It also takes an object where you can do things like sort and filter the query.
In our case, we want it sorted by that created field.
What's really cool though is how easy it noticed to join in relational data.
Remember, every message has a user field that points to a user record.
If we want to also include the user data on every message.
We can do that with the expand option, and that means we get all the data we need without any complex SQL joins.
Now the return value is a result list, and we can set our messages array as the result list items.
From there, we can go went to our HTML and loop over the messages with a Svelte each block.
Notice how for each message, I have the message ID in parentheses.
Not.
This creates a keyed loop so Svelte can keep track of all the items in the list to render them more efficiently.
For each message, I'm going to render out the message text in the database.
And, also, because we joined in the user, I'm going to render out the user's username and also generate a unique a tar for each user using an awesome little service called DiceBear.
Let's go ahead and try it out in the browser.
I also have the pocket base admin UI side by side.
And as you can see here, not.
It fetches all the messages from the database.
That's pretty cool, but how do we create a new message?
Let's go back into the code and set up a variable for a new message.
Then define a function called send message.
For data, we'll need the text of the new message and also the current user's user ID.
Remember, We can always get that by putting a dollar sign in front of it because Svelte is awesome.
And now we just tell Pocket Base to create a new message.
Let's go ahead and take this function and bind it to the on submit event on a form that also prevents the default action and binds the value of the text to that new message variable.
Let's go ahead and open it up in the browser again and tried to create a new message.
As you can see here, it creates a new message, but we need to refresh the entire page to actually see the message, and that's not going to fly for a real time chat app.
The final thing we'll do here is make these messages update in real time.
Let's go back into the on mount callback, and then we'll call pocket based collection messages and subscribe to the entire collection with the star symbol.
This allows us to run a callback anytime a message is created, updated or deleted.
The action tells us what happened.
In our case, we want to update the UI if a new message was created or deleted.
When created, we can update the messages array with that new record.
One caveat with real time though is that it won't include that expanded user record, although we can easily fetch it with a one query if needed.
Then for the delete action, we can filter out the ID of the message that was removed.
That gives us a real time listener, but whenever working with real time, It's a good practice to unsubscribe when the data is no longer needed because otherwise, you could end up with memory leaks and unnecessary reads on the database.
Create a variable to represent a function named unsubscribe.
We obtain this function from pocket base when making the call to subscribe.
Once we have that function as state, We can then call it on the on destroy life cycle hook to end the subscription when the user logs out or if they navigate to a different page.
Let's open up the browser and tried it out.
You should now have a chat application that updates the messages feed in real time.
And now we can run npm build to build our site for production and deploy it somewhere on the Internet.
In fact, because we have a single page application, we could actually do this on Linode by uploading the generated files to a storage bucket, then configuring it as a static website host.
The final thing you wanna know is that as your website grows, the pocket base will need to scale vertically with more CPU and RAM to handle more and more traffic.
Not.
This can be easily accomplished by simply resizing your Linode.
A bigger server can handle more traffic.
It can easily handle tens the thousands of concurrent users and should be more than adequate for the vast majority of projects out there.
This allows you to fail over and over again as not looked her without a bunch of wasted time and money as collateral damage.
Thanks for watching, and I will see you in the next one.

Speaker 0: What you're looking at is the actual side projects directory on my computer. None of these side projects have gone on to become the next Facebook yet, but I have not failed. I've just found hundreds of apps that don't work. If you're a developer slash entrepreneur, it's extremely important not to over engineer things. Andy Jassy once said, invention requires 2 things.

1, the ability to try lots of experiments, and 2, not having to live with the collateral damage of failed experiments. In today's video, we'll build a full stack chat app using pocket base and Svelte, then deploy it to a Linux server on Linode for just $5. I call this the Spok Stack and prepared to be amazed at how quickly it can get things done. Stupidly, I made this demo public, so you can actually try it out on the Internet right now. This is not my first rodeo, and I know you guys will spam it with the most horrific comments imaginable, but this time messages can be moderated with community reactions.

If a comment gets pooped on 5 times, it disappears from the UI. The back end magic behind this application is a relatively new tool called Pocketbase, which is like a free and open source ierbase written in Go that provides user authentication along with a real time database powered by SQLite. But unlike any other base not out there. It compiles everything to a single executable, and that means to self host it, all you need is one little server, which costs less than your grande soy milk macchiato. Is the ultimate sophistication.

But today, we'll find out if the simplicity of pocket base can actually scale. To kick things off, we're going to start things in reverse by deploying pocket face to a Linux server in the cloud. Luckily for us, Linode has sponsored this video, which means I get to make it rain with a $100 in free credits for everyone watching in this video. For those that don't know, Linode is one of the original cloud providers that's been around since 2003. Their platform is a perfect fit for this project because like Svelte and Pocketbase, it's famous for simplicity.

Unlike big cloud providers, you can get a Linux server up and running with a few clicks with flat predictable pricing that won't cause collateral damage later. After you register, go to the dashboard and click the button to create a new Linode, then then choose an image with your preferred Linux distro. I'm going with Debian, but the real Chads out there will use Arch, by the way. Then choose a region and the size of your machine. And finally, give it a password and click create.

Step 1 is complete. We now have a Linux server running in the cloud. I told you that would be easy. Let's go ahead and make a note of its key address to access it on the Internet. Now, in step 2, let's deploy Pocket Base to it.

1st, download and unzip Pocket Base from the website. I'm also using Debian on my local machine, so we'll download the Linux version. Unzip it to get this single pocket based executable. You can run it by running pocket based serve, but I wanna run it in the cloud on my Linode server so I can access it from anywhere just like a platform like Fire database. Let's open up the terminal and use secure shell to access the Linode IP address as a root user.

It'll require the password you created earlier, and Now we have access to the mainframe. We're currently in the root directory, so let's go ahead and create another directory called p b. And now we just need to upload the Pocket Base to this directory. We could do it with r sync or an application like Filezilla, but I think the easiest approach is to use secure copy, which will simply copy the local file over to a remote directory we just created. Run this command from a separate terminal on your local machine.

Once that's done, we can go back to the terminal on the Linode machine and run the pocketbase serve command. And to make it accessible over the Internet, we'll use the HTTP flag followed by our IP address and port 80. Congratulations. You just self hosted your own back end that you can now access over HTTP with the IP address. It serves a REST API as well as an admin dashboard that you can access with the underscore URL.

However, there's a few more things I wanna show you to make it fully production ready. The first thing I would do is bring my domain over to Linode. No. It has a fully featured DNS manager, and Pocket Base uses Let's Encrypt to automatically generate an SSL certificate to serve your back end over HTTPS. All you have to to do is add this extra flag to the serve command.

Now the next thing I would consider doing is mounting a volume to the pbdata directory. Not read. This is where Pocketbase stores all of your data. A volume is just its own file system that can be moved around to different servers. On Linode, we can easily attach an extra 20 gigabytes for just $2.

And then finally, I would recommend setting up a system d service to automatically restart Pocket Base whenever the server reboots. And now it's time for step 3, where we model the data for our chat app. Navigate to your Pocket Base dashboard and create an admin user. From here, we can go to the database and by default, it has a collection for users. These are the users of your application, which contain fields like username, email, users of your application which contain fields like username, email, password, and so on.

What we need is a way to create a one to many relationship between users and chat messages. Create a second collection called messages and give it 2 fields. The first field is text for the message content itself, and you can add some optional server side validations here like min length and max length, while the second field, user, creates a relationship that says a message belongs to a no user. Under the hood, Pocket Base creates a foreign key for the user ID on the messages table in the SQLite database. Go ahead and click create to update the schema.

And now, you should be able to create new records in the database. That takes care of our data modeling. Now let's make it secure. Every collection in pocket base can have API rules. These rules determine who can access your data from a front end application.

By default, the messages collection can only be accessed by admin users. However, we want anybody to be able to view the messages, so let's go ahead and hit the unlock button for list and view. Users also need the ability to create new messages, but it's critical that they only create messages associated to their own user ID. We can enforce that rule by ensuring that the user property is equal to the request auth user ID. And just like that, we've eliminated tons of complexity that we would need in our back end code otherwise.

Not. Save the changes, then head over to the users collection. For users, we already have a bunch of rules built in, but we wanna give users the ability to view each other's profiles, So let's go ahead and remove the rules for view and list to make this data public. Now that we're somewhat secure, we can start building out the front end with Svelte. As you may know, I use Svelte to build the Fireship IO website, but it's also been used by the pocket based developers to build their admin UI as well.

It's a great fit for this project because not it's really good at building real time UIs, thanks to its built in reactive stores. Generate a new project with Vite, then select the Svelte option, and we'll also go with TypeScript. Not. Open the project, run npm install, then npm run dev to serve it locally. Then in the code, delete all the boilerplate and create a new file called pocket base in the lib directory.

Whenever building a new app, I usually start by thinking about user authentication. What we'll do in this file is provide a way to listen to the current user in real time from anywhere in the application. To handle that, we'll install the pocket based JavaScript SDK with NPM. Once installed, we can then import it in this file as well as writable from Svelte store. Now to connect to our back end, all we have to do is initialize pocket base with the URL it's hosted at, which in this case be the Linode IP address.

From there, I'm creating a variable for current user that's equal to a writable store. Its default value is the pocket base auth store model, which is equal to null when the user is not logged in or equal to that database record of the currently logged in user that contains fields like the user ID, user name and so on. Now the value of this model will change when the user signs in and signs out, and we can listen to those changes by registering a callback for the on changed event. When this event fires, we can update the Svelte store with the current model. That gives us a way to subscribe to the current user.

Let's put it to use by creating a login dot spelled component. Inside this component, we'll log in a user with email and password. What's awesome about that store we just created is that been subscribed to the current value anywhere in the application reactively by putting a dollar sign in front of it. For example, we might say, if current user, render the text signed in as current user dot username. Now the question becomes, how do we sign in a user?

Well, let's start by creating variables for username and password, then create an HTML form that has 2 inputs for those values. In Svelte, we can easily bind that variable to that form value with the bind value directive. Now we can access the current form value in our script. Let's create an async function called login that awaits a call to the pocket based collection of users then calls the auth with password method using the username and password as arguments. And that's all the code it takes to authenticate a user.

However, we don't have a user yet, which means we'll also need another function named sign up. In this function, we'll set up some initial data for a new user like the username, password, And we can also pass a name and email address here as well or whatever custom fields you configured in Pocket Base. We can then take that data and create a new record in the user's collection. Option. Once created, we call login with that same user data, and that's all it takes to sign up.

But it'd be a good idea to wrap this in a try catch block and render an error message if a bad username or password is used. We also need a sign out function, which is accomplished by calling auth store clear. Now let's go into the HTML and bind these functions to buttons, which is accomplished in Svelte with on click. And as one final touch, I'm also going to listen to the on submit event on the form and prevent the default action so it doesn't refresh the page when submitted. Now now.

Let's open the app dot Svelte file and declare the login component there. If we view the app in the browser, we should now see this login form. And And when you enter a username and password and click sign up, the UI should automatically rerender to show the current user's username. And now we're finally ready to build the fun part, the a real time chat messages feature. Let's go ahead and create a new component called messages.

We can import the on mount and on destroy lifecycle hooks from Svelte as well as pocket based. Our first goal here is to fetch the most recent messages, which we can represent initially as an empty array. From there, we can fetch the messages when the component is first initialized with on mount. This code will run once at the beginning of the component life cycle to make a query to the messages collection. Use git list to fetch a paginated list of messages that starts on page 1 and has 50 messages per page.

It also takes an object where you can do things like sort and filter the query. In our case, we want it sorted by that created field. What's really cool though is how easy it noticed to join in relational data. Remember, every message has a user field that points to a user record. If we want to also include the user data on every message.

We can do that with the expand option, and that means we get all the data we need without any complex SQL joins. Now the return value is a result list, and we can set our messages array as the result list items. From there, we can go went to our HTML and loop over the messages with a Svelte each block. Notice how for each message, I have the message ID in parentheses. Not.

This creates a keyed loop so Svelte can keep track of all the items in the list to render them more efficiently. For each message, I'm going to render out the message text in the database. And, also, because we joined in the user, I'm going to render out the user's username and also generate a unique a tar for each user using an awesome little service called DiceBear. Let's go ahead and try it out in the browser. I also have the pocket base admin UI side by side.

And as you can see here, not. It fetches all the messages from the database. That's pretty cool, but how do we create a new message? Let's go back into the code and set up a variable for a new message. Then define a function called send message.

For data, we'll need the text of the new message and also the current user's user ID. Remember, We can always get that by putting a dollar sign in front of it because Svelte is awesome. And now we just tell Pocket Base to create a new message. Let's go ahead and take this function and bind it to the on submit event on a form that also prevents the default action and binds the value of the text to that new message variable. Let's go ahead and open it up in the browser again and tried to create a new message.

As you can see here, it creates a new message, but we need to refresh the entire page to actually see the message, and that's not going to fly for a real time chat app. The final thing we'll do here is make these messages update in real time. Let's go back into the on mount callback, and then we'll call pocket based collection messages and subscribe to the entire collection with the star symbol. This allows us to run a callback anytime a message is created, updated or deleted. The action tells us what happened.

In our case, we want to update the UI if a new message was created or deleted. When created, we can update the messages array with that new record. One caveat with real time though is that it won't include that expanded user record, although we can easily fetch it with a one query if needed. Then for the delete action, we can filter out the ID of the message that was removed. That gives us a real time listener, but whenever working with real time, It's a good practice to unsubscribe when the data is no longer needed because otherwise, you could end up with memory leaks and unnecessary reads on the database.

Create a variable to represent a function named unsubscribe. We obtain this function from pocket base when making the call to subscribe. Once we have that function as state, We can then call it on the on destroy life cycle hook to end the subscription when the user logs out or if they navigate to a different page. Let's open up the browser and tried it out. You should now have a chat application that updates the messages feed in real time.

And now we can run npm build to build our site for production and deploy it somewhere on the Internet. In fact, because we have a single page application, we could actually do this on Linode by uploading the generated files to a storage bucket, then configuring it as a static website host. The final thing you wanna know is that as your website grows, the pocket base will need to scale vertically with more CPU and RAM to handle more and more traffic. Not. This can be easily accomplished by simply resizing your Linode.

A bigger server can handle more traffic. It can easily handle tens the thousands of concurrent users and should be more than adequate for the vast majority of projects out there. This allows you to fail over and over again as not looked her without a bunch of wasted time and money as collateral damage. Thanks for watching, and I will see you in the next one.
What you're looking at is the actual side projects directory on my computer. None of these side projects have gone on to become the next Facebook yet, but I have not failed.
I've just found hundreds of apps that don't work. If you're a developer slash entrepreneur, it's extremely important not to over engineer things. Andy Jassy once said, invention requires 2 things. 1, the ability to try lots of experiments, and 2, not having to live with the collateral damage of failed experiments. In today's video, we'll build a full stack chat app using pocket base and Svelte, then deploy it to a Linux server on Linode for just $5. I call this the Spok Stack and prepared to be amazed at how quickly it can get things done.
technology
patents
intellectual property
engineering
toys
networking
Stupidly, I made this demo public, so you can actually try it out on the Internet right now. This is not my first rodeo, and I know you guys will spam it with the most horrific comments imaginable, but this time messages can be moderated with community reactions. If a comment gets pooped on 5 times, it disappears from the UI. The back end magic behind this application is a relatively new tool called Pocketbase, which is like a free and open source ierbase written in Go that provides user authentication along with a real time database powered by SQLite. But unlike any other base not out there. It compiles everything to a single executable, and that means to self host it, all you need is one little server, which costs less than your grande soy milk macchiato. Is the ultimate sophistication. But today, we'll find out if the simplicity of pocket base can actually scale. To kick things off, we're going to start things in reverse by deploying pocket face to a Linux server in the cloud. Luckily for us, Linode has sponsored this video, which means I get to make it rain with a $100 in free credits for everyone watching in this video. For those that don't know, Linode is one of the original cloud providers that's been around since 2003. Their platform is a perfect fit for this project because like Svelte and Pocketbase, it's famous for simplicity. Unlike big cloud providers, you can get a Linux server up and running with a few clicks with flat predictable pricing that won't cause collateral damage later. After you register, go to the dashboard and click the button to create a new Linode, then then choose an image with your preferred Linux distro. I'm going with Debian, but the real Chads out there will use Arch, by the way. Then choose a region and the size of your machine. And finally, give it a password and click create. Step 1 is complete. We now have a Linux server running in the cloud. I told you that would be easy. Let's go ahead and make a note of its key address to access it on the Internet. Now, in step 2, let's deploy Pocket Base to it. 1st, download and unzip Pocket Base from the website. I'm also using Debian on my local machine, so we'll download the Linux version. Unzip it to get this single pocket based executable. You can run it by running pocket based serve, but I wanna run it in the cloud on my Linode server so I can access it from anywhere just like a platform like Fire database.
Let's open up the terminal and use secure shell to access the Linode IP address as a root user. It'll require the password you created earlier, and Now we have access to the mainframe. We're currently in the root directory, so let's go ahead and create another directory called p b.
security
And now we just need to upload the Pocket Base to this directory. We could do it with r sync or an application like Filezilla, but I think the easiest approach is to use secure copy, which will simply copy the local file over to a remote directory we just created. Run this command from a separate terminal on your local machine. Once that's done, we can go back to the terminal on the Linode machine and run the pocketbase serve command.
And to make it accessible over the Internet, we'll use the HTTP flag followed by our IP address and port 80. Congratulations. You just self hosted your own back end that you can now access over HTTP with the IP address. It serves a REST API as well as an admin dashboard that you can access with the underscore URL.
networking
However, there's a few more things I wanna show you to make it fully production ready.
The first thing I would do is bring my domain over to Linode. No. It has a fully featured DNS manager, and Pocket Base uses Let's Encrypt to automatically generate an SSL certificate to serve your back end over HTTPS. All you have to to do is add this extra flag to the serve command.
copyright licenses
Now the next thing I would consider doing is mounting a volume to the pbdata directory. Not read. This is where Pocketbase stores all of your data. A volume is just its own file system that can be moved around to different servers. On Linode, we can easily attach an extra 20 gigabytes for just $2. And then finally, I would recommend setting up a system d service to automatically restart Pocket Base whenever the server reboots.
And now it's time for step 3, where we model the data for our chat app. Navigate to your Pocket Base dashboard and create an admin user. From here, we can go to the database and by default, it has a collection for users. These are the users of your application, which contain fields like username, email, users of your application which contain fields like username, email, password, and so on. What we need is a way to create a one to many relationship between users and chat messages.
databases
data management
Create a second collection called messages and give it 2 fields. The first field is text for the message content itself, and you can add some optional server side validations here like min length and max length, while the second field, user, creates a relationship that says a message belongs to a no user.
Under the hood, Pocket Base creates a foreign key for the user ID on the messages table in the SQLite database. Go ahead and click create to update the schema. And now, you should be able to create new records in the database. That takes care of our data modeling. Now let's make it secure. Every collection in pocket base can have API rules. These rules determine who can access your data from a front end application. By default, the messages collection can only be accessed by admin users.
databases
data management
security
However, we want anybody to be able to view the messages, so let's go ahead and hit the unlock button for list and view. Users also need the ability to create new messages, but it's critical that they only create messages associated to their own user ID. We can enforce that rule by ensuring that the user property is equal to the request auth user ID.
security
And just like that, we've eliminated tons of complexity that we would need in our back end code otherwise. Not. Save the changes, then head over to the users collection. For users, we already have a bunch of rules built in, but we wanna give users the ability to view each other's profiles, So let's go ahead and remove the rules for view and list to make this data public. Now that we're somewhat secure, we can start building out the front end with Svelte. As you may know, I use Svelte to build the Fireship IO website, but it's also been used by the pocket based developers to build their admin UI as well.
It's a great fit for this project because not it's really good at building real time UIs, thanks to its built in reactive stores. Generate a new project with Vite, then select the Svelte option, and we'll also go with TypeScript. Not. Open the project, run npm install, then npm run dev to serve it locally. Then in the code, delete all the boilerplate and create a new file called pocket base in the lib directory. Whenever building a new app, I usually start by thinking about user authentication. What we'll do in this file is provide a way to listen to the current user in real time from anywhere in the application.
software development
software
To handle that, we'll install the pocket based JavaScript SDK with NPM. Once installed, we can then import it in this file as well as writable from Svelte store. Now to connect to our back end, all we have to do is initialize pocket base with the URL it's hosted at, which in this case be the Linode IP address. From there, I'm creating a variable for current user that's equal to a writable store. Its default value is the pocket base auth store model, which is equal to null when the user is not logged in or equal to that database record of the currently logged in user that contains fields like the user ID, user name and so on. Now the value of this model will change when the user signs in and signs out, and we can listen to those changes by registering a callback for the on changed event. When this event fires, we can update the Svelte store with the current model. That gives us a way to subscribe to the current user. Let's put it to use by creating a login dot spelled component. Inside this component, we'll log in a user with email and password. What's awesome about that store we just created is that been subscribed to the current value anywhere in the application reactively by putting a dollar sign in front of it. For example, we might say, if current user, render the text signed in as current user dot username. Now the question becomes, how do we sign in a user? Well, let's start by creating variables for username and password, then create an HTML form that has 2 inputs for those values. In Svelte, we can easily bind that variable to that form value with the bind value directive. Now we can access the current form value in our script. Let's create an async function called login that awaits a call to the pocket based collection of users then calls the auth with password method using the username and password as arguments. And that's all the code it takes to authenticate a user. However, we don't have a user yet, which means we'll also need another function named sign up. In this function, we'll set up some initial data for a new user like the username, password, And we can also pass a name and email address here as well or whatever custom fields you configured in Pocket Base. We can then take that data and create a new record in the user's collection. Option. Once created, we call login with that same user data, and that's all it takes to sign up. But it'd be a good idea to wrap this in a try catch block and render an error message if a bad username or password is used. We also need a sign out function, which is accomplished by calling auth store clear. Now let's go into the HTML and bind these functions to buttons, which is accomplished in Svelte with on click. And as one final touch, I'm also going to listen to the on submit event on the form and prevent the default action so it doesn't refresh the page when submitted. Now now. Let's open the app dot Svelte file and declare the login component there. If we view the app in the browser, we should now see this login form. And And when you enter a username and password and click sign up, the UI should automatically rerender to show the current user's username. And now we're finally ready to build the fun part, the a real time chat messages feature. Let's go ahead and create a new component called messages. We can import the on mount and on destroy lifecycle hooks from Svelte as well as pocket based. Our first goal here is to fetch the most recent messages, which we can represent initially as an empty array. From there, we can fetch the messages when the component is first initialized with on mount. This code will run once at the beginning of the component life cycle to make a query to the messages collection. Use git list to fetch a paginated list of messages that starts on page 1 and has 50 messages per page.
It also takes an object where you can do things like sort and filter the query. In our case, we want it sorted by that created field. What's really cool though is how easy it noticed to join in relational data. Remember, every message has a user field that points to a user record. If we want to also include the user data on every message. We can do that with the expand option, and that means we get all the data we need without any complex SQL joins. Now the return value is a result list, and we can set our messages array as the result list items.
databases
data management
data
From there, we can go went to our HTML and loop over the messages with a Svelte each block.
Notice how for each message, I have the message ID in parentheses. Not. This creates a keyed loop so Svelte can keep track of all the items in the list to render them more efficiently. For each message, I'm going to render out the message text in the database. And, also, because we joined in the user, I'm going to render out the user's username and also generate a unique a tar for each user using an awesome little service called DiceBear. Let's go ahead and try it out in the browser. I also have the pocket base admin UI side by side. And as you can see here, not. It fetches all the messages from the database. That's pretty cool, but how do we create a new message? Let's go back into the code and set up a variable for a new message. Then define a function called send message. For data, we'll need the text of the new message and also the current user's user ID. Remember, We can always get that by putting a dollar sign in front of it because Svelte is awesome. And now we just tell Pocket Base to create a new message.
programming
Let's go ahead and take this function and bind it to the on submit event on a form that also prevents the default action and binds the value of the text to that new message variable. Let's go ahead and open it up in the browser again and tried to create a new message. As you can see here, it creates a new message, but we need to refresh the entire page to actually see the message, and that's not going to fly for a real time chat app. The final thing we'll do here is make these messages update in real time. Let's go back into the on mount callback, and then we'll call pocket based collection messages and subscribe to the entire collection with the star symbol. This allows us to run a callback anytime a message is created, updated or deleted. The action tells us what happened. In our case, we want to update the UI if a new message was created or deleted. When created, we can update the messages array with that new record. One caveat with real time though is that it won't include that expanded user record, although we can easily fetch it with a one query if needed. Then for the delete action, we can filter out the ID of the message that was removed. That gives us a real time listener, but whenever working with real time, It's a good practice to unsubscribe when the data is no longer needed because otherwise, you could end up with memory leaks and unnecessary reads on the database. Create a variable to represent a function named unsubscribe. We obtain this function from pocket base when making the call to subscribe. Once we have that function as state, We can then call it on the on destroy life cycle hook to end the subscription when the user logs out or if they navigate to a different page. Let's open up the browser and tried it out. You should now have a chat application that updates the messages feed in real time. And now we can run npm build to build our site for production and deploy it somewhere on the Internet. In fact, because we have a single page application, we could actually do this on Linode by uploading the generated files to a storage bucket, then configuring it as a static website host. The final thing you wanna know is that as your website grows, the pocket base will need to scale vertically with more CPU and RAM to handle more and more traffic.
Not. This can be easily accomplished by simply resizing your Linode. A bigger server can handle more traffic. It can easily handle tens the thousands of concurrent users and should be more than adequate for the vast majority of projects out there. This allows you to fail over and over again as not looked her without a bunch of wasted time and money as collateral damage.
networking
internet
Thanks for watching, and I will see you in the next one.
What you're looking at is the actual side projects directory on my computer. None of these side projects have gone on to become the next Facebook yet, but I have not failed. I've just found hundreds of apps that don't work. If you're a developer slash entrepreneur, it's extremely important not to over engineer things. Andy Jassy once said, invention requires 2 things. 1, the ability to try lots of experiments, and 2, not having to live with the collateral damage of failed experiments. In today's video, we'll build a full stack chat app using pocket base and Svelte, then deploy it to a Linux server on Linode for just $5. I call this the Spok Stack and prepared to be amazed at how quickly it can get things done. Stupidly, I made this demo public, so you can actually try it out on the Internet right now. This is not my first rodeo, and I know you guys will spam it with the most horrific comments imaginable, but this time messages can be moderated with community reactions. If a comment gets pooped on 5 times, it disappears from the UI. The back end magic behind this application is a relatively new tool called Pocketbase, which is like a free and open source ierbase written in Go that provides user authentication along with a real time database powered by SQLite. But unlike any other base not out there. It compiles everything to a single executable, and that means to self host it, all you need is one little server, which costs less than your grande soy milk macchiato. Is the ultimate sophistication. But today, we'll find out if the simplicity of pocket base can actually scale. To kick things off, we're going to start things in reverse by deploying pocket face to a Linux server in the cloud. Luckily for us, Linode has sponsored this video, which means I get to make it rain with a $100 in free credits for everyone watching in this video. For those that don't know, Linode is one of the original cloud providers that's been around since 2003. Their platform is a perfect fit for this project because like Svelte and Pocketbase, it's famous for simplicity. Unlike big cloud providers, you can get a Linux server up and running with a few clicks with flat predictable pricing that won't cause collateral damage later. After you register, go to the dashboard and click the button to create a new Linode, then then choose an image with your preferred Linux distro. I'm going with Debian, but the real Chads out there will use Arch, by the way. Then choose a region and the size of your machine. And finally, give it a password and click create. Step 1 is complete. We now have a Linux server running in the cloud. I told you that would be easy. Let's go ahead and make a note of its key address to access it on the Internet. Now, in step 2, let's deploy Pocket Base to it. 1st, download and unzip Pocket Base from the website. I'm also using Debian on my local machine, so we'll download the Linux version. Unzip it to get this single pocket based executable. You can run it by running pocket based serve, but I wanna run it in the cloud on my Linode server so I can access it from anywhere just like a platform like Fire database. Let's open up the terminal and use secure shell to access the Linode IP address as a root user. It'll require the password you created earlier, and Now we have access to the mainframe. We're currently in the root directory, so let's go ahead and create another directory called p b. And now we just need to upload the Pocket Base to this directory. We could do it with r sync or an application like Filezilla, but I think the easiest approach is to use secure copy, which will simply copy the local file over to a remote directory we just created. Run this command from a separate terminal on your local machine. Once that's done, we can go back to the terminal on the Linode machine and run the pocketbase serve command. And to make it accessible over the Internet, we'll use the HTTP flag followed by our IP address and port 80. Congratulations. You just self hosted your own back end that you can now access over HTTP with the IP address. It serves a REST API as well as an admin dashboard that you can access with the underscore URL. However, there's a few more things I wanna show you to make it fully production ready. The first thing I would do is bring my domain over to Linode. No. It has a fully featured DNS manager, and Pocket Base uses Let's Encrypt to automatically generate an SSL certificate to serve your back end over HTTPS. All you have to to do is add this extra flag to the serve command. Now the next thing I would consider doing is mounting a volume to the pbdata directory. Not read. This is where Pocketbase stores all of your data. A volume is just its own file system that can be moved around to different servers. On Linode, we can easily attach an extra 20 gigabytes for just $2. And then finally, I would recommend setting up a system d service to automatically restart Pocket Base whenever the server reboots. And now it's time for step 3, where we model the data for our chat app. Navigate to your Pocket Base dashboard and create an admin user. From here, we can go to the database and by default, it has a collection for users. These are the users of your application, which contain fields like username, email, users of your application which contain fields like username, email, password, and so on. What we need is a way to create a one to many relationship between users and chat messages. Create a second collection called messages and give it 2 fields. The first field is text for the message content itself, and you can add some optional server side validations here like min length and max length, while the second field, user, creates a relationship that says a message belongs to a no user. Under the hood, Pocket Base creates a foreign key for the user ID on the messages table in the SQLite database. Go ahead and click create to update the schema. And now, you should be able to create new records in the database. That takes care of our data modeling. Now let's make it secure. Every collection in pocket base can have API rules. These rules determine who can access your data from a front end application. By default, the messages collection can only be accessed by admin users. However, we want anybody to be able to view the messages, so let's go ahead and hit the unlock button for list and view. Users also need the ability to create new messages, but it's critical that they only create messages associated to their own user ID. We can enforce that rule by ensuring that the user property is equal to the request auth user ID. And just like that, we've eliminated tons of complexity that we would need in our back end code otherwise. Not. Save the changes, then head over to the users collection. For users, we already have a bunch of rules built in, but we wanna give users the ability to view each other's profiles, So let's go ahead and remove the rules for view and list to make this data public. Now that we're somewhat secure, we can start building out the front end with Svelte. As you may know, I use Svelte to build the Fireship IO website, but it's also been used by the pocket based developers to build their admin UI as well. It's a great fit for this project because not it's really good at building real time UIs, thanks to its built in reactive stores. Generate a new project with Vite, then select the Svelte option, and we'll also go with TypeScript. Not. Open the project, run npm install, then npm run dev to serve it locally. Then in the code, delete all the boilerplate and create a new file called pocket base in the lib directory. Whenever building a new app, I usually start by thinking about user authentication. What we'll do in this file is provide a way to listen to the current user in real time from anywhere in the application. To handle that, we'll install the pocket based JavaScript SDK with NPM. Once installed, we can then import it in this file as well as writable from Svelte store. Now to connect to our back end, all we have to do is initialize pocket base with the URL it's hosted at, which in this case be the Linode IP address. From there, I'm creating a variable for current user that's equal to a writable store. Its default value is the pocket base auth store model, which is equal to null when the user is not logged in or equal to that database record of the currently logged in user that contains fields like the user ID, user name and so on. Now the value of this model will change when the user signs in and signs out, and we can listen to those changes by registering a callback for the on changed event. When this event fires, we can update the Svelte store with the current model. That gives us a way to subscribe to the current user. Let's put it to use by creating a login dot spelled component. Inside this component, we'll log in a user with email and password. What's awesome about that store we just created is that been subscribed to the current value anywhere in the application reactively by putting a dollar sign in front of it. For example, we might say, if current user, render the text signed in as current user dot username. Now the question becomes, how do we sign in a user? Well, let's start by creating variables for username and password, then create an HTML form that has 2 inputs for those values. In Svelte, we can easily bind that variable to that form value with the bind value directive. Now we can access the current form value in our script. Let's create an async function called login that awaits a call to the pocket based collection of users then calls the auth with password method using the username and password as arguments. And that's all the code it takes to authenticate a user. However, we don't have a user yet, which means we'll also need another function named sign up. In this function, we'll set up some initial data for a new user like the username, password, And we can also pass a name and email address here as well or whatever custom fields you configured in Pocket Base. We can then take that data and create a new record in the user's collection. Option. Once created, we call login with that same user data, and that's all it takes to sign up. But it'd be a good idea to wrap this in a try catch block and render an error message if a bad username or password is used. We also need a sign out function, which is accomplished by calling auth store clear. Now let's go into the HTML and bind these functions to buttons, which is accomplished in Svelte with on click. And as one final touch, I'm also going to listen to the on submit event on the form and prevent the default action so it doesn't refresh the page when submitted. Now now. Let's open the app dot Svelte file and declare the login component there. If we view the app in the browser, we should now see this login form. And And when you enter a username and password and click sign up, the UI should automatically rerender to show the current user's username. And now we're finally ready to build the fun part, the a real time chat messages feature. Let's go ahead and create a new component called messages. We can import the on mount and on destroy lifecycle hooks from Svelte as well as pocket based. Our first goal here is to fetch the most recent messages, which we can represent initially as an empty array. From there, we can fetch the messages when the component is first initialized with on mount. This code will run once at the beginning of the component life cycle to make a query to the messages collection. Use git list to fetch a paginated list of messages that starts on page 1 and has 50 messages per page. It also takes an object where you can do things like sort and filter the query. In our case, we want it sorted by that created field. What's really cool though is how easy it noticed to join in relational data. Remember, every message has a user field that points to a user record. If we want to also include the user data on every message. We can do that with the expand option, and that means we get all the data we need without any complex SQL joins. Now the return value is a result list, and we can set our messages array as the result list items. From there, we can go went to our HTML and loop over the messages with a Svelte each block. Notice how for each message, I have the message ID in parentheses. Not. This creates a keyed loop so Svelte can keep track of all the items in the list to render them more efficiently. For each message, I'm going to render out the message text in the database. And, also, because we joined in the user, I'm going to render out the user's username and also generate a unique a tar for each user using an awesome little service called DiceBear. Let's go ahead and try it out in the browser. I also have the pocket base admin UI side by side. And as you can see here, not. It fetches all the messages from the database. That's pretty cool, but how do we create a new message? Let's go back into the code and set up a variable for a new message. Then define a function called send message. For data, we'll need the text of the new message and also the current user's user ID. Remember, We can always get that by putting a dollar sign in front of it because Svelte is awesome. And now we just tell Pocket Base to create a new message. Let's go ahead and take this function and bind it to the on submit event on a form that also prevents the default action and binds the value of the text to that new message variable. Let's go ahead and open it up in the browser again and tried to create a new message. As you can see here, it creates a new message, but we need to refresh the entire page to actually see the message, and that's not going to fly for a real time chat app. The final thing we'll do here is make these messages update in real time. Let's go back into the on mount callback, and then we'll call pocket based collection messages and subscribe to the entire collection with the star symbol. This allows us to run a callback anytime a message is created, updated or deleted. The action tells us what happened. In our case, we want to update the UI if a new message was created or deleted. When created, we can update the messages array with that new record. One caveat with real time though is that it won't include that expanded user record, although we can easily fetch it with a one query if needed. Then for the delete action, we can filter out the ID of the message that was removed. That gives us a real time listener, but whenever working with real time, It's a good practice to unsubscribe when the data is no longer needed because otherwise, you could end up with memory leaks and unnecessary reads on the database. Create a variable to represent a function named unsubscribe. We obtain this function from pocket base when making the call to subscribe. Once we have that function as state, We can then call it on the on destroy life cycle hook to end the subscription when the user logs out or if they navigate to a different page. Let's open up the browser and tried it out. You should now have a chat application that updates the messages feed in real time. And now we can run npm build to build our site for production and deploy it somewhere on the Internet. In fact, because we have a single page application, we could actually do this on Linode by uploading the generated files to a storage bucket, then configuring it as a static website host. The final thing you wanna know is that as your website grows, the pocket base will need to scale vertically with more CPU and RAM to handle more and more traffic. Not. This can be easily accomplished by simply resizing your Linode. A bigger server can handle more traffic. It can easily handle tens the thousands of concurrent users and should be more than adequate for the vast majority of projects out there. This allows you to fail over and over again as not looked her without a bunch of wasted time and money as collateral damage. Thanks for watching, and I will see you in the next one.
What
what
you're
you're
looking
looking
at
at
is
is
the
the
actual
actual
side
side
projects
projects
directory
directory
on
on
my
my
computer.
computer
None
none
of
of
these
these
side
side
projects
projects
have
have
gone
gone
on
on
to
to
become
become
the
the
next
next
Facebook
facebook
yet,
yet
but
but
I
i
have
have
not
not
failed.
failed
I've
i've
just
just
found
found
hundreds
hundreds
of
of
apps
apps
that
that
don't
don't
work.
work
If
if
you're
you're
a
a
developer
developer
slash
slash
entrepreneur,
entrepreneur
it's
it's
extremely
extremely
important
important
not
not
to
to
over
over
engineer
engineer
things.
things
Andy
andy
Jassy
jassy
once
once
said,
said
invention
invention
requires
requires
2
2
things.
things
1,
1
the
the
ability
ability
to
to
try
try
lots
lots
of
of
experiments,
experiments
and
and
2,
2
not
not
having
having
to
to
live
live
with
with
the
the
collateral
collateral
damage
damage
of
of
failed
failed
experiments.
experiments
In
in
today's
today's
video,
video
we'll
we'll
build
build
a
a
full
full
stack
stack
chat
chat
app
app
using
using
pocket
pocket
base
base
and
and
Svelte,
svelte
then
then
deploy
deploy
it
it
to
to
a
a
Linux
linux
server
server
on
on
Linode
linode
for
for
just
just
$5.
$5
I
i
call
call
this
this
the
the
Spok
spok
Stack
stack
and
and
prepared
prepared
to
to
be
be
amazed
amazed
at
at
how
how
quickly
quickly
it
it
can
can
get
get
things
things
done.
done
Stupidly,
stupidly
I
i
made
made
this
this
demo
demo
public,
public
so
so
you
you
can
can
actually
actually
try
try
it
it
out
out
on
on
the
the
Internet
internet
right
right
now.
now
This
this
is
is
not
not
my
my
first
first
rodeo,
rodeo
and
and
I
i
know
know
you
you
guys
guys
will
will
spam
spam
it
it
with
with
the
the
most
most
horrific
horrific
comments
comments
imaginable,
imaginable
but
but
this
this
time
time
messages
messages
can
can
be
be
moderated
moderated
with
with
community
community
reactions.
reactions
If
if
a
a
comment
comment
gets
gets
pooped
pooped
on
on
5
5
times,
times
it
it
disappears
disappears
from
from
the
the
UI.
ui
The
the
back
back
end
end
magic
magic
behind
behind
this
this
application
application
is
is
a
a
relatively
relatively
new
new
tool
tool
called
called
Pocketbase,
pocketbase
which
which
is
is
like
like
a
a
free
free
and
and
open
open
source
source
ierbase
ierbase
written
written
in
in
Go
go
that
that
provides
provides
user
user
authentication
authentication
along
along
with
with
a
a
real
real
time
time
database
database
powered
powered
by
by
SQLite.
sqlite
But
but
unlike
unlike
any
any
other
other
base
base
not
not
out
out
there.
there
It
it
compiles
compiles
everything
everything
to
to
a
a
single
single
executable,
executable
and
and
that
that
means
means
to
to
self
self
host
host
it,
it
all
all
you
you
need
need
is
is
one
one
little
little
server,
server
which
which
costs
costs
less
less
than
than
your
your
grande
grande
soy
soy
milk
milk
macchiato.
macchiato
Is
is
the
the
ultimate
ultimate
sophistication.
sophistication
But
but
today,
today
we'll
we'll
find
find
out
out
if
if
the
the
simplicity
simplicity
of
of
pocket
pocket
base
base
can
can
actually
actually
scale.
scale
To
to
kick
kick
things
things
off,
off
we're
we're
going
going
to
to
start
start
things
things
in
in
reverse
reverse
by
by
deploying
deploying
pocket
pocket
face
face
to
to
a
a
Linux
linux
server
server
in
in
the
the
cloud.
cloud
Luckily
luckily
for
for
us,
us
Linode
linode
has
has
sponsored
sponsored
this
this
video,
video
which
which
means
means
I
i
get
get
to
to
make
make
it
it
rain
rain
with
with
a
a
$100
$100
in
in
free
free
credits
credits
for
for
everyone
everyone
watching
watching
in
in
this
this
video.
video
For
for
those
those
that
that
don't
don't
know,
know
Linode
linode
is
is
one
one
of
of
the
the
original
original
cloud
cloud
providers
providers
that's
that's
been
been
around
around
since
since
2003.
2003
Their
their
platform
platform
is
is
a
a
perfect
perfect
fit
fit
for
for
this
this
project
project
because
because
like
like
Svelte
svelte
and
and
Pocketbase,
pocketbase
it's
it's
famous
famous
for
for
simplicity.
simplicity
Unlike
unlike
big
big
cloud
cloud
providers,
providers
you
you
can
can
get
get
a
a
Linux
linux
server
server
up
up
and
and
running
running
with
with
a
a
few
few
clicks
clicks
with
with
flat
flat
predictable
predictable
pricing
pricing
that
that
won't
won't
cause
cause
collateral
collateral
damage
damage
later.
later
After
after
you
you
register,
register
go
go
to
to
the
the
dashboard
dashboard
and
and
click
click
the
the
button
button
to
to
create
create
a
a
new
new
Linode,
linode
then
then
then
then
choose
choose
an
an
image
image
with
with
your
your
preferred
preferred
Linux
linux
distro.
distro
I'm
i'm
going
going
with
with
Debian,
debian
but
but
the
the
real
real
Chads
chads
out
out
there
there
will
will
use
use
Arch,
arch
by
by
the
the
way.
way
Then
then
choose
choose
a
a
region
region
and
and
the
the
size
size
of
of
your
your
machine.
machine
And
and
finally,
finally
give
give
it
it
a
a
password
password
and
and
click
click
create.
create
Step
step
1
1
is
is
complete.
complete
We
we
now
now
have
have
a
a
Linux
linux
server
server
running
running
in
in
the
the
cloud.
cloud
I
i
told
told
you
you
that
that
would
would
be
be
easy.
easy
Let's
let's
go
go
ahead
ahead
and
and
make
make
a
a
note
note
of
of
its
its
key
key
address
address
to
to
access
access
it
it
on
on
the
the
Internet.
internet
Now,
now
in
in
step
step
2,
2
let's
let's
deploy
deploy
Pocket
pocket
Base
base
to
to
it.
it
1st,
1st
download
download
and
and
unzip
unzip
Pocket
pocket
Base
base
from
from
the
the
website.
website
I'm
i'm
also
also
using
using
Debian
debian
on
on
my
my
local
local
machine,
machine
so
so
we'll
we'll
download
download
the
the
Linux
linux
version.
version
Unzip
unzip
it
it
to
to
get
get
this
this
single
single
pocket
pocket
based
based
executable.
executable
You
you
can
can
run
run
it
it
by
by
running
running
pocket
pocket
based
based
serve,
serve
but
but
I
i
wanna
wanna
run
run
it
it
in
in
the
the
cloud
cloud
on
on
my
my
Linode
linode
server
server
so
so
I
i
can
can
access
access
it
it
from
from
anywhere
anywhere
just
just
like
like
a
a
platform
platform
like
like
Fire
fire
database.
database
Let's
let's
open
open
up
up
the
the
terminal
terminal
and
and
use
use
secure
secure
shell
shell
to
to
access
access
the
the
Linode
linode
IP
ip
address
address
as
as
a
a
root
root
user.
user
It'll
it'll
require
require
the
the
password
password
you
you
created
created
earlier,
earlier
and
and
Now
now
we
we
have
have
access
access
to
to
the
the
mainframe.
mainframe
We're
we're
currently
currently
in
in
the
the
root
root
directory,
directory
so
so
let's
let's
go
go
ahead
ahead
and
and
create
create
another
another
directory
directory
called
called
p
p
b.
b
And
and
now
now
we
we
just
just
need
need
to
to
upload
upload
the
the
Pocket
pocket
Base
base
to
to
this
this
directory.
directory
We
we
could
could
do
do
it
it
with
with
r
r
sync
sync
or
or
an
an
application
application
like
like
Filezilla,
filezilla
but
but
I
i
think
think
the
the
easiest
easiest
approach
approach
is
is
to
to
use
use
secure
secure
copy,
copy
which
which
will
will
simply
simply
copy
copy
the
the
local
local
file
file
over
over
to
to
a
a
remote
remote
directory
directory
we
we
just
just
created.
created
Run
run
this
this
command
command
from
from
a
a
separate
separate
terminal
terminal
on
on
your
your
local
local
machine.
machine
Once
once
that's
that's
done,
done
we
we
can
can
go
go
back
back
to
to
the
the
terminal
terminal
on
on
the
the
Linode
linode
machine
machine
and
and
run
run
the
the
pocketbase
pocketbase
serve
serve
command.
command
And
and
to
to
make
make
it
it
accessible
accessible
over
over
the
the
Internet,
internet
we'll
we'll
use
use
the
the
HTTP
http
flag
flag
followed
followed
by
by
our
our
IP
ip
address
address
and
and
port
port
80.
80
Congratulations.
congratulations
You
you
just
just
self
self
hosted
hosted
your
your
own
own
back
back
end
end
that
that
you
you
can
can
now
now
access
access
over
over
HTTP
http
with
with
the
the
IP
ip
address.
address
It
it
serves
serves
a
a
REST
rest
API
api
as
as
well
well
as
as
an
an
admin
admin
dashboard
dashboard
that
that
you
you
can
can
access
access
with
with
the
the
underscore
underscore
URL.
url
However,
however
there's
there's
a
a
few
few
more
more
things
things
I
i
wanna
wanna
show
show
you
you
to
to
make
make
it
it
fully
fully
production
production
ready.
ready
The
the
first
first
thing
thing
I
i
would
would
do
do
is
is
bring
bring
my
my
domain
domain
over
over
to
to
Linode.
linode
No.
no
It
it
has
has
a
a
fully
fully
featured
featured
DNS
dns
manager,
manager
and
and
Pocket
pocket
Base
base
uses
uses
Let's
let's
Encrypt
encrypt
to
to
automatically
automatically
generate
generate
an
an
SSL
ssl
certificate
certificate
to
to
serve
serve
your
your
back
back
end
end
over
over
HTTPS.
https
All
all
you
you
have
have
to
to
to
to
do
do
is
is
add
add
this
this
extra
extra
flag
flag
to
to
the
the
serve
serve
command.
command
Now
now
the
the
next
next
thing
thing
I
i
would
would
consider
consider
doing
doing
is
is
mounting
mounting
a
a
volume
volume
to
to
the
the
pbdata
pbdata
directory.
directory
Not
not
read.
read
This
this
is
is
where
where
Pocketbase
pocketbase
stores
stores
all
all
of
of
your
your
data.
data
A
a
volume
volume
is
is
just
just
its
its
own
own
file
file
system
system
that
that
can
can
be
be
moved
moved
around
around
to
to
different
different
servers.
servers
On
on
Linode,
linode
we
we
can
can
easily
easily
attach
attach
an
an
extra
extra
20
20
gigabytes
gigabytes
for
for
just
just
$2.
$2
And
and
then
then
finally,
finally
I
i
would
would
recommend
recommend
setting
setting
up
up
a
a
system
system
d
d
service
service
to
to
automatically
automatically
restart
restart
Pocket
pocket
Base
base
whenever
whenever
the
the
server
server
reboots.
reboots
And
and
now
now
it's
it's
time
time
for
for
step
step
3,
3
where
where
we
we
model
model
the
the
data
data
for
for
our
our
chat
chat
app.
app
Navigate
navigate
to
to
your
your
Pocket
pocket
Base
base
dashboard
dashboard
and
and
create
create
an
an
admin
admin
user.
user
From
from
here,
here
we
we
can
can
go
go
to
to
the
the
database
database
and
and
by
by
default,
default
it
it
has
has
a
a
collection
collection
for
for
users.
users
These
these
are
are
the
the
users
users
of
of
your
your
application,
application
which
which
contain
contain
fields
fields
like
like
username,
username
email,
email
users
users
of
of
your
your
application
application
which
which
contain
contain
fields
fields
like
like
username,
username
email,
email
password,
password
and
and
so
so
on.
on
What
what
we
we
need
need
is
is
a
a
way
way
to
to
create
create
a
a
one
one
to
to
many
many
relationship
relationship
between
between
users
users
and
and
chat
chat
messages.
messages
Create
create
a
a
second
second
collection
collection
called
called
messages
messages
and
and
give
give
it
it
2
2
fields.
fields
The
the
first
first
field
field
is
is
text
text
for
for
the
the
message
message
content
content
itself,
itself
and
and
you
you
can
can
add
add
some
some
optional
optional
server
server
side
side
validations
validations
here
here
like
like
min
min
length
length
and
and
max
max
length,
length
while
while
the
the
second
second
field,
field
user,
user
creates
creates
a
a
relationship
relationship
that
that
says
says
a
a
message
message
belongs
belongs
to
to
a
a
no
no
user.
user
Under
under
the
the
hood,
hood
Pocket
pocket
Base
base
creates
creates
a
a
foreign
foreign
key
key
for
for
the
the
user
user
ID
id
on
on
the
the
messages
messages
table
table
in
in
the
the
SQLite
sqlite
database.
database
Go
go
ahead
ahead
and
and
click
click
create
create
to
to
update
update
the
the
schema.
schema
And
and
now,
now
you
you
should
should
be
be
able
able
to
to
create
create
new
new
records
records
in
in
the
the
database.
database
That
that
takes
takes
care
care
of
of
our
our
data
data
modeling.
modeling
Now
now
let's
let's
make
make
it
it
secure.
secure
Every
every
collection
collection
in
in
pocket
pocket
base
base
can
can
have
have
API
api
rules.
rules
These
these
rules
rules
determine
determine
who
who
can
can
access
access
your
your
data
data
from
from
a
a
front
front
end
end
application.
application
By
by
default,
default
the
the
messages
messages
collection
collection
can
can
only
only
be
be
accessed
accessed
by
by
admin
admin
users.
users
However,
however
we
we
want
want
anybody
anybody
to
to
be
be
able
able
to
to
view
view
the
the
messages,
messages
so
so
let's
let's
go
go
ahead
ahead
and
and
hit
hit
the
the
unlock
unlock
button
button
for
for
list
list
and
and
view.
view
Users
users
also
also
need
need
the
the
ability
ability
to
to
create
create
new
new
messages,
messages
but
but
it's
it's
critical
critical
that
that
they
they
only
only
create
create
messages
messages
associated
associated
to
to
their
their
own
own
user
user
ID.
id
We
we
can
can
enforce
enforce
that
that
rule
rule
by
by
ensuring
ensuring
that
that
the
the
user
user
property
property
is
is
equal
equal
to
to
the
the
request
request
auth
auth
user
user
ID.
id
And
and
just
just
like
like
that,
that
we've
we've
eliminated
eliminated
tons
tons
of
of
complexity
complexity
that
that
we
we
would
would
need
need
in
in
our
our
back
back
end
end
code
code
otherwise.
otherwise
Not.
not
Save
save
the
the
changes,
changes
then
then
head
head
over
over
to
to
the
the
users
users
collection.
collection
For
for
users,
users
we
we
already
already
have
have
a
a
bunch
bunch
of
of
rules
rules
built
built
in,
in
but
but
we
we
wanna
wanna
give
give
users
users
the
the
ability
ability
to
to
view
view
each
each
other's
other's
profiles,
profiles
So
so
let's
let's
go
go
ahead
ahead
and
and
remove
remove
the
the
rules
rules
for
for
view
view
and
and
list
list
to
to
make
make
this
this
data
data
public.
public
Now
now
that
that
we're
we're
somewhat
somewhat
secure,
secure
we
we
can
can
start
start
building
building
out
out
the
the
front
front
end
end
with
with
Svelte.
svelte
As
as
you
you
may
may
know,
know
I
i
use
use
Svelte
svelte
to
to
build
build
the
the
Fireship
fireship
IO
io
website,
website
but
but
it's
it's
also
also
been
been
used
used
by
by
the
the
pocket
pocket
based
based
developers
developers
to
to
build
build
their
their
admin
admin
UI
ui
as
as
well.
well
It's
it's
a
a
great
great
fit
fit
for
for
this
this
project
project
because
because
not
not
it's
it's
really
really
good
good
at
at
building
building
real
real
time
time
UIs,
uis
thanks
thanks
to
to
its
its
built
built
in
in
reactive
reactive
stores.
stores
Generate
generate
a
a
new
new
project
project
with
with
Vite,
vite
then
then
select
select
the
the
Svelte
svelte
option,
option
and
and
we'll
we'll
also
also
go
go
with
with
TypeScript.
typescript
Not.
not
Open
open
the
the
project,
project
run
run
npm
npm
install,
install
then
then
npm
npm
run
run
dev
dev
to
to
serve
serve
it
it
locally.
locally
Then
then
in
in
the
the
code,
code
delete
delete
all
all
the
the
boilerplate
boilerplate
and
and
create
create
a
a
new
new
file
file
called
called
pocket
pocket
base
base
in
in
the
the
lib
lib
directory.
directory
Whenever
whenever
building
building
a
a
new
new
app,
app
I
i
usually
usually
start
start
by
by
thinking
thinking
about
about
user
user
authentication.
authentication
What
what
we'll
we'll
do
do
in
in
this
this
file
file
is
is
provide
provide
a
a
way
way
to
to
listen
listen
to
to
the
the
current
current
user
user
in
in
real
real
time
time
from
from
anywhere
anywhere
in
in
the
the
application.
application
To
to
handle
handle
that,
that
we'll
we'll
install
install
the
the
pocket
pocket
based
based
JavaScript
javascript
SDK
sdk
with
with
NPM.
npm
Once
once
installed,
installed
we
we
can
can
then
then
import
import
it
it
in
in
this
this
file
file
as
as
well
well
as
as
writable
writable
from
from
Svelte
svelte
store.
store
Now
now
to
to
connect
connect
to
to
our
our
back
back
end,
end
all
all
we
we
have
have
to
to
do
do
is
is
initialize
initialize
pocket
pocket
base
base
with
with
the
the
URL
url
it's
it's
hosted
hosted
at,
at
which
which
in
in
this
this
case
case
be
be
the
the
Linode
linode
IP
ip
address.
address
From
from
there,
there
I'm
i'm
creating
creating
a
a
variable
variable
for
for
current
current
user
user
that's
that's
equal
equal
to
to
a
a
writable
writable
store.
store
Its
its
default
default
value
value
is
is
the
the
pocket
pocket
base
base
auth
auth
store
store
model,
model
which
which
is
is
equal
equal
to
to
null
null
when
when
the
the
user
user
is
is
not
not
logged
logged
in
in
or
or
equal
equal
to
to
that
that
database
database
record
record
of
of
the
the
currently
currently
logged
logged
in
in
user
user
that
that
contains
contains
fields
fields
like
like
the
the
user
user
ID,
id
user
user
name
name
and
and
so
so
on.
on
Now
now
the
the
value
value
of
of
this
this
model
model
will
will
change
change
when
when
the
the
user
user
signs
signs
in
in
and
and
signs
signs
out,
out
and
and
we
we
can
can
listen
listen
to
to
those
those
changes
changes
by
by
registering
registering
a
a
callback
callback
for
for
the
the
on
on
changed
changed
event.
event
When
when
this
this
event
event
fires,
fires
we
we
can
can
update
update
the
the
Svelte
svelte
store
store
with
with
the
the
current
current
model.
model
That
that
gives
gives
us
us
a
a
way
way
to
to
subscribe
subscribe
to
to
the
the
current
current
user.
user
Let's
let's
put
put
it
it
to
to
use
use
by
by
creating
creating
a
a
login
login
dot
dot
spelled
spelled
component.
component
Inside
inside
this
this
component,
component
we'll
we'll
log
log
in
in
a
a
user
user
with
with
email
email
and
and
password.
password
What's
what's
awesome
awesome
about
about
that
that
store
store
we
we
just
just
created
created
is
is
that
that
been
been
subscribed
subscribed
to
to
the
the
current
current
value
value
anywhere
anywhere
in
in
the
the
application
application
reactively
reactively
by
by
putting
putting
a
a
dollar
dollar
sign
sign
in
in
front
front
of
of
it.
it
For
for
example,
example
we
we
might
might
say,
say
if
if
current
current
user,
user
render
render
the
the
text
text
signed
signed
in
in
as
as
current
current
user
user
dot
dot
username.
username
Now
now
the
the
question
question
becomes,
becomes
how
how
do
do
we
we
sign
sign
in
in
a
a
user?
user
Well,
well
let's
let's
start
start
by
by
creating
creating
variables
variables
for
for
username
username
and
and
password,
password
then
then
create
create
an
an
HTML
html
form
form
that
that
has
has
2
2
inputs
inputs
for
for
those
those
values.
values
In
in
Svelte,
svelte
we
we
can
can
easily
easily
bind
bind
that
that
variable
variable
to
to
that
that
form
form
value
value
with
with
the
the
bind
bind
value
value
directive.
directive
Now
now
we
we
can
can
access
access
the
the
current
current
form
form
value
value
in
in
our
our
script.
script
Let's
let's
create
create
an
an
async
async
function
function
called
called
login
login
that
that
awaits
awaits
a
a
call
call
to
to
the
the
pocket
pocket
based
based
collection
collection
of
of
users
users
then
then
calls
calls
the
the
auth
auth
with
with
password
password
method
method
using
using
the
the
username
username
and
and
password
password
as
as
arguments.
arguments
And
and
that's
that's
all
all
the
the
code
code
it
it
takes
takes
to
to
authenticate
authenticate
a
a
user.
user
However,
however
we
we
don't
don't
have
have
a
a
user
user
yet,
yet
which
which
means
means
we'll
we'll
also
also
need
need
another
another
function
function
named
named
sign
sign
up.
up
In
in
this
this
function,
function
we'll
we'll
set
set
up
up
some
some
initial
initial
data
data
for
for
a
a
new
new
user
user
like
like
the
the
username,
username
password,
password
And
and
we
we
can
can
also
also
pass
pass
a
a
name
name
and
and
email
email
address
address
here
here
as
as
well
well
or
or
whatever
whatever
custom
custom
fields
fields
you
you
configured
configured
in
in
Pocket
pocket
Base.
base
We
we
can
can
then
then
take
take
that
that
data
data
and
and
create
create
a
a
new
new
record
record
in
in
the
the
user's
user's
collection.
collection
Option.
option
Once
once
created,
created
we
we
call
call
login
login
with
with
that
that
same
same
user
user
data,
data
and
and
that's
that's
all
all
it
it
takes
takes
to
to
sign
sign
up.
up
But
but
it'd
it'd
be
be
a
a
good
good
idea
idea
to
to
wrap
wrap
this
this
in
in
a
a
try
try
catch
catch
block
block
and
and
render
render
an
an
error
error
message
message
if
if
a
a
bad
bad
username
username
or
or
password
password
is
is
used.
used
We
we
also
also
need
need
a
a
sign
sign
out
out
function,
function
which
which
is
is
accomplished
accomplished
by
by
calling
calling
auth
auth
store
store
clear.
clear
Now
now
let's
let's
go
go
into
into
the
the
HTML
html
and
and
bind
bind
these
these
functions
functions
to
to
buttons,
buttons
which
which
is
is
accomplished
accomplished
in
in
Svelte
svelte
with
with
on
on
click.
click
And
and
as
as
one
one
final
final
touch,
touch
I'm
i'm
also
also
going
going
to
to
listen
listen
to
to
the
the
on
on
submit
submit
event
event
on
on
the
the
form
form
and
and
prevent
prevent
the
the
default
default
action
action
so
so
it
it
doesn't
doesn't
refresh
refresh
the
the
page
page
when
when
submitted.
submitted
Now
now
now.
now
Let's
let's
open
open
the
the
app
app
dot
dot
Svelte
svelte
file
file
and
and
declare
declare
the
the
login
login
component
component
there.
there
If
if
we
we
view
view
the
the
app
app
in
in
the
the
browser,
browser
we
we
should
should
now
now
see
see
this
this
login
login
form.
form
And
and
And
and
when
when
you
you
enter
enter
a
a
username
username
and
and
password
password
and
and
click
click
sign
sign
up,
up
the
the
UI
ui
should
should
automatically
automatically
rerender
rerender
to
to
show
show
the
the
current
current
user's
user's
username.
username
And
and
now
now
we're
we're
finally
finally
ready
ready
to
to
build
build
the
the
fun
fun
part,
part
the
the
a
a
real
real
time
time
chat
chat
messages
messages
feature.
feature
Let's
let's
go
go
ahead
ahead
and
and
create
create
a
a
new
new
component
component
called
called
messages.
messages
We
we
can
can
import
import
the
the
on
on
mount
mount
and
and
on
on
destroy
destroy
lifecycle
lifecycle
hooks
hooks
from
from
Svelte
svelte
as
as
well
well
as
as
pocket
pocket
based.
based
Our
our
first
first
goal
goal
here
here
is
is
to
to
fetch
fetch
the
the
most
most
recent
recent
messages,
messages
which
which
we
we
can
can
represent
represent
initially
initially
as
as
an
an
empty
empty
array.
array
From
from
there,
there
we
we
can
can
fetch
fetch
the
the
messages
messages
when
when
the
the
component
component
is
is
first
first
initialized
initialized
with
with
on
on
mount.
mount
This
this
code
code
will
will
run
run
once
once
at
at
the
the
beginning
beginning
of
of
the
the
component
component
life
life
cycle
cycle
to
to
make
make
a
a
query
query
to
to
the
the
messages
messages
collection.
collection
Use
use
git
git
list
list
to
to
fetch
fetch
a
a
paginated
paginated
list
list
of
of
messages
messages
that
that
starts
starts
on
on
page
page
1
1
and
and
has
has
50
50
messages
messages
per
per
page.
page
It
it
also
also
takes
takes
an
an
object
object
where
where
you
you
can
can
do
do
things
things
like
like
sort
sort
and
and
filter
filter
the
the
query.
query
In
in
our
our
case,
case
we
we
want
want
it
it
sorted
sorted
by
by
that
that
created
created
field.
field
What's
what's
really
really
cool
cool
though
though
is
is
how
how
easy
easy
it
it
noticed
noticed
to
to
join
join
in
in
relational
relational
data.
data
Remember,
remember
every
every
message
message
has
has
a
a
user
user
field
field
that
that
points
points
to
to
a
a
user
user
record.
record
If
if
we
we
want
want
to
to
also
also
include
include
the
the
user
user
data
data
on
on
every
every
message.
message
We
we
can
can
do
do
that
that
with
with
the
the
expand
expand
option,
option
and
and
that
that
means
means
we
we
get
get
all
all
the
the
data
data
we
we
need
need
without
without
any
any
complex
complex
SQL
sql
joins.
joins
Now
now
the
the
return
return
value
value
is
is
a
a
result
result
list,
list
and
and
we
we
can
can
set
set
our
our
messages
messages
array
array
as
as
the
the
result
result
list
list
items.
items
From
from
there,
there
we
we
can
can
go
go
went
went
to
to
our
our
HTML
html
and
and
loop
loop
over
over
the
the
messages
messages
with
with
a
a
Svelte
svelte
each
each
block.
block
Notice
notice
how
how
for
for
each
each
message,
message
I
i
have
have
the
the
message
message
ID
id
in
in
parentheses.
parentheses
Not.
not
This
this
creates
creates
a
a
keyed
keyed
loop
loop
so
so
Svelte
svelte
can
can
keep
keep
track
track
of
of
all
all
the
the
items
items
in
in
the
the
list
list
to
to
render
render
them
them
more
more
efficiently.
efficiently
For
for
each
each
message,
message
I'm
i'm
going
going
to
to
render
render
out
out
the
the
message
message
text
text
in
in
the
the
database.
database
And,
and
also,
also
because
because
we
we
joined
joined
in
in
the
the
user,
user
I'm
i'm
going
going
to
to
render
render
out
out
the
the
user's
user's
username
username
and
and
also
also
generate
generate
a
a
unique
unique
a
a
tar
tar
for
for
each
each
user
user
using
using
an
an
awesome
awesome
little
little
service
service
called
called
DiceBear.
dicebear
Let's
let's
go
go
ahead
ahead
and
and
try
try
it
it
out
out
in
in
the
the
browser.
browser
I
i
also
also
have
have
the
the
pocket
pocket
base
base
admin
admin
UI
ui
side
side
by
by
side.
side
And
and
as
as
you
you
can
can
see
see
here,
here
not.
not
It
it
fetches
fetches
all
all
the
the
messages
messages
from
from
the
the
database.
database
That's
that's
pretty
pretty
cool,
cool
but
but
how
how
do
do
we
we
create
create
a
a
new
new
message?
message
Let's
let's
go
go
back
back
into
into
the
the
code
code
and
and
set
set
up
up
a
a
variable
variable
for
for
a
a
new
new
message.
message
Then
then
define
define
a
a
function
function
called
called
send
send
message.
message
For
for
data,
data
we'll
we'll
need
need
the
the
text
text
of
of
the
the
new
new
message
message
and
and
also
also
the
the
current
current
user's
user's
user
user
ID.
id
Remember,
remember
We
we
can
can
always
always
get
get
that
that
by
by
putting
putting
a
a
dollar
dollar
sign
sign
in
in
front
front
of
of
it
it
because
because
Svelte
svelte
is
is
awesome.
awesome
And
and
now
now
we
we
just
just
tell
tell
Pocket
pocket
Base
base
to
to
create
create
a
a
new
new
message.
message
Let's
let's
go
go
ahead
ahead
and
and
take
take
this
this
function
function
and
and
bind
bind
it
it
to
to
the
the
on
on
submit
submit
event
event
on
on
a
a
form
form
that
that
also
also
prevents
prevents
the
the
default
default
action
action
and
and
binds
binds
the
the
value
value
of
of
the
the
text
text
to
to
that
that
new
new
message
message
variable.
variable
Let's
let's
go
go
ahead
ahead
and
and
open
open
it
it
up
up
in
in
the
the
browser
browser
again
again
and
and
tried
tried
to
to
create
create
a
a
new
new
message.
message
As
as
you
you
can
can
see
see
here,
here
it
it
creates
creates
a
a
new
new
message,
message
but
but
we
we
need
need
to
to
refresh
refresh
the
the
entire
entire
page
page
to
to
actually
actually
see
see
the
the
message,
message
and
and
that's
that's
not
not
going
going
to
to
fly
fly
for
for
a
a
real
real
time
time
chat
chat
app.
app
The
the
final
final
thing
thing
we'll
we'll
do
do
here
here
is
is
make
make
these
these
messages
messages
update
update
in
in
real
real
time.
time
Let's
let's
go
go
back
back
into
into
the
the
on
on
mount
mount
callback,
callback
and
and
then
then
we'll
we'll
call
call
pocket
pocket
based
based
collection
collection
messages
messages
and
and
subscribe
subscribe
to
to
the
the
entire
entire
collection
collection
with
with
the
the
star
star
symbol.
symbol
This
this
allows
allows
us
us
to
to
run
run
a
a
callback
callback
anytime
anytime
a
a
message
message
is
is
created,
created
updated
updated
or
or
deleted.
deleted
The
the
action
action
tells
tells
us
us
what
what
happened.
happened
In
in
our
our
case,
case
we
we
want
want
to
to
update
update
the
the
UI
ui
if
if
a
a
new
new
message
message
was
was
created
created
or
or
deleted.
deleted
When
when
created,
created
we
we
can
can
update
update
the
the
messages
messages
array
array
with
with
that
that
new
new
record.
record
One
one
caveat
caveat
with
with
real
real
time
time
though
though
is
is
that
that
it
it
won't
won't
include
include
that
that
expanded
expanded
user
user
record,
record
although
although
we
we
can
can
easily
easily
fetch
fetch
it
it
with
with
a
a
one
one
query
query
if
if
needed.
needed
Then
then
for
for
the
the
delete
delete
action,
action
we
we
can
can
filter
filter
out
out
the
the
ID
id
of
of
the
the
message
message
that
that
was
was
removed.
removed
That
that
gives
gives
us
us
a
a
real
real
time
time
listener,
listener
but
but
whenever
whenever
working
working
with
with
real
real
time,
time
It's
it's
a
a
good
good
practice
practice
to
to
unsubscribe
unsubscribe
when
when
the
the
data
data
is
is
no
no
longer
longer
needed
needed
because
because
otherwise,
otherwise
you
you
could
could
end
end
up
up
with
with
memory
memory
leaks
leaks
and
and
unnecessary
unnecessary
reads
reads
on
on
the
the
database.
database
Create
create
a
a
variable
variable
to
to
represent
represent
a
a
function
function
named
named
unsubscribe.
unsubscribe
We
we
obtain
obtain
this
this
function
function
from
from
pocket
pocket
base
base
when
when
making
making
the
the
call
call
to
to
subscribe.
subscribe
Once
once
we
we
have
have
that
that
function
function
as
as
state,
state
We
we
can
can
then
then
call
call
it
it
on
on
the
the
on
on
destroy
destroy
life
life
cycle
cycle
hook
hook
to
to
end
end
the
the
subscription
subscription
when
when
the
the
user
user
logs
logs
out
out
or
or
if
if
they
they
navigate
navigate
to
to
a
a
different
different
page.
page
Let's
let's
open
open
up
up
the
the
browser
browser
and
and
tried
tried
it
it
out.
out
You
you
should
should
now
now
have
have
a
a
chat
chat
application
application
that
that
updates
updates
the
the
messages
messages
feed
feed
in
in
real
real
time.
time
And
and
now
now
we
we
can
can
run
run
npm
npm
build
build
to
to
build
build
our
our
site
site
for
for
production
production
and
and
deploy
deploy
it
it
somewhere
somewhere
on
on
the
the
Internet.
internet
In
in
fact,
fact
because
because
we
we
have
have
a
a
single
single
page
page
application,
application
we
we
could
could
actually
actually
do
do
this
this
on
on
Linode
linode
by
by
uploading
uploading
the
the
generated
generated
files
files
to
to
a
a
storage
storage
bucket,
bucket
then
then
configuring
configuring
it
it
as
as
a
a
static
static
website
website
host.
host
The
the
final
final
thing
thing
you
you
wanna
wanna
know
know
is
is
that
that
as
as
your
your
website
website
grows,
grows
the
the
pocket
pocket
base
base
will
will
need
need
to
to
scale
scale
vertically
vertically
with
with
more
more
CPU
cpu
and
and
RAM
ram
to
to
handle
handle
more
more
and
and
more
more
traffic.
traffic
Not.
not
This
this
can
can
be
be
easily
easily
accomplished
accomplished
by
by
simply
simply
resizing
resizing
your
your
Linode.
linode
A
a
bigger
bigger
server
server
can
can
handle
handle
more
more
traffic.
traffic
It
it
can
can
easily
easily
handle
handle
tens
tens
the
the
thousands
thousands
of
of
concurrent
concurrent
users
users
and
and
should
should
be
be
more
more
than
than
adequate
adequate
for
for
the
the
vast
vast
majority
majority
of
of
projects
projects
out
out
there.
there
This
this
allows
allows
you
you
to
to
fail
fail
over
over
and
and
over
over
again
again
as
as
not
not
looked
looked
her
her
without
without
a
a
bunch
bunch
of
of
wasted
wasted
time
time
and
and
money
money
as
as
collateral
collateral
damage.
damage
Thanks
thanks
for
for
watching,
watching
and
and
I
i
will
will
see
see
you
you
in
in
the
the
next
next
one.
one
success
The speakers discuss the directory and chat app in the cloud, emphasizing the importance of creating a one-toone relationship between users and chat messages. They also explain how to model data and create a one-toone relationship between users and chat messages in the pocket based application. The importance of scaling the application and resizing it for better performance is emphasized.
I built a $5 chat app with Pocketbase & Svelte. Will it scale?
What you're looking at is the actual side projects directory on my computer. None of these side projects have gone on to become the next Facebook yet, but I have not failed. I've just found hundreds of apps that don't work. If you're a developer slash entrepreneur, it's extremely important not to over engineer things. Andy Jassy once said, invention requires 2 things. 1, the ability to try lots of experiments, and 2, not having to live with the collateral damage of failed experiments. In today's video, we'll build a full stack chat app using pocket base and Svelte, then deploy it to a Linux server on Linode for just $5. I call this the Spok Stack and prepared to be amazed at how quickly it can get things done. Stupidly, I made this demo public, so you can actually try it out on the Internet right now. This is not my first rodeo, and I know you guys will spam it with the most horrific comments imaginable, but this time messages can be moderated with community reactions. If a comment gets pooped on 5 times, it disappears from the UI. The back end magic behind this application is a relatively new tool called Pocketbase, which is like a free and open source ierbase written in Go that provides user authentication along with a real time database powered by SQLite. But unlike any other base not out there. It compiles everything to a single executable, and that means to self host it, all you need is one little server, which costs less than your grande soy milk macchiato. Is the ultimate sophistication. But today, we'll find out if the simplicity of pocket base can actually scale. To kick things off, we're going to start things in reverse by deploying pocket face to a Linux server in the cloud. Luckily for us, Linode has sponsored this video, which means I get to make it rain with a $100 in free credits for everyone watching in this video. For those that don't know, Linode is one of the original cloud providers that's been around since 2003. Their platform is a perfect fit for this project because like Svelte and Pocketbase, it's famous for simplicity. Unlike big cloud providers, you can get a Linux server up and running with a few clicks with flat predictable pricing that won't cause collateral damage later. After you register, go to the dashboard and click the button to create a new Linode, then then choose an image with your preferred Linux distro. I'm going with Debian, but the real Chads out there will use Arch, by the way. Then choose a region and the size of your machine. And finally, give it a password and click create. Step 1 is complete. We now have a Linux server running in the cloud. I told you that would be easy. Let's go ahead and make a note of its key address to access it on the Internet. Now, in step 2, let's deploy Pocket Base to it. 1st, download and unzip Pocket Base from the website. I'm also using Debian on my local machine, so we'll download the Linux version. Unzip it to get this single pocket based executable. You can run it by running pocket based serve, but I wanna run it in the cloud on my Linode server so I can access it from anywhere just like a platform like Fire database. Let's open up the terminal and use secure shell to access the Linode IP address as a root user. It'll require the password you created earlier, and Now we have access to the mainframe. We're currently in the root directory, so let's go ahead and create another directory called p b. And now we just need to upload the Pocket Base to this directory. We could do it with r sync or an application like Filezilla, but I think the easiest approach is to use secure copy, which will simply copy the local file over to a remote directory we just created. Run this command from a separate terminal on your local machine. Once that's done, we can go back to the terminal on the Linode machine and run the pocketbase serve command. And to make it accessible over the Internet, we'll use the HTTP flag followed by our IP address and port 80. Congratulations. You just self hosted your own back end that you can now access over HTTP with the IP address. It serves a REST API as well as an admin dashboard that you can access with the underscore URL. However, there's a few more things I wanna show you to make it fully production ready. The first thing I would do is bring my domain over to Linode. No. It has a fully featured DNS manager, and Pocket Base uses Let's Encrypt to automatically generate an SSL certificate to serve your back end over HTTPS. All you have to to do is add this extra flag to the serve command. Now the next thing I would consider doing is mounting a volume to the pbdata directory. Not read. This is where Pocketbase stores all of your data. A volume is just its own file system that can be moved around to different servers. On Linode, we can easily attach an extra 20 gigabytes for just $2. And then finally, I would recommend setting up a system d service to automatically restart Pocket Base whenever the server reboots. And now it's time for step 3, where we model the data for our chat app. Navigate to your Pocket Base dashboard and create an admin user. From here, we can go to the database and by default, it has a collection for users. These are the users of your application, which contain fields like username, email, users of your application which contain fields like username, email, password, and so on. What we need is a way to create a one to many relationship between users and chat messages. Create a second collection called messages and give it 2 fields. The first field is text for the message content itself, and you can add some optional server side validations here like min length and max length, while the second field, user, creates a relationship that says a message belongs to a no user. Under the hood, Pocket Base creates a foreign key for the user ID on the messages table in the SQLite database. Go ahead and click create to update the schema. And now, you should be able to create new records in the database. That takes care of our data modeling. Now let's make it secure. Every collection in pocket base can have API rules. These rules determine who can access your data from a front end application. By default, the messages collection can only be accessed by admin users. However, we want anybody to be able to view the messages, so let's go ahead and hit the unlock button for list and view. Users also need the ability to create new messages, but it's critical that they only create messages associated to their own user ID. We can enforce that rule by ensuring that the user property is equal to the request auth user ID. And just like that, we've eliminated tons of complexity that we would need in our back end code otherwise. Not. Save the changes, then head over to the users collection. For users, we already have a bunch of rules built in, but we wanna give users the ability to view each other's profiles, So let's go ahead and remove the rules for view and list to make this data public. Now that we're somewhat secure, we can start building out the front end with Svelte. As you may know, I use Svelte to build the Fireship IO website, but it's also been used by the pocket based developers to build their admin UI as well. It's a great fit for this project because not it's really good at building real time UIs, thanks to its built in reactive stores. Generate a new project with Vite, then select the Svelte option, and we'll also go with TypeScript. Not. Open the project, run npm install, then npm run dev to serve it locally. Then in the code, delete all the boilerplate and create a new file called pocket base in the lib directory. Whenever building a new app, I usually start by thinking about user authentication. What we'll do in this file is provide a way to listen to the current user in real time from anywhere in the application. To handle that, we'll install the pocket based JavaScript SDK with NPM. Once installed, we can then import it in this file as well as writable from Svelte store. Now to connect to our back end, all we have to do is initialize pocket base with the URL it's hosted at, which in this case be the Linode IP address. From there, I'm creating a variable for current user that's equal to a writable store. Its default value is the pocket base auth store model, which is equal to null when the user is not logged in or equal to that database record of the currently logged in user that contains fields like the user ID, user name and so on. Now the value of this model will change when the user signs in and signs out, and we can listen to those changes by registering a callback for the on changed event. When this event fires, we can update the Svelte store with the current model. That gives us a way to subscribe to the current user. Let's put it to use by creating a login dot spelled component. Inside this component, we'll log in a user with email and password. What's awesome about that store we just created is that been subscribed to the current value anywhere in the application reactively by putting a dollar sign in front of it. For example, we might say, if current user, render the text signed in as current user dot username. Now the question becomes, how do we sign in a user? Well, let's start by creating variables for username and password, then create an HTML form that has 2 inputs for those values. In Svelte, we can easily bind that variable to that form value with the bind value directive. Now we can access the current form value in our script. Let's create an async function called login that awaits a call to the pocket based collection of users then calls the auth with password method using the username and password as arguments. And that's all the code it takes to authenticate a user. However, we don't have a user yet, which means we'll also need another function named sign up. In this function, we'll set up some initial data for a new user like the username, password, And we can also pass a name and email address here as well or whatever custom fields you configured in Pocket Base. We can then take that data and create a new record in the user's collection. Option. Once created, we call login with that same user data, and that's all it takes to sign up. But it'd be a good idea to wrap this in a try catch block and render an error message if a bad username or password is used. We also need a sign out function, which is accomplished by calling auth store clear. Now let's go into the HTML and bind these functions to buttons, which is accomplished in Svelte with on click. And as one final touch, I'm also going to listen to the on submit event on the form and prevent the default action so it doesn't refresh the page when submitted. Now now. Let's open the app dot Svelte file and declare the login component there. If we view the app in the browser, we should now see this login form. And And when you enter a username and password and click sign up, the UI should automatically rerender to show the current user's username. And now we're finally ready to build the fun part, the a real time chat messages feature. Let's go ahead and create a new component called messages. We can import the on mount and on destroy lifecycle hooks from Svelte as well as pocket based. Our first goal here is to fetch the most recent messages, which we can represent initially as an empty array. From there, we can fetch the messages when the component is first initialized with on mount. This code will run once at the beginning of the component life cycle to make a query to the messages collection. Use git list to fetch a paginated list of messages that starts on page 1 and has 50 messages per page. It also takes an object where you can do things like sort and filter the query. In our case, we want it sorted by that created field. What's really cool though is how easy it noticed to join in relational data. Remember, every message has a user field that points to a user record. If we want to also include the user data on every message. We can do that with the expand option, and that means we get all the data we need without any complex SQL joins. Now the return value is a result list, and we can set our messages array as the result list items. From there, we can go went to our HTML and loop over the messages with a Svelte each block. Notice how for each message, I have the message ID in parentheses. Not. This creates a keyed loop so Svelte can keep track of all the items in the list to render them more efficiently. For each message, I'm going to render out the message text in the database. And, also, because we joined in the user, I'm going to render out the user's username and also generate a unique a tar for each user using an awesome little service called DiceBear. Let's go ahead and try it out in the browser. I also have the pocket base admin UI side by side. And as you can see here, not. It fetches all the messages from the database. That's pretty cool, but how do we create a new message? Let's go back into the code and set up a variable for a new message. Then define a function called send message. For data, we'll need the text of the new message and also the current user's user ID. Remember, We can always get that by putting a dollar sign in front of it because Svelte is awesome. And now we just tell Pocket Base to create a new message. Let's go ahead and take this function and bind it to the on submit event on a form that also prevents the default action and binds the value of the text to that new message variable. Let's go ahead and open it up in the browser again and tried to create a new message. As you can see here, it creates a new message, but we need to refresh the entire page to actually see the message, and that's not going to fly for a real time chat app. The final thing we'll do here is make these messages update in real time. Let's go back into the on mount callback, and then we'll call pocket based collection messages and subscribe to the entire collection with the star symbol. This allows us to run a callback anytime a message is created, updated or deleted. The action tells us what happened. In our case, we want to update the UI if a new message was created or deleted. When created, we can update the messages array with that new record. One caveat with real time though is that it won't include that expanded user record, although we can easily fetch it with a one query if needed. Then for the delete action, we can filter out the ID of the message that was removed. That gives us a real time listener, but whenever working with real time, It's a good practice to unsubscribe when the data is no longer needed because otherwise, you could end up with memory leaks and unnecessary reads on the database. Create a variable to represent a function named unsubscribe. We obtain this function from pocket base when making the call to subscribe. Once we have that function as state, We can then call it on the on destroy life cycle hook to end the subscription when the user logs out or if they navigate to a different page. Let's open up the browser and tried it out. You should now have a chat application that updates the messages feed in real time. And now we can run npm build to build our site for production and deploy it somewhere on the Internet. In fact, because we have a single page application, we could actually do this on Linode by uploading the generated files to a storage bucket, then configuring it as a static website host. The final thing you wanna know is that as your website grows, the pocket base will need to scale vertically with more CPU and RAM to handle more and more traffic. Not. This can be easily accomplished by simply resizing your Linode. A bigger server can handle more traffic. It can easily handle tens the thousands of concurrent users and should be more than adequate for the vast majority of projects out there. This allows you to fail over and over again as not looked her without a bunch of wasted time and money as collateral damage. Thanks for watching, and I will see you in the next one.
The speakers discuss the directory and chat app in the cloud, emphasizing the importance of creating a one-toone relationship between users and chat messages. They also explain how to model data and create a one-toone relationship between users and chat messages in the pocket based application. The importance of scaling the application and resizing it for better performance is emphasized.