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

# Development Environment

> Run PostQueen from source with hot reload, so you can change her

This sets up PostQueen from source on your own machine, with the frontend and backend
reloading as you edit. It is the right setup for writing code, adding a provider or fixing a
bug.

If you only want to run her, not change her, [Docker Compose](/installation/docker-compose) is
much shorter and it is the supported path.

<Note>
  Prefer to let your editor do the setup? [Dev Container](/installation/devcontainer) runs this
  same environment inside a container, with Node, pnpm and the databases already in place.
</Note>

## Tested configurations

macOS and Linux. Windows and WSL are not officially supported and are not well tested, so help
with problems specific to them may be limited.

## What you need

| Tool    | Version                      | Notes                                                |
| ------- | ---------------------------- | ---------------------------------------------------- |
| Node.js | **22.12 or newer, below 23** | Enforced by the repository. Node 20 or 18 will fail. |
| pnpm    | 10.6.1                       | Comes with Node through Corepack, see below          |
| Docker  | any recent                   | Provides PostgreSQL, Redis and Temporal for you      |

<Warning>
  **Node 22 specifically.** The repository declares `>=22.12.0 <23.0.0`, and installs fail on
  older versions. If you use a version manager, switch to 22 in this directory before you start.
</Warning>

You do not need to install pnpm by hand. Node ships with Corepack, which fetches the exact
version this repository expects:

```bash theme={"system"}
corepack enable
```

## Set it up

