Export & .bbd

The BlackBox Dungeon file format, and what “Save to poqpoq” actually does.

Two Ways to Save

DM's save button knows where it's running:

The .bbd file produced is identical in either case — the difference is only whether it lands on your disk or in your world.

The .bbd Format

A .bbd file is a JSON document. Human-readable, version-controlled in any Git repo, diff-able with regular tools. The top level looks like:

{
  "id": "dungeon_7f3e...",           // UUID
  "name": "Crimson Depths",          // Your chosen name
  "seed": 82714,                     // RNG seed
  "version": "1.0.0",
  "simType": "dungeon",              // NEXUS sim type classification

  "octagonCols": 10,                 // Octagon grid width
  "octagonRows": 10,                 // Octagon grid height
  "gridWidth": 19,                   // Interleaved array width (= cols * 2 - 1)
  "gridHeight": 19,

  "baseSquareSize": 12.8,            // Meters
  "cornerCutRatio": 0.20,            // Default = 20%
  "corridorScale": "standard",       // "cramped" | "standard" | "spacious"
  "layerHeight": 12,                 // Meters per layer

  "entrance": { "row": 0, "col": 4, "layer": 0 },

  "layers": [ ... ],                 // See below
  "dna": { ... },                    // Personality / archetype hints
  "resolvedAssets": { ... },         // Textures + models (resolved at save time)

  "createdAt": "2026-04-23T12:00:00Z",
  "modifiedAt": "2026-04-23T14:30:00Z"
}

Layers

A dungeon can have multiple stacked floors. Each layer is a full grid with its own theme, ambient light, and fog settings:

{
  "depth": 0,                        // 0 = top floor, increments downward
  "name": "Level 1",
  "theme": "natural_cave",           // Drives default textures
  "grid": [ [...], [...], ... ],     // 19×19 interleaved array
  "ambientLight": "#1a1520",
  "fogDensity": 0.3,
  "ambientAudio": "cave_drip"
}

Grid Cells

Every entry in layers[N].grid is one of three things:

Resolved Assets

At save time, DM resolves every texture and model reference to a concrete path so World doesn't have to guess:

{
  "baseUrl": "https://poqpoq.com/dungeon-master",
  "textures": [
    { "id": "cave_crystal_001", "path": "/textures/floors/cave_crystal_001.png" },
    ...
  ],
  "models": [
    { "id": "chest_ornate", "path": "/models/loot/chest_ornate.glb", "category": "loot" },
    ...
  ]
}

Save to poqpoq (Embedded Flow)

When DM detects it's running inside an iframe with an instance URL parameter, it switches into embedded mode. The export button relabels and its behavior changes:

  1. User clicks Save to poqpoq DM serializes the dungeon to JSON.
  2. postMessage: dungeon_saved DM posts to the parent window with:
    {
      type: "dungeon_saved",
      source: "dungeonmaster",
      instanceId: "<uuid>",
      payload: {
        dungeonData: "<BBD JSON string>",
        timestamp: "2026-04-23T14:30:00Z"
      }
    }
  3. World persists poqpoq World stores the dungeon in the creator's NEXUS inventory.
  4. postMessage: tool_close (200 ms later) DM signals the modal can close. World dismisses the iframe.
📝 Why the 200 ms pause

Giving World a tick to acknowledge the save before closing avoids race conditions where the modal closes before the parent has stored the blob. Empirical; 200 ms is comfortable.

Export .bbd (Standalone Flow)

In standalone mode, there's no parent frame. Clicking Export .bbd triggers a browser blob download of the same JSON document, named <dungeon-name>.bbd. Keep the file anywhere — Git repo, Dropbox, email attachment. Re-import by dragging it back onto the editor.

Re-importing

Opening a .bbd back into DM is round-trip lossless. Every wall state, every placed content item, every cell type, every room cluster's resulting wall states — all preserved. Room names and types are not persisted (see Rooms & Clusters for why), so if you re-import and want to re-label rooms you'll need to re-cluster them.

Sample File

The repo ships a sample dungeon, samples/crimson-depths.bbd (~30 KB), as a reference for the full schema with realistic content placement.

What's Next