dojo-system
Create Dojo systems that implement game logic, modify model state, and handle player actions. Use when implementing game mechanics, player commands, or automated logic.
dojo-react
Use for React integration patterns and best practices in dojo.js. Triggers: dojo react, react hooks, effect atoms, Result.match, infinite scroll dojo, DojoSdkProvider, useDojoSDK, react patterns
Full skill instructions
Use this skill when:
Recommended order:
import { StarknetConfig } from "@starknet-react/core";
import { DojoSdkProvider } from "@dojoengine/sdk/react";
function Providers({ children }) {
return (
<StarknetConfig connectors={connectors}>
<DojoSdkProvider
dojoConfig={dojoConfig}
sdk={sdk}
clientFn={createClient}
>
{children}
</DojoSdkProvider>
</StarknetConfig>
);
}
import { useDojoSDK } from "@dojoengine/sdk/react";
function GameComponent() {
const {
sdk, // SDK instance
config, // DojoConfig
client, // Client from clientFn
provider, // DojoProvider
useDojoStore // Zustand store hook
} = useDojoSDK();
}
Effect atoms provide robust async state management:
import { createEntityQueryAtom } from "@dojoengine/react/effect";
import { Result } from "@dojoengine/react/effect";
const playersAtom = createEntityQueryAtom(
runtime,
new ToriiQueryBuilder().addEntityModel("game-Player").withLimit(100)
);
function PlayerList() {
const players = useAtomValue(playersAtom);
return Result.match(players, {
onSuccess: ({ value }) => (
<ul>
{value.items.map(p => <li key={p.entityId}>{p.models.game.Player.name}</li>)}
</ul>
),
onFailure: (error) => <div>Error: {error.message}</div>,
onInitial: () => <div>Loading...</div>
});
}
import { createEntityUpdatesAtom } from "@dojoengine/react/effect";
const updatesAtom = createEntityUpdatesAtom(
runtime,
KeysClause(["game-Player"], [], "VariableLen").build()
);
import { createEntityQueryWithUpdatesAtom } from "@dojoengine/react/effect";
const livePlayersAtom = createEntityQueryWithUpdatesAtom(
runtime,
query,
clause
);
import { createEntitiesInfiniteScrollAtom } from "@dojoengine/react/effect";
const infinitePlayersAtom = createEntitiesInfiniteScrollAtom(
runtime,
new ToriiQueryBuilder().addEntityModel("game-Player"),
20 // page size
);
function InfinitePlayerList() {
const [state, loadMore] = useAtom(infinitePlayersAtom);
return Result.match(state, {
onSuccess: ({ value }) => (
<>
<ul>
{value.items.map(p => (
<li key={p.entityId}>{p.models.game.Player.name}</li>
))}
</ul>
{value.hasMore && (
<button onClick={loadMore}>Load More</button>
)}
</>
),
onFailure: (error) => <div>Error: {error.message}</div>,
onInitial: () => <div>Loading...</div>
});
}
import {
createTokenBalanceQueryAtom,
createTokenBalanceUpdatesAtom
} from "@dojoengine/react/effect";
// One-time query
const balanceAtom = createTokenBalanceQueryAtom(runtime, {
contractAddresses: ["0x..."],
accountAddresses: [playerAddress]
});
// Polling updates
const liveBalanceAtom = createTokenBalanceUpdatesAtom(
runtime,
{ contractAddresses: ["0x..."], accountAddresses: [playerAddress] },
5000 // poll every 5 seconds
);
Transform data before rendering:
const formatters = {
models: {
"game-Player": (player) => ({
...player,
displayName: player.name || "Anonymous",
displayScore: `${player.score.toLocaleString()} pts`
})
},
fields: {
"game-Player.score": (score) => Math.floor(score / 100)
}
};
const playersAtom = createEntityQueryAtom(runtime, query, formatters);
import { createSubscriptionHook } from "@dojoengine/sdk/react";
const usePlayerSubscription = createSubscriptionHook({
subscribeMethod: (sdk, params) => sdk.subscribeEntityQuery(params),
processInitialData: (data) => data.items,
processUpdateData: (update) => update
});
function PlayerTracker({ entityId }) {
const { data, error, isLoading } = usePlayerSubscription({
query: new ToriiQueryBuilder()
.withClause(KeysClause(["game-Player"], [entityId]).build())
});
}
Optimize re-renders with selectors:
function PlayerScore({ entityId }) {
const { useDojoStore } = useDojoSDK();
// Only re-render when score changes
const score = useDojoStore(
state => state.entities[entityId]?.models?.game?.Player?.score,
(a, b) => a === b // equality function
);
return <span>{score}</span>;
}
import { useEntityId } from "@dojoengine/sdk/react";
function PlayerCard({ address, gameId }) {
// Memoized entity ID computation
const entityId = useEntityId(address, gameId);
const player = useModel(entityId, "game-Player");
}
import { ErrorBoundary } from "react-error-boundary";
function GameErrorFallback({ error, resetErrorBoundary }) {
return (
<div>
<p>Something went wrong: {error.message}</p>
<button onClick={resetErrorBoundary}>Retry</button>
</div>
);
}
function App() {
return (
<ErrorBoundary FallbackComponent={GameErrorFallback}>
<Game />
</ErrorBoundary>
);
}
Create Dojo systems that implement game logic, modify model state, and handle player actions. Use when implementing game mechanics, player commands, or automated logic.
CRITICAL: Use for generics, traits, zero-cost abstraction. Triggers: E0277, E0308, E0599, generic, trait, impl, dyn, where, monomorphization, static dispatch, dynamic dispatch, impl Trait, trait bound not satisfied, 泛型, 特征, 零成本抽象, 单态化
Manage world permissions, namespaces, resource registration, and access control. Use when configuring world ownership, setting up authorization policies, or managing resource permissions.
Integrate Cartridge's Verifiable Random Function (VRF) for provably fair, atomic randomness in Dojo games.
Integrate Dojo with game clients for JavaScript, Unity, Unreal, Rust, and other platforms. Generate typed bindings and connection code. Use when connecting frontends or game engines to your Dojo world.
Deploy Dojo worlds to local Katana, testnet, or mainnet. Configure Katana sequencer and manage deployments with sozo. Use when deploying your game or starting local development environment.
Write tests for Dojo models and systems using spawn_test_world, cheat codes, and assertions. Use when testing game logic, verifying state changes, or ensuring system correctness.
Manage world migrations, handle breaking changes, and upgrade Dojo versions. Use when updating deployed worlds, migrating to new versions, or handling schema changes.
Initialize new Dojo projects with proper directory structure, configuration files, and dependencies. Use when starting a new Dojo game project or setting up the initial project structure.
Configure Scarb.toml, dojo profiles, world settings, and dependencies. Use when setting up project configuration, managing dependencies, or configuring deployment environments.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience