---
title: Real-tenant dev fixtures
description: Boot local dev on real migrated Basenet tenant data instead of demo fixtures, without MariaDB access.
---

Canonical detail lives in the repo runbook ([`docs/runbooks/real-tenant-fixture.md`](https://github.com/blinqx-hq/basenet-rebuild-poc/blob/main/docs/runbooks/real-tenant-fixture.md)); this page keeps the essentials.

`pnpm dev` boots the synthetic `demo-kantoor` tenant ([Setup and checks](/developers/setup)). That is fine for feature work, but it exercises the app against hand-made data. A **tenant fixture** boots the same stack against a real migrated Basenet tenant — realistic shapes, volumes, and edge cases — and needs **no MariaDB access**. This is the developer workflow delivered by [BLI-247](https://linear.app/blinqx/issue/BLI-247/shareable-real-tenant-dev-fixture-boot-local-dev-with-migrated-basenet).

## Boot one

```bash
pnpm dev:tenant 112927          # http://localhost:3000
pnpm dev:tenant 108140 3001     # the other tenant, on another port
```

Each fixture is an isolated database with its own local-only login. Credentials are intentionally kept out of the published documentation; retrieve them from the repo-only runbook. One server serves one tenant at a time, so stop the running dev server first or pass a different port.

| Fixture              | Slug             | Rows (rel / matter / hour / doc) |
| -------------------- | ---------------- | -------------------------------- |
| `tenant-112927.json` | `basenet-112927` | 151 / 125 / 411 / 2110           |
| `tenant-108140.json` | `basenet-108140` | 704 / 133 / 327 / 1822           |

First boot provisions the database and loads ~6,000 mapped rows before web starts — roughly 75 seconds for 112927. Re-boots re-run the idempotent loader, which skips rows already recorded in `_migration_map`.

## Why pre-transform

The committed artifact is the **pre-transform `SourceTenant` JSON** in legacy Basenet vocabulary (`rcode`, `dostatus` ints, party refs as `(rcode, rtype)`) — not a Postgres dump. Boot runs the migration `load()` over it, so the legacy → CRM3 mapping is applied **fresh every boot**.

That is the point of decision **D32** ([Decisions & ADRs](/developers/decisions)): a dump would go stale the next time the schema moved and would have to be regenerated from MariaDB — the exact dependency these fixtures remove. Pre-transform data auto-tracks the current schema instead.

## Verify

A local dev API token lets you check the tenant without the UI. Its deterministic derivation is deliberately omitted from this public surface; use the repo-only runbook to obtain the command, then request one row:

```bash
curl -s -H "Authorization: Bearer ${LOCAL_FIXTURE_API_TOKEN}" \
  'http://localhost:3000/api/v1/matters?pageSize=1'
```

Totals must match the table above — except matters, which read one higher (`126`) because tenant defaults add the `__unfiled__` system bucket. Full derivation and per-entity counts are in the [runbook](https://github.com/blinqx-hq/basenet-rebuild-poc/blob/main/docs/runbooks/real-tenant-fixture.md).

## Demo stays the default

Fixtures are strictly opt-in, gated on `BASENET_FIXTURE`. `pnpm dev`, `pnpm test`, and CI never set it, so `demo-kantoor` remains the default everywhere and [Testing](/developers/testing) expectations are unaffected.

Fixture mode also skips the demo and phase seeds, seeding only tenant defaults, the dev admin, and the dev API token — so the tenant stays pure real data.

## Regenerating a fixture

Only needed when the extractor improves; it requires access to the legacy MariaDB, so most engineers never run it.

```bash
OWNER=112927 pnpm fixture:extract
```

The fixtures are test-tenant data, not a live customer tenant. Never commit a real customer tenant — anonymize it first.
