---
title: "Setup"
description: "From a fresh clone to every app running locally."
url: https://docs.skiffr.findmalek.engineer/docs/setup
markdown: https://docs.skiffr.findmalek.engineer/docs/setup.md
---

# Setup

You need node 24, pnpm, bun and docker.

```bash
pnpm install
cp .env.example .env
pnpm db:up
pnpm dev --filter='!extension'
```

Edit `.env` before the first start. `BETTER_AUTH_SECRET` must be at least 32 characters (`openssl rand -base64 32` gives 44), otherwise the api refuses to start. `ADMIN_PASSWORD` must be at least 10 characters, and with `ADMIN_EMAIL` or `ADMIN_PASSWORD` empty no admin is created. `DATABASE_URL` in `.env.example` already matches the local postgres from `pnpm db:up`.

`pnpm dev` runs `turbo dev`, which starts every workspace with a `dev` script: web, api, dashboard, docs and the extension (`wxt`, which opens a development browser). `pnpm dev --filter='!extension'` starts only the four apps. Run the extension on its own with `pnpm --filter extension dev`.

`pnpm db:up` starts a local postgres (`pgvector/pgvector:pg17`) from `docker/docker-compose.yml`. The api applies migrations on start and, when `SEED=demo`, fills an empty database with sample data.

The pgvector image is debian based, the old alpine based postgres image used a different libc, so the compose file mounts a new volume, `skiffr-pgvector-data`, and never reuses the old one. Never point the new image at an old alpine data directory, text indexes break silently. Remove the old dev volume (it holds the old data) with `docker volume rm docker_skiffr-pg`.

| App | Url |
| --- | --- |
| web | http://localhost:3000 |
| api | http://localhost:3001 |
| dashboard | http://localhost:3002 |
| docs | http://localhost:3003 |

Sign in to the dashboard with `ADMIN_EMAIL` and `ADMIN_PASSWORD` from `.env`. The admin is created or reset on every api start.

## Load the extension

Build it, load it unpacked, create a token on the dashboard's Extension page and paste it in the extension options. The steps, the CI build option and what the extension does on a page are in [the extension](https://docs.skiffr.findmalek.engineer/docs/extension.md).

## Working on one app

```bash
pnpm dev:web        # web and api
pnpm dev:dashboard  # dashboard and api
```

## Before you push

```bash
pnpm lint
pnpm check-types
pnpm test
pnpm build
```
