Why You Should Use PocketBase for Your Next Project
Tags: serverless, javascript, svelte
Published: 2023-09-01 16:21:23

PocketBase is an open-source backend as a service platform that is shipped as a single executable that can be self-hosted. For you to use PocketBase in production you have to host it yourself. This is in stark contrast to platforms like Supabase and Firebase. PocketBase ships with a full-blown authentication module, an SQL lite database that's embedded in the executable, and a file storage API making it concise for all your needs.

PocketBase is written in Go making it extremely fast, It comes with a built-in Admin dashboard where you can monitor your users, your database, and your files. You can also customize the STMP configurations for sending emails. PocketBase also provides an API for interacting with the server however there's a package for interacting with the server in some of the popular languages out there like Javascript, and Dart.

PocketBase is very easy to set up and use and in this post, I'm going to show you how to set up a PocketBase on your PC then we'll also set up a Svelte project to interact with the PocketBase server. We are going to consider the following in this post.

- Download, install, and set up PocketBase locally.
- Set up a Svelte project.
- Install PocketBase client and set up authentication in our app
- Why PocketBase and should you use it?

## Downloading PocketBase

To get started with PocketBase head over to the [documentation page](https://pocketbase.io/docs/) to download an executable for your PC. PocketBase comes bundled in a zip file so you need to extract the files from the archive first. When you are done with that open up a terminal navigate to the recent PocketBase server you just extracted and run the following command `pocketbase server` to start up your pocketbase server. Visit `http://127.0.0.1:8090/_/` to view your admin dashboard, since this is the first time you are using PocketBase you need to create a new admin account. If you do that successfully you should be redirected to your dashboard where you can view and manage your PocketBase server. Now that's done let's set up a Svelte project.

## Setup a Svelte project

We are going to set up this Svelte project with Vite, so that run the following command.

```bash
$ npm create vite@latest test_app --template svelte
```
Follow the prompts to set up the project and if everything is successful run the following commands.

```bash
$ cd test_app && npm install
```
The above commands first navigate into the newly created Svelte project then we install the dependencies for the project from npm. When the installation is complete run the next command to start up this project locally to verify that everything is set up successfully.

```bash
$ npm run dev
```
If you get the default UI that comes with a Svelte and Vite project, you're good to go. Next, let's install a router for our Svelte project.

```bash
$ npm install svelte-routing
```
This is the default package I use for routing in my Svelte projects. Now let's set up the UIs for this project. Bear with me because I will not add any styles to the UI. It will be as minimal as possible so it doesn't get in the way. Create a new folder named `pages` inside the `src` folder of your Svelte project. Inside the `pages` folder create a new Svelte component named `signup.svelte`

```jsx
// src/pages/signup.svelte

<script>
  let name = '';
  let email = '';
  let password = '';
  $:loading = false
</script>

<main>
  <h3>Logout</h3>
  <form>
    <label for="name">Name</label>
    <input type="text" bind:value={name} id="name" placeholder="John Doe" /><br />
    <label for="email">Email</label>
    <input type="email" bind:value={email} id="email" placeholder="email@domain.com" /><br />
    <label for="password">Password</label>
    <input type="password" bind:value={password} id="password" placeholder="***" /><br />
    {#if loading}
    <button disabled={loading}>
      loading...
    </button>
    {:else}
      <button type="submit">
        register
      </button>
    {/if}
  </form>
</main>

<style>
  form {
    padding: 3rem
  }
</style>
```
There's nothing much above just a form with three inputs one for the user's name, another for the user's email, and one for their password. Let's add a login component.

```jsx
// src/pages/login.svelte

<script>
  let email = '';
  let password = '';
  $:loading = false
</script>

<main>
  <h3>Login</h3>
  <form on:submit|preventDefault={() => Signin(email, password)}>
    <label for="email">Email</label>
    <input type="email" bind:value={email} id="email" placeholder="email@domain.com" /><br />
    <label for="password">Password</label>
    <input type="password" bind:value={password} id="password" placeholder="***" /><br />
    {#if loading}
    <button disabled={loading}>
      loading...
    </button>
    {:else}
      <button type="submit">
        register
      </button>
    {/if}
  </form>
</main>
```

Finally, let's add a last component which will serve as the dashboard page the user will see when they log in.

```jsx
// src/pages/index.svelte

<script>
  $:currentUser = {};
</script>


<h1>Current user {currentUser?.email}</h1>

<button>Logout</button>
```

Now we've added our components let's set up our router, so go ahead and edit the `App.svelte` file inside the `src` folder and paste it into the following content.

```jsx
// src/app.svelte

<script>
  import {Router, Route} from 'svelte-routing'
  import Login from "./pages/login.svelte";
  import Signup from "./pages/signup.svelte";
  import Index from './pages/index.svelte';

  export let url = "/";
</script>

<Router {url}>
  <Route path="/">
    <Signup />
  </Route>
  <Route path="/login">
    <Login />
  </Route>
  <Route path="/dashboard">
    <Index />
  </Route>
</Router>
```

You can run `npm run dev` again to confirm that everything is working successfully, Now let's go ahead and install the PocketBase Javascript client. 

## Installing a PocketBase client.

To install the PocketBase Javascript client run the following command;

```bash
$ npm i pocketbase
```

If you're done installing the PocketBase client create a new file named `helper.js` inside of the `src` folder. This module will contain the code for interacting with the PocketBase server. Let's add the first function for creating a new user account.

```javascript
// src/helper.js

import PocketBase from 'pocketbase';
const pb = new PocketBase('http://127.0.0.1:8090');


export const signUp = async ({name, email, password}) => {
  try {
    const user = await pb.collection('users').create({
      email, 
      name, 
      password, 
      passwordConfirm: password
    });
    return [null, user];
  } catch (error) {
    return [error, null]
  }
}
```

The snippet above first imports the `PocketBase` module from the `pocketbase` package. This module provides the JavaScript API for interacting with PocketBase. Then we create a new `PocketBase` client instance and specify the URL of the PocketBase server. We then define a function called `signUp`. This function takes three arguments: the user's name, email address, and password.

The function first tries to create a new user record in the `users` collection. The `create()` method takes an object as its argument, which specifies the properties of the new user record. In this case, the object specifies the user's email address, name, password, and password confirmation. If the `create()` method succeeds, the function returns an array with two elements: the first element is `null`, and the second element is the newly created user record. If the `create()` method fails, the function returns an array with two elements: the first element is the error object, and the second element is `null`.

Let's add the function for logging in a user.

```javascript
// helper cont'd

export const login = async (email, password) => {
  try {
    const authData = await pb.collection('users').authWithPassword(
      email,
      password
  );
  return [null, authData];
  } catch (error) {
    return [error, null]
  }
}

```

Now let's use the helper functions we have defined inside our components starting with the signup page.

```jsx
// src/pages/signup.svelte

<script>
  import {signUp} from '../helper';
  import {navigate} from 'svelte-routing'

  const Signin = async (email, password, name) => {
    loading = true
    const [error, authData] = await signUp({email, password, name});
    loading = false
    if (error) {
      console.error(error)
    } else if (authData) {
      console.log(authData);
      alert('account created successfully!')
      navigate('/login', { replace: true })
    }
  }
  let email = '';
  let password = '';
  let name = '';
  $:loading = false
</script>

<main>
  <h3>Logout</h3>
  <form on:submit|preventDefault={() => Signin(email, password, name)}>
   {/* ...other parts of the form */}
  </form
</main>
```
We import the `signUp` function from the helper file. This function is the one that we defined in the first code snippet. Then we import the `navigate` function from the `svelte-routing` package. This function is used to navigate to different pages in the application. Then we define a function called `Signin`. This function takes three arguments: the user's email address, password, and name. The function first calls the `signUp` function, passing in the user's email address, password, and name. The signUp function returns an array with two elements: the first element is an error object, and the second element is the newly created user record if it was successful.

The function then checks the error object. If the error object is not null, then the function logs the error to the console. If the error object is null, then the function logs the newly created user record to the console. The function then alerts the user that their account has been created successfully and navigates to the login page. Let's set up the integrations for the `login` page.

```jsx
// src/pages/login.svelte

<script>
  import { navigate } from 'svelte-routing';
  import {login} from '../helper';
  const Signin = async (email, password) => {
    loading = true
    const [error, authData] = await login(email, password);
    loading = false
    if (error) {
      console.error(error)
    } else if (authData) {
      console.log(authData);
      navigate('/dashboard', {replace: true})
    }
  }
  let email = '';
  let password = '';
  $:loading = false
</script>

<main>
  <h3>Login</h3>
  <form on:submit|preventDefault={() => Signin(email, password)}>
    {/* continued... */}
  </form>
</main>
```

And finally, let's add the integrations for the dashboard page.

```jsx
// src/pages/index.svelte

<script>
  import { navigate } from 'svelte-routing';
  import pb from "../helper";

  console.log(pb.authStore.model);
  $:currentUser = pb.authStore.model;

  pb.authStore.onChange((auth) => {
    console.log('authStore changed', auth);
    currentUser = pb.authStore.model;
  });

  function signOut() {
    pb.authStore.clear();
    navigate('/login', {replace: true})
  }

</script>

<h1>Current user {currentUser?.email}</h1>

<button on:click={() => signOut()}>Logout</button>
```

## Why PocketBase and should you even use it?

PocketBase is a very good alternative to Supabase and Firebase especially if you are looking at hosting it yourself. PocketBase is also open source so you are sure that the code is not controlled by some big tech firm. PocketBase is also extremely fast and reliable. It's going to save you hours of development time if your application requires a backend service and it keeps you glued to focusing on what matters. Delivering a good user experience.

So if you are looking at building something amazing but you don't have the time to invest in building a backend from scratch or you don't have the skills required to build or the money to hire a backend engineer then you can use PocketBase and since you have to host it yourself you're not worried about vendor lock-in or issues when trying to migrate your data. Leave your thoughts about PocketBase in the comments section. I'd like to know your experience and thoughts about working with PocketBase. I hope you found this super useful and I will see you in the next one.