Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,6 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*

TODO
TODO

/reviews
103 changes: 58 additions & 45 deletions docs/cli/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ description: "@bedrock-core/cli scaffolds a complete Minecraft Bedrock addon pro
`@bedrock-core/cli` is in beta: the API can change between releases. Pin exact versions and read the changelog before upgrading.
:::

## Prerequisites

- Node.js 22.18+ — [https://nodejs.org/](https://nodejs.org/)
- Regolith — [https://regolith-docs.readthedocs.io/en/stable](https://regolith-docs.readthedocs.io/en/stable)

<Exec cmd="@bedrock-core/cli" />

## Usage
Expand All @@ -28,20 +33,25 @@ description: "@bedrock-core/cli scaffolds a complete Minecraft Bedrock addon pro
| --- | --- |
| `-a, --author <name>` | Author name. Skips the author prompt |
| `-d, --description <text>` | Project description. Skips the description prompt |
| `-p, --package-manager <manager>` | Install with `yarn`, `npm`, `pnpm`, or `none` to skip |
| `-V, --version` | Print the CLI version |
| `-h, --help` | Print usage |

No template switch and no package-manager choice — the template ships a `yarn.lock`.
There is one complete template. Choose npm, yarn, pnpm, or `none` when you want to install
later. Yarn and pnpm record their selected version in `package.json`; each manager creates its own lockfile, which should be committed with the project.

### Prompts

Three text prompts, all with defaults you can accept with Enter. `[project-name]` and `--author`/`--description` each skip their own prompt, so a fully-flagged invocation runs with no prompts at all:
Three text prompts and a package-manager selection, all with defaults you can accept with Enter.
`[project-name]`, `--author`, `--description`, and `--package-manager` each skip their own prompt,
so a fully flagged invocation runs with no prompts at all:

| Prompt | Default | Validation |
| --- | --- | --- |
| `Project name:` | `my-addon` | Must be a valid new npm package name (this becomes the directory and `package.json` name) |
| `Author name:` | `Your Name` | — |
| `Description:` | `A Minecraft Bedrock addon with custom UI` | — |
| `Install dependencies with:` | `yarn (recommended)` | yarn, npm, pnpm, or install later |

Ctrl-C prints `✖ Operation cancelled` and exits cleanly. The CLI refuses to write into a directory that already exists and is not empty.

Expand All @@ -57,7 +67,7 @@ my-addon/
├── tsconfig.test.json extends tsconfig.json; entry is scripts/gametest.ts
├── eslint.config.mjs
├── .vscode/ launch.json wired to the Minecraft debugger (port 19144)
├── core-ui-v*.mcpack render pack, downloaded for you
├── core-ui-<UI version>.mcpack render pack, downloaded for you
└── packs/
├── BP/
│ ├── manifest.json
Expand Down Expand Up @@ -125,14 +135,14 @@ after scaffolding.

| Profile | Script | Export | Notes |
| --- | --- | --- | --- |
| `build` | `yarn build` | read-only, `local` | Minified, `bundler.debug: false` — the release build |
| `default` | `yarn watch` | writable, `development` | Laid-out JSON, debug bundle, build-stamp HUD, redeploys on change |
| `test` | `yarn watch:test` | writable, `development` | Same as `default`, resolving `manifest.test.json` and bundling `gametest.ts` |
| `build-test` | `yarn build:test` | read-only, `./build/test/BP` and `./build/test/RP` | The gametest manifest and entry, for [`bds-runner`](/docs/bds-runner) |
| `build` | `build` | read-only, `local` | Minified, `bundler.debug: false` — the release build |
| `default` | `watch` | writable, `development` | Laid-out JSON, debug bundle, build-stamp HUD, redeploys on change |
| `test` | `watch:test` | writable, `development` | Same as `default`, resolving `manifest.test.json` and bundling `gametest.ts` |
| `build-test` | `build:test` | writable, `./build/test/BP` and `./build/test/RP` | The gametest manifest and entry, for [`bds-runner`](/docs/bds-runner) |

### GameTests

`packs/BP/scripts/tests/index.ts` registers one GameTest tagged `example` through `@minecraft/server-gametest`, a beta module only `manifest.test.json` declares. `gametest.ts` — the entry `tsconfig.test.json` names — imports `./main` then `./tests`, so a release build (`main.ts`) never pulls in the test suite or the beta module. `yarn build:test` produces the pack [`bds-runner`](/docs/bds-runner) runs the suite against.
`packs/BP/scripts/tests/index.ts` registers one GameTest tagged `example` through `@minecraft/server-gametest`, a beta module only `manifest.test.json` declares. `gametest.ts` — the entry `tsconfig.test.json` names — imports `./main` then `./tests`, so a release build (`main.ts`) never pulls in the test suite or the beta module. The `build:test` script produces the pack [`bds-runner`](/docs/bds-runner) runs the suite against.

### tsconfig

Expand All @@ -152,7 +162,7 @@ after scaffolding.
```

:::caution Build once before the editor is happy
Both generated files are produced by the filters, so a freshly scaffolded project does not typecheck until `yarn build` has run at least once. This is expected — run the build before hunting for missing modules.
Both generated files are produced by the filters, so a freshly scaffolded project does not typecheck until the `build` script has run at least once. This is expected — run the build before hunting for missing modules.
:::

A second tsconfig, `tsconfig.test.json`, extends this one and names `packs/BP/scripts/gametest.ts` as its sole entry — the `test` and `build-test` profiles point the bundler at it. See [GameTests](#gametests).
Expand Down Expand Up @@ -198,52 +208,55 @@ A `playerSpawn` handler greets the player with an interpolated translation (gate

## After scaffolding

The CLI **does not** install anything. It copies the template, substitutes your answers, and downloads the latest render pack `.mcpack` from GitHub releases into the project root (non-fatal if that fails — it prints the download link instead).

It then prints:

```txt
✔ Project created successfully!

Next steps:

cd my-addon
yarn install (or npm install)
yarn run regolith-install (or npm run regolith-install)
yarn run build (or npm run build)
The first build writes the Minecraft document types, so the .ts templates in
packs/BP/blocks and packs/BP/entities autocomplete once it has run.
See packs/BP/scripts/UI/screens/ to explore the starter screens and navigation.

Render pack:

Install: open "./core-ui-v<version>.mcpack" (double-click to import into Minecraft)

Development:

yarn run watch - Watch mode for auto-rebuild
yarn run lint - Lint your code

Push a stone button in-game to see the example UI!
```

When the render pack download fails, the last line under "Render pack:" is replaced with a link to the latest `.mcpack` on GitHub Releases instead of a filename — non-fatal, so scaffolding still finishes.
The CLI copies the template, substitutes your answers, downloads the render pack matching UI
`0.12.1` (`core-ui-0.12.1.mcpack`), then installs dependencies with the package manager you chose.
If the asset download fails, it prints the matching release link instead. Choosing `none` creates
the files without running a package manager.

It prints the commands for your selected manager:

<PackageCommands
npm={`cd my-addon
npm run regolith-install
npm run build
npm run watch
npm run lint`}
yarn={`cd my-addon
yarn regolith-install
yarn build
yarn watch
yarn lint`}
pnpm={`cd my-addon
pnpm regolith-install
pnpm build
pnpm watch
pnpm lint`}
/>

The output also explains that the first build writes the generated Minecraft types, points to the
starter screens, and tells you how to import the matching render pack into the client.

When the render pack download fails, the last line under "Render pack:" is replaced with a link to
the UI `0.12.1` release instead of a filename — non-fatal, so scaffolding still finishes.

| Script | What it runs |
| --- | --- |
| `regolith-install` | `regolith install-all` — fetches every filter declared in `config.json` |
| `build` | `regolith run build` — the read-only local export profile |
| `build:test` | `regolith run build-test` — the read-only gametest export, for `bds-runner` |
| `build:test` | `regolith run build-test` — the writable gametest export, for `bds-runner` |
| `watch` | `regolith watch` — the development profile, redeploying on change |
| `watch:test` | `regolith watch test` — the development profile, resolving the gametest manifest and entry |
| `lint` | `eslint .` |
| `loopback` / `loopback:preview` | Windows loopback exemption for the Minecraft debugger |

No git repository is created and no package manager is detected — the template ships a `yarn.lock`, so `yarn install` is the smoothest path.

:::tip Prerequisites
Node.js 22.18+ (what the Regolith filters run on), a package manager, and [Regolith](https://regolith-docs.readthedocs.io/en/stable) on your `PATH`. See [Installation](/docs/ui/installation).
:::
When Git is available, the generated directory is initialized as a repository without creating a
commit. Yarn and pnpm choices run `corepack enable` once, then invoke the selected manager without
a `corepack` prefix. npm runs
directly. The selected manager creates its own lockfile; commit it and use that manager's frozen/immutable install mode in CI. If Corepack
cannot write its shims, the generated project is preserved and the CLI prints the manual command.
Yarn uses `nodeLinker: node-modules`; pnpm uses `nodeLinker: hoisted` in
`pnpm-workspace.yaml`, so the build sees the conventional `node_modules` layout with either
manager.

## Next steps

Expand Down
81 changes: 69 additions & 12 deletions docs/filters/ci.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,80 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 24

- name: Set up Regolith
uses: bedrock-core/setup-regolith@v1
uses: bedrock-core/setup-regolith@1.0.1
with:
regolith-version: '1.6.1'
regolith-version: '1.8.0'
resolvers: |
github.com/bedrock-core/regolith-filters
```

Add the steps from your package manager after `Set up Regolith`:

<PackageCommands
language="yaml"
npm={` - name: Install project dependencies
run: npm ci

- name: Install declared filters
run: regolith install-all
run: npm run regolith-install

- name: Run Regolith profile
run: regolith run release
```
- name: Build the addon
run: npm run build

- name: Build the GameTest pack
run: npm run build:test

- name: Run GameTests
run: npx --yes @bedrock-core/bds-runner@0.1.0 run --packs ./build/test/BP --tag example --expect-registered 1 --bds-version 1.26.51.1`}
yarn={` - name: Enable Yarn Berry through Corepack
run: corepack enable

- name: Install project dependencies
run: yarn install --immutable

- name: Install declared filters
run: yarn regolith-install

- name: Build the addon
run: yarn build

- name: Build the GameTest pack
run: yarn build:test

- name: Run GameTests
run: yarn dlx @bedrock-core/bds-runner@0.1.0 run --packs ./build/test/BP --tag example --expect-registered 1 --bds-version 1.26.51.1`}
pnpm={` - name: Enable pnpm through Corepack
run: corepack enable

- name: Install project dependencies
run: pnpm install --frozen-lockfile

- name: Install declared filters
run: pnpm regolith-install

- name: Build the addon
run: pnpm build

- name: Build the GameTest pack
run: pnpm build:test

- name: Run GameTests
run: pnpm dlx @bedrock-core/bds-runner@0.1.0 run --packs ./build/test/BP --tag example --expect-registered 1 --bds-version 1.26.51.1`}
/>

Commit the lockfile generated by the CLI before this workflow runs. npm CI expects
`package-lock.json`, Yarn's immutable install expects `yarn.lock`, and pnpm's frozen install expects
`pnpm-lock.yaml`.

After the step completes, `regolith` is on `PATH` for every later step in the same job. The action
only registers resolvers: `regolith install-all` installs the filters in the project's
`filterDefinitions`. A `core` profile must declare `core` and its six delegated stages.
only registers resolvers: the project's `regolith-install` script installs the filters declared in
`filterDefinitions`. The template's `core` profile declares `core` and its six delegated stages.

## Inputs

Expand All @@ -49,7 +106,7 @@ The binary for the runner's OS comes from the Regolith GitHub releases and is ke

Pair it with [`bds-runner`](/docs/bds-runner) to run the addon's GameTests on a dedicated server in the same job:

```yaml
- name: Run GameTests
run: npx @bedrock-core/bds-runner run --packs ./build --tag my-suite
```
<Exec cmd="@bedrock-core/bds-runner@0.1.0 run --packs ./build/test/BP --tag example --expect-registered 1 --bds-version 1.26.51.1" />

Only the behavior pack is passed to the dedicated server. Render packs are client-side and are not
needed for GameTests.
6 changes: 3 additions & 3 deletions docs/server/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ Get a bedrock-core addon online, then get a second one talking to it.

## Prerequisites

- Node.js 20+ and Yarn (or npm) — https://nodejs.org/
- Regolith (recommended) — https://regolith-docs.readthedocs.io/en/stable
- Node.js 22.18+ and Git — [https://nodejs.org/](https://nodejs.org/)
- Regolith — [https://regolith-docs.readthedocs.io/en/stable](https://regolith-docs.readthedocs.io/en/stable)

## Quick start with the CLI

Expand All @@ -33,7 +33,7 @@ That single dependency pins matching versions of the packages the runtime is bui
```ts
import { core } from '@bedrock-core/server'; // the runtime
import { computed } from '@bedrock-core/server/observable'; // the reactive primitive
import { createEngineDb } from '@bedrock-core/server/db'; // documents beyond core.db, rarely needed
import { schema } from '@bedrock-core/server/db'; // collection schema helpers
import { createSync } from '@bedrock-core/server/sync'; // the raw transport, rarely needed
import { createI18n } from '@bedrock-core/server/i18n'; // typed translations
```
Expand Down
2 changes: 1 addition & 1 deletion docs/ui/guides/render-pack.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The protocol version is a hard gate, not a negotiation. A behavior pack emitting

## Getting the matching pack

The render pack ships as the `core-ui-v*.mcpack` attached to each `@bedrock-core/ui` release, and the [CLI](/docs/cli) downloads the latest one into new projects automatically. **Take the pack from the same release as the library** — that pairing is the compatibility contract.
The render pack ships as `core-ui-<UI version>.mcpack`, attached to the matching `@bedrock-core/ui` release. For example, UI `0.12.1` uses `core-ui-0.12.1.mcpack`. The [CLI](/docs/cli) downloads that matching asset into new projects. **Take the pack from the same release as the library** — that pairing is the compatibility contract.

Its UUID never changes — `761ecd37-ad1c-4a64-862a-d6cc38767426` — so the dependency entry in your behavior pack's `manifest.json` stays as it is:

Expand Down
10 changes: 6 additions & 4 deletions docs/ui/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ Three things have to be in place: the package, the render pack in the world, and

## Prerequisites

- Node.js 22.18.0+ and Yarn or npm — https://nodejs.org
- Regolith — https://regolith-docs.readthedocs.io/en/stable
- Node.js 22.18+ and Git — [https://nodejs.org/](https://nodejs.org/)
- Regolith — [https://regolith-docs.readthedocs.io/en/stable](https://regolith-docs.readthedocs.io/en/stable)

Regolith is not optional here. A screen is drawn from JSON UI the build writes, so a project with no build has no screens.

Expand Down Expand Up @@ -61,7 +61,7 @@ The render pack decodes what the build wrote, so it must come from the **same re
"dependencies": [
{
"uuid": "761ecd37-ad1c-4a64-862a-d6cc38767426",
"version": [1, 11, 0]
"version": "1.12.0"
}
]
}
Expand Down Expand Up @@ -119,7 +119,9 @@ export default function Hello(): JSX.Element {
}
```

<Exec cmd="regolith run" />
```bash
regolith run
```

The filter logs one line per screen it compiled. If `render()` throws `UncompiledScreenError` instead, the build did not see the file or `@bedrock-core/generated/ui` was never imported.

Expand Down
1 change: 1 addition & 0 deletions src/components/Home/home.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
.stepNo { font-family: var(--font-mono); color: var(--text-faint); }
.stepOn { color: var(--text-strong); }
.stepOn .stepNo { color: var(--accent-solid); }
[data-theme='light'] .stepOn .stepNo { color: var(--text-accent); }
@media (max-width: 996px) {
.tour { grid-template-columns: 1fr; gap: var(--space-6); }
.hero { padding: var(--space-12) var(--space-5) var(--space-10); }
Expand Down
3 changes: 2 additions & 1 deletion src/components/PackageGrid/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default function PackageGrid(): ReactNode {
<div className={styles.columns}>
{categories.map((category) => (
<div key={category.id} className={styles.column}>
<h2 className={styles.eyebrow} style={{ color: `var(${category.accent})` }}>
<h2 className={styles.eyebrow} style={{ color: `var(${category.text})` }}>
{category.label}
</h2>
{sectionsOf(category.id).map((section) => (
Expand All @@ -28,6 +28,7 @@ export default function PackageGrid(): ReactNode {
description={section.description}
icon={section.icon}
accent={`var(${category.accent})`}
accentText={`var(${category.text})`}
status={section.status}
href={`/docs/${section.id}`}
/>
Expand Down
Loading
Loading