Skip to content

Asset bootstrap

declarative-hex-worlds is an asset-bootstrapping library, not an asset-bundled one. The published npm tarball ships:

  • The typed runtime, CLI, React + Three.js bindings.
  • The FREE-edition manifest.json (metadata only — asset ids, paths, bounds, taxonomy, file sizes).

The KayKit GLTF binaries themselves (≈30 MB for FREE, more for EXTRA) are fetched at install time by the CLI bootstrap subcommand, or by calling the programmatic bootstrapKayKitAssets API directly.

  • Keeps the npm tarball lean (~1 MB shipped vs 30+ MB if bundled).
  • Lets consumers re-use a single asset tree across multiple apps via a shared public/assets/models/ directory.
  • Avoids redistributing CC0 binary blobs through npm’s CDN.
  • Supports the purchased EXTRA edition without forcing every consumer to redistribute the larger archive.
Terminal window
pnpm add declarative-hex-worlds
pnpm exec declarative-hex-worlds bootstrap

The default --out heuristic detects:

  1. public/assets/models/ (Vite / Next.js convention) — preferred.
  2. assets/models/ (fallback).
  3. The current working directory.

You can always pass --out <path> explicitly. After bootstrap, the tree lives at:

<out>/addons/kaykit_medieval_hexagon_pack/
├── Assets/gltf/
│ ├── buildings/{blue,green,red,yellow,neutral}/...gltf
│ ├── decoration/{nature,props}/...gltf
│ └── tiles/{base,coast,rivers,roads}/...gltf
├── Textures/
│ └── hexagons_medieval.png
└── .bootstrap.json

The EXTRA edition is sold on kaylousberg.itch.io and ships extra units/ GLTFs plus seasonal hexagons_medieval_{Fall,Summer, Winter}.png textures. Download the zip from itch.io, then:

Terminal window
pnpm exec declarative-hex-worlds bootstrap \
--source zip \
--zip ~/Downloads/KayKit_Medieval_Hexagon_Pack_1.0_EXTRA.zip \
--edition extra \
--out public/assets/models

The CLI auto-detects the edition from the zip’s layout markers and refuses to overwrite a FREE-shaped target with EXTRA content (and vice-versa).

The integrity sidecar (.bootstrap.json) records:

  • schemaVersion (currently 1.0.0).
  • edition (free or extra).
  • libraryVersion (the library version that performed the bootstrap).
  • sourceUrl (the GitHub tarball URL, or file:// for zip sources).
  • fetchedAt (ISO-8601 timestamp).
  • files[] — sorted list of {path, sha256, bytes} for every mirrored file.

For deterministic CI builds, pass fetchedAt and libraryVersion to the programmatic API:

import { bootstrapKayKitAssets } from 'declarative-hex-worlds/bootstrap';
await bootstrapKayKitAssets({
source: { kind: 'github', commit: 'main' }, // pin to a specific sha for reproducibility
out: 'public/assets/models',
fetchedAt: '2026-01-01T00:00:00.000Z',
libraryVersion: '1.0.0',
});
Terminal window
pnpm exec declarative-hex-worlds bootstrap --verify --out public/assets/models

Re-hashes every file recorded in .bootstrap.json and reports any drift (missing files, size mismatches, hash mismatches). Exits non-zero on drift — useful as a CI step before deploys.

Wiring the runtime to your bootstrap target

Section titled “Wiring the runtime to your bootstrap target”

Three ways to tell the loaders where your bootstrap target lives:

// 1. Per-call (most explicit)
import { resolveManifestAssetUrl, freeManifest } from 'declarative-hex-worlds';
const url = resolveManifestAssetUrl(freeManifest.assets[0], {
bootstrapAssetRoot: '/app/public/assets/models',
});
// 2. Process-wide (app boot)
import { setGameboardAssetRoot } from 'declarative-hex-worlds';
setGameboardAssetRoot('/app/public/assets/models');
// 3. Environment variable (Node consumers)
// HEX_WORLDS_ASSET_ROOT=/app/public/assets/models

Resolution priority: explicit setGameboardAssetRoot override → globalThis.HEX_WORLDS_ASSET_ROOTprocess.env.HEX_WORLDS_ASSET_ROOT → default public/assets/models.

The target already contains files. Pass --force to wipe and re-mirror, or pick a different --out.

zip contains the EXTRA edition but bootstrap was asked for FREE

Section titled “zip contains the EXTRA edition but bootstrap was asked for FREE”

The zip’s layout markers identify it as EXTRA. Add --edition extra (and make sure you have a license / purchased copy).

failed to download KayKit FREE tarball ... unexpected status 404

Section titled “failed to download KayKit FREE tarball ... unexpected status 404”

GitHub returned a non-2xx response. Common causes:

  • Pinned --commit <sha> no longer exists (force-pushed or deleted).
  • Temporary GitHub outage. Retry, or pass --source zip with a locally downloaded copy.

A file on disk no longer matches its recorded sha256. Either a deploy modified the tree (unlikely — the tree should be read-only after bootstrap) or disk corruption. Re-run bootstrap --force to restore.

The runtime falls back to public/assets/models if no override is configured. If you bootstrapped to assets/models or elsewhere, set HEX_WORLDS_ASSET_ROOT or call setGameboardAssetRoot(...) at boot.

See the bootstrap reference for the full surface, including the {@link BootstrapKayKitAssetsOptions}, {@link BootstrapResult}, and {@link BootstrapSidecar} types.