Skip to content

Local Setup

Getting from a fresh clone to a running app. Budget about 15 minutes, plus download time.

Make sure you have everything in Prerequisites first.

1. Clone and install

bash
git clone https://github.com/cryptixcoder/playpals.git
cd playpalz
pnpm install

pnpm install links every workspace package. It does not build them — that comes next.

2. Create environment files

Each service reads its own .env. Every one of them ships with a .env.example:

bash
cp packages/database/.env.example packages/database/.env
cp packages/queue/.env.example    packages/queue/.env
cp apps/api/.env.example          apps/api/.env
cp apps/esu/.env.example          apps/esu/.env
cp apps/ogun/.env.example         apps/ogun/.env
cp apps/anansi/.env.example       apps/anansi/.env

Then set the database URL in both packages/database/.env and apps/api/.env so it matches the Docker Compose Postgres:

bash
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/postgres"

And point Redis at the Compose instance — note the password, which is set in docker-compose.yaml:

bash
REDIS_URL="redis://:playpalz@localhost:6379"

The Redis password is easy to miss

docker-compose.yaml starts Redis with --requirepass playpalz. If your REDIS_URL omits the password you will get NOAUTH Authentication required from BullMQ and the Socket.IO adapter, which surfaces as media never finishing processing and realtime silently not working.

The minimum you must fill in for a working local app is DATABASE_URL, REDIS_URL, and JWT_SECRET (the same value in apps/api/.env and apps/esu/.env — the realtime server verifies tokens the API issued). Everything else can stay blank until you need that integration. See Environment Variables for the complete matrix.

3. Start infrastructure

bash
docker compose up -d db redis

That gives you:

ContainerImagePort
playpals-dbpostgres:15.45432
playpals-redisredis:76379

Add livekit to the command if you are working on voice rooms:

bash
docker compose up -d db redis livekit

4. Generate the Prisma client and migrate

bash
cd packages/database
pnpm db:generate     # generates the client into packages/database/generated/prisma
pnpm db:migrate      # applies migrations, then re-generates
cd ../..

Wait a few seconds after docker compose up before running these — Postgres needs to finish initialising or the migration will fail to connect.

5. Build the shared packages

bash
pnpm build

Backend services import @playpals/db, @playpals/queue, and @playpals/types from their compiled dist/ output, so this step is required before the services will start. Turborepo caches it, so subsequent runs are near-instant.

bash
cd packages/database
pnpm db:seed
cd ../..

An empty database gives you an empty feed, an empty explore page, and no one to message. Seed unless you specifically need a blank slate.

7. Run the services

The root dev script starts the four services you usually need at once:

bash
pnpm dev

That runs api, esu, ogun, and mobile through Turborepo's TUI. Use pnpm dev:all to include web, anansi, and igdb-heartbeat.

To run one service on its own:

bash
pnpm --filter @playpals/api    dev    # REST API      → :4000
pnpm --filter @playpals/esu    dev    # Socket.IO     → :4010
pnpm --filter @playpals/ogun   dev    # media worker  (no HTTP port)
pnpm --filter @playpals/anansi dev    # payouts       → :4005
pnpm --filter @playpals/web    dev    # Next.js       → :3000

Confirm the API is alive:

bash
curl http://localhost:4000/health
# {"status":"ok"}

8. Run the mobile app

The app needs a development build installed in your simulator — Expo Go cannot load the native modules this app depends on. Unzip the development client build and drag it onto the running iOS Simulator, then:

bash
pnpm --filter @playpals/mobile ios

Point the app at your machine with apps/mobile/.env. All three variables are read in apps/mobile/lib/env.ts, and the app logs an error at startup if the first two are missing:

bash
EXPO_PUBLIC_ENV=development
EXPO_PUBLIC_API_URL=http://localhost:4000/api/v1
EXPO_PUBLIC_REALTIME_URL=http://localhost:4010

EXPO_PUBLIC_API_URL must include /api/v1

It is used verbatim as the axios baseURL (apps/mobile/lib/axios.ts). Every call in apps/mobile/api/ is written relative to it, so dropping the suffix produces a wall of 404s.

Physical device on the same Wi-Fi

localhost resolves to the device itself, not your laptop. Use your machine's LAN address (http://192.168.x.x:4000/api/v1) and make sure your firewall allows inbound connections on 4000 and 4010.

Alternative: run the backend entirely in Docker

docker-compose.dev.yaml overlays live-reload containers for api, esu, and ogun on top of the base Compose file. This is slower than running natively but removes "works on my machine" drift:

bash
./start-dev.sh          # foreground, all services
./start-dev.sh -d api   # detached, just the API

You are running when…

  • curl http://localhost:4000/health returns {"status":"ok"}
  • curl http://localhost:4010/health returns {"ok":true}
  • The mobile app opens to the login screen and you can register an account
  • Creating a post with an image results in thumbnails appearing after a few seconds (that is ogun working)

If any of those fail, see Troubleshooting.

Internal documentation — PlayPalz platform