Quickstart
Scaffold a devstack app or install the packages in an existing app.
The fastest path is the scaffolded app:
pnpm create @mysten-incubation/devstack-app my-app
cd my-app
pnpm devFor an existing app, install the devstack package, the dev wallet used by the generated browser bindings, and the shared tsconfig package:
pnpm add @mysten-incubation/devstack @mysten-incubation/dev-wallet @mysten/signers
pnpm add -D @mysten-incubation/tsconfigThen add a devstack.config.ts at the app root:
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import {
defineDevstack,
account,
HOST_SERVICE_PORT_TOKEN,
hostService,
localPackage,
sui,
wallet,
} from '@mysten-incubation/devstack';
const HERE = dirname(fileURLToPath(import.meta.url));
const DEV_PORT = 5173;
export const localnet = sui();
export const publisher = account('publisher');
export const alice = account('alice');
export const bob = account('bob');
export const hello = localPackage('hello', {
sourcePath: resolve(HERE, 'move/hello'),
publisher,
});
export const devWallet = wallet({
accounts: [publisher, alice, bob],
});
export const app = hostService({
name: 'app',
script: `pnpm exec vite --host 127.0.0.1 --strictPort --port ${HOST_SERVICE_PORT_TOKEN}`,
cwd: HERE,
port: DEV_PORT,
ready: { kind: 'http' },
after: [hello, devWallet] as const,
});
export default defineDevstack({
members: [localnet, app],
stackName: 'main',
codegen: { outputDir: 'src/generated' },
});Add a plain Vite config. The stack passes the allocated port through the hostService command.
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite';
export default defineConfig({ plugins: [react()] });The generated files are importable from application code. For dapp-kit wiring, consume the generated config file and the generated Sui network file:
import { createDAppKit } from '@mysten/dapp-kit-react';
import { devWalletInitializer } from '@mysten-incubation/dev-wallet';
import { DevstackSignerAdapter, parseDevstackToken } from '@mysten-incubation/dev-wallet/adapters';
import { SuiGrpcClient } from '@mysten/sui/grpc';
import { dappKitConfig } from './generated/dapp-kit/config.js';
import { suiNetwork } from './generated/sui/network.js';
export const dAppKit = createDAppKit({
networks: [dappKitConfig.chain],
defaultNetwork: dappKitConfig.chain,
createClient() {
return new SuiGrpcClient({
network: dappKitConfig.chain,
baseUrl: suiNetwork.rpcUrl,
});
},
walletInitializers: [
devWalletInitializer({
adapters: [
new DevstackSignerAdapter({
serverOrigin: dappKitConfig.walletUrl,
token: parseDevstackToken(dappKitConfig.pairUrl),
name: 'Devstack',
}),
],
autoConnect: true,
createInitialAccount: false,
}),
],
});Run the stack:
pnpm devstack upReconcile from another shell, CI, or before typechecking:
pnpm devstack applyIf pnpm devstack up is already live for this stack, apply reuses that supervisor and waits for
it to finish. Without a live supervisor, it runs the same setup in one-shot mode.
Use the generated files from src/generated, and treat .devstack/ as runtime state only.