Packages
One scope, four categories.
Install the meta-package for a matching set, or take the layers you need on their own.
Framework
Registry, RPC, shared state and config across addon realms.
Read the docsPersisted documents on dynamic properties.
Read the docsReactive values: observable, computed, effect, batch.
Read the docsThe script-event transport: bus, discovery, RPC, replicated state.
Read the docsUI
JSX screens, forms and containers.
Read the docsThemed components with vanilla Minecraft textures.
Read the docsStack navigation between screens.
Read the docsThe layout engine under every screen.
Read the docsContent
Every addon in the world, each with the page it published.
Read the docsSettings in three scopes, and the screens that edit them.
Read the docsIn-game guides authored in MDX.
Read the docsTyped keys, interpolation and plurals, resolved per player.
Read the docsWhat you get
Cross-realm plumbing, already solved.
Six pieces that turn a pile of unrelated behavior packs into one coordinated world.
Runtime discovery
Register once. Every other bedrock-core addon in the world sees you, and you see them, the moment they load.
Typed RPC
Request/response calls to another addon, typed from the interface the peer publishes.
Shared state
A declared shape every realm mirrors locally as a typed tree. Reads are synchronous, writes broadcast a delta.
JSX screens
React-like components for forms and containers. Screens compile ahead of time; only state moves at runtime.
Config, guides and translations
Declare a settings schema, ship an MDX guide and a typed translation bundle; the shared UI renders all three for every addon in the world.
One build chain
Regolith filters compile guides, localization and screens, bundle the scripts, and run your GameTests on a real dedicated server.
In practice
Two packs, no imports.
Register, call, show. Each addon ships on its own and finds the others at runtime.
- 01
- 02
- 03
One call brings the addon online: it validates the manifest, joins the world and starts every subsystem. The config schema becomes typed accessors and an in-game settings screen.
import { core } from '@bedrock-core/server';
export interface EconomyRPC {
getBalance(params: { player: string }): number;
}
const { config } = core.register({
manifest: { creator: 'drav0011', pack: 'economy', packName: 'Economy', version: '1.0.0' },
config: {
server: {
economy: {
startingBalance: { type: 'number', default: 100, min: 0, max: 10000, label: 'Starting Balance' },
},
},
} as const,
});
core.rpc.serve<EconomyRPC>({
getBalance: ({ player }) => balances.get(player) ?? config.server.economy.startingBalance.get(),
});
import { core } from '@bedrock-core/server';
core.register({
manifest: {
creator: 'drav0011', pack: 'shop', packName: 'Shop', version: '1.0.0',
dependencies: ['drav0011_economy'],
},
});
core.registry.onDependenciesSatisfied(async () => {
const economy = core.rpc.typed<EconomyRPC>('drav0011_economy');
const balance = await economy.getBalance({ player: 'Steve' });
console.warn(`[shop] balance: ${balance}`);
});
import { render, Text } from '@bedrock-core/ui';
import { Button, Card } from '@bedrock-core/ore-styled';
function Shop({ balance }: { balance: number }) {
return (
<Card>
<Text>{`Balance: ${balance}`}</Text>
<Button onPress={({ player }) => buy(player)}>{'Buy'}</Button>
</Card>
);
}
render(() => <Shop balance={balance} />, player);
Start with one package.
Pin an exact version, and read the changelog before you upgrade.
