> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/pocketbase/pocketbase/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript SDK overview

> Learn how to extend PocketBase with JavaScript hooks and the JavaScript VM

PocketBase comes with a built-in JavaScript VM that allows you to extend your backend with custom JavaScript code. You can write hooks, custom routes, scheduled tasks, and more using JavaScript.

## What is the JavaScript VM?

The JavaScript VM (JSVM) is a plugin that enables you to write server-side JavaScript code that runs directly in PocketBase. It uses the [goja](https://github.com/dop251/goja) JavaScript runtime, which implements ECMAScript 5.1 with some ES6+ features.

## Getting started

To use JavaScript hooks in PocketBase, you need to:

1. Create a `pb_hooks` directory in your project root
2. Add `.pb.js` or `.pb.ts` files to this directory
3. Write your JavaScript code using the PocketBase APIs

<Note>
  Files must end with `.pb.js` or `.pb.ts` to be recognized by the JavaScript VM. The `.pb.ts` extension is recommended for better IDE support with TypeScript definitions.
</Note>

## Basic example

Here's a simple example that adds a custom route:

```javascript theme={null}
// pb_hooks/routes.pb.js

routerAdd("GET", "/hello", (e) => {
  return e.json(200, { "message": "Hello from PocketBase!" })
})
```

## File structure

Your PocketBase project structure should look like this:

```
my-project/
├── pb_data/           # Database and storage
├── pb_hooks/          # JavaScript hooks (your custom code)
│   ├── main.pb.js
│   ├── routes.pb.js
│   └── tasks.pb.js
├── pb_migrations/     # Database migrations
└── pocketbase         # PocketBase executable
```

## Available APIs

The JavaScript VM provides several namespaces and functions:

### Global variables

* `$app` - The PocketBase application instance
* `$template` - Template rendering helpers
* `__hooks` - Absolute path to the hooks directory

### Utility namespaces

* `$http` - HTTP client for making requests
* `$security` - Cryptography and security utilities
* `$filesystem` - File system operations
* `$os` - Operating system utilities
* `$filepath` - File path utilities
* `$dbx` - Database query builder helpers
* `$apis` - API route helpers and middlewares
* `$mails` - Email sending utilities

### Global functions

* `routerAdd()` - Register custom HTTP routes
* `routerUse()` - Register global middlewares
* `cronAdd()` - Schedule cron jobs
* `cronRemove()` - Remove cron jobs
* `on*()` - Event hooks (e.g., `onRecordCreate`, `onRecordUpdate`)

## TypeScript support

PocketBase automatically generates a `types.d.ts` file in your `pb_data` directory with full TypeScript definitions. To use it:

1. Create your hook files with `.pb.ts` extension
2. Add a reference directive at the top of your file:

```typescript theme={null}
/// <reference path="../pb_data/types.d.ts" />

routerAdd("GET", "/users/:id", (e) => {
  const id = e.request.pathValue("id")
  // Your IDE will now provide autocomplete and type checking
  return e.json(200, { id })
})
```

## Hot reloading

During development, you can enable hot reloading to automatically restart PocketBase when your hook files change:

```bash theme={null}
./pocketbase serve --hooksWatch=true
```

<Warning>
  Hot reloading is not supported on Windows. You'll need to manually restart PocketBase after making changes.
</Warning>

## Performance

The JavaScript VM uses a pool of runtime instances to handle concurrent requests efficiently. You can configure the pool size:

```bash theme={null}
./pocketbase serve --hooksPool=25
```

The default pool size is 15 instances.

## Node.js compatibility

The JavaScript VM includes support for some Node.js modules:

* `console` - Logging to stdout
* `require()` - Module loading
* `process` - Process information
* `buffer` - Buffer operations

You can use `require()` to load local modules or packages from `node_modules`.

## Error handling

Errors in JavaScript hooks are automatically caught and returned as HTTP errors. You can throw errors or return them:

```javascript theme={null}
routerAdd("POST", "/api/validate", (e) => {
  const data = e.requestInfo().data
  
  if (!data.email) {
    throw new BadRequestError("Email is required")
  }
  
  return e.json(200, { success: true })
})
```

## Next steps

<CardGroup cols={2}>
  <Card title="App instance" icon="cube" href="/js/app">
    Learn about the global \$app instance and its methods
  </Card>

  <Card title="Collections" icon="database" href="/js/collections">
    Work with collections and schemas
  </Card>

  <Card title="Records" icon="file" href="/js/records">
    Create, read, update, and delete records
  </Card>

  <Card title="Events" icon="bolt" href="/js/events">
    Hook into PocketBase lifecycle events
  </Card>
</CardGroup>