<Steps>
  <Step title="Clone the repository">
    ```bash theme={"system"}
    git clone https://github.com/GkhanKINAY/postqueen-app.git
    cd postqueen-app
    ```
  </Step>

  <Step title="Start the databases and the scheduler">
    ```bash theme={"system"}
    pnpm run dev:docker
    ```

    That runs `docker-compose.dev.yaml`, which brings up PostgreSQL, Redis, Temporal and two
    optional inspection tools. **Temporal is included**, so there is no second repository to
    clone for it.

    | Service            | Where                                          | For                                                |
    | ------------------ | ---------------------------------------------- | -------------------------------------------------- |
    | PostgreSQL         | `localhost:5432`                               | Your data                                          |
    | Redis              | `localhost:6379`                               | Caching and rate limits                            |
    | Temporal           | `localhost:7233`                               | Scheduling posts                                   |
    | Temporal dashboard | [http://localhost:8080](http://localhost:8080) | Watching scheduled work                            |
    | pgAdmin            | [http://localhost:8081](http://localhost:8081) | Browsing the database, `admin@admin.com` / `admin` |
    | RedisInsight       | [http://localhost:5540](http://localhost:5540) | Browsing Redis                                     |
  </Step>

  <Step title="Create your .env">
    ```bash theme={"system"}
    cp .env.example .env
    ```

    One shared `.env` at the repository root serves every app in the monorepo. The defaults
    match the containers you just started, so for a plain local setup there is nothing to
    change. The values that matter:

    ```env theme={"system"}
    DATABASE_URL="postgresql://postqueen-local:postqueen-local-pwd@localhost:5432/postqueen-db-local"
    REDIS_URL="redis://localhost:6379"
    TEMPORAL_ADDRESS="localhost:7233"
    JWT_SECRET="any long random string will do locally"

    FRONTEND_URL="http://localhost:4200"
    NEXT_PUBLIC_BACKEND_URL="http://localhost:3000"
    BACKEND_INTERNAL_URL="http://localhost:3000"

    STORAGE_PROVIDER="local"
    NOT_SECURED=true
    IS_GENERAL="true"
    ```

    <Note>
      `NOT_SECURED=true` is what lets sign-in work over plain HTTP. It belongs in local
      development and nowhere else.
    </Note>

    Add provider keys only for the networks you actually want to test against. Each one is
    covered under [Providers](/providers/overview).
  </Step>

  <Step title="Install dependencies">
    ```bash theme={"system"}
    pnpm install
    ```

    This also generates the Prisma client for you, so there is no separate generate step.

    <Note>
      If this dies with a JavaScript heap error, give Node more room:

      ```bash theme={"system"}
      NODE_OPTIONS="--max-old-space-size=4096" pnpm install
      ```
    </Note>
  </Step>

  <Step title="Create the database schema">
    ```bash theme={"system"}
    pnpm run prisma-db-push
    ```
  </Step>

  <Step title="Run it">
    ```bash theme={"system"}
    pnpm run dev
    ```

    Open **[http://localhost:4200](http://localhost:4200)**.

    <Warning>
      `pnpm run dev` also starts the browser extension build, which wants port **8081**, and
      pgAdmin from the previous step is already using it. If that clashes, run the two you
      actually need:

      ```bash theme={"system"}
      pnpm run dev-backend
      ```

      That starts only the backend and the frontend.
    </Warning>
  </Step>
</Steps>

## What runs where

| Part              | Port | Command on its own          |
| ----------------- | ---- | --------------------------- |
| Frontend, Next.js | 4200 | `pnpm run dev:frontend`     |
| Backend, NestJS   | 3000 | `pnpm run dev:backend`      |
| Orchestrator      | 3002 | `pnpm run dev:orchestrator` |
| Browser extension | 8081 | part of `pnpm run dev`      |

Note that these are not the ports the container image uses. From source the frontend and
backend are separate servers on separate ports, while the published image puts a small proxy in
front of both on a single port. That is why `NEXT_PUBLIC_BACKEND_URL` is `http://localhost:3000`
here and carries an `/api` suffix in a Compose install.

## Useful commands

```bash theme={"system"}
pnpm run dev              # everything, hot reload
pnpm run dev-backend      # backend and frontend only
pnpm run dev:docker       # start the local databases and Temporal
pnpm run build            # production build of all three apps
pnpm run prisma-db-push   # apply the schema without writing a migration
pnpm run prisma-generate   # regenerate the Prisma client after editing the schema
pnpm test                 # test suite
```

## The layout

It is a pnpm workspace, not an Nx-driven build, so tasks run through `pnpm --filter`.

```
apps/
  frontend/       Next.js and Tailwind
  backend/        NestJS, controllers, services, repositories, DTOs
  orchestrator/   Temporal workflows and activities
  extension/      Chrome extension
  commands/       CLI entry points
  sdk/            Public API client
libraries/
  nestjs-libraries/  Prisma schema, integrations, shared backend code
  react-shared-libraries/
  helpers/
```

Imports use the `@gitroom/*` prefix. That is intentional and correct, it is the real workspace
alias in `tsconfig.base.json`.

## If something goes wrong

<AccordionGroup>
  <Accordion title="Postgres connection refused">
    The containers are probably not up. `docker ps` should list `postqueen-postgres` and
    `postqueen-redis`. If not, `pnpm run dev:docker` again and watch for errors.
  </Accordion>

  <Accordion title="Password authentication failed for user">
    `DATABASE_URL` does not match the container. The dev stack creates the user
    `postqueen-local` with password `postqueen-local-pwd` and the database
    `postqueen-db-local`. Copy the line from the step above exactly.
  </Accordion>

  <Accordion title="Port 8081 already in use">
    pgAdmin and the extension's hot reload both want it. Use `pnpm run dev-backend`, or stop
    pgAdmin with `docker stop postqueen-pg-admin`.
  </Accordion>

  <Accordion title="Nothing gets published, but posting appears to work">
    Temporal is not reachable. It is what actually fires posts. Check `TEMPORAL_ADDRESS` is
    `localhost:7233` and that the dashboard answers at [http://localhost:8080](http://localhost:8080).
  </Accordion>

  <Accordion title="Sign-in does not stick">
    Set `NOT_SECURED=true` in `.env`. Without it the login cookie requires HTTPS, which you do
    not have locally.
  </Accordion>
</AccordionGroup>

Still stuck? The [support](/support) page has where to ask.

## Next Steps

<CardGroup cols={2}>
  <Card title="Add a provider" icon="plug" href="/configuration/create-provider">
    What a new social network needs on the backend and the frontend
  </Card>

  <Card title="Developer guide" icon="code" href="/developer-guide">
    How the codebase is organised and how to contribute
  </Card>

  <Card title="Architecture" icon="diagram-project" href="/howitworks">
    The services behind a post, and what each one does
  </Card>

  <Card title="Configuration reference" icon="sliders" href="/configuration/reference">
    Every environment variable she reads
  </Card>
</CardGroup>
