Quickstart
[⏱️ ~3 min] Install the three MDK React packages, wrap your app in MdkProvider, and wire headless stores
This page walks through the minimum integration of the MDK UI toolkit into a React application.
Prerequisites
- Node.js 20+
- npm 11+ (upgrade npm if
npm -vshows 10.x on Node 22) - React 19+ and react-dom 19+
Install
# Clone the MDK UI monorepo (adjust the URL to your fork if needed)
git clone https://github.com/tetherto/mdk.git
cd mdk
# Install dependencies and build packages (npm workspaces)
npm install
npm run buildThen add to your app's package.json:
{
"dependencies": {
"@tetherto/mdk-react-devkit": "*",
"@tetherto/mdk-react-adapter": "*",
"@tetherto/mdk-ui-core": "*"
}
}Wrap your app in <MdkProvider> from @tetherto/mdk-react-adapter when using connected foundation components
or adapter store hooks.
Run npm install from the monorepo root after your app is under apps/ so npm links workspace packages.
Wrap your app in MdkProvider
MdkProvider sets up the TanStack QueryClient and the API base URL context. It is required for foundation hooks and components that read shared app state.
// main.tsx
import { MdkProvider } from '@tetherto/mdk-react-adapter'
import '@tetherto/mdk-react-devkit/styles.css'
ReactDOM.createRoot(rootElement).render(
<MdkProvider apiBaseUrl="https://app-node.example.com">
<App />
</MdkProvider>,
)Use the adapter hooks inside React
Each hook subscribes the component to the relevant Zustand store and re-renders only when the selected slice changes.
import { useActions, useAuth, useDevices } from '@tetherto/mdk-react-adapter'
const Toolbar = () => {
const { permissions } = useAuth()
const { selectedDevices } = useDevices()
const { setAddPendingSubmissionAction } = useActions()
// ...
}Or read / write stores directly outside React
The vanilla stores expose getState() / setState() so utility code, side-effect handlers, and tests can interact with the same source of truth.
import { actionsStore, devicesStore } from '@tetherto/mdk-ui-core'
// Outside React (utilities, sagas, etc.) you can read/write directly:
devicesStore.getState().setSelectedDevices([])
actionsStore.getState().setAddPendingSubmissionAction({ /* … */ })Theme via design tokens and @layer mdk
The compiled stylesheet declares @layer base, mdk, app — so unlayered or @layer app styles in your application always win against devkit
component styles. MDK ships with --mdk-color-primary: #f7931a; override tokens in :root only when reskinning.
/* app.css — imported AFTER @tetherto/mdk-react-devkit/styles.css */
:root {
--mdk-color-primary: #f7931a;
--mdk-radius: 6px;
}
@layer app {
.mdk-button--variant-primary { letter-spacing: 0.04em; }
}See Theme for design tokens and @layer override rules.
Next steps
- Tutorial — full integration walkthrough
- Hooks — state hooks, component hooks, and utility hooks
- Explore the demo — run the demo browser without adding MDK to your own app yet
- Core — primitives reference (
@tetherto/mdk-react-devkit/core) - Foundation — mining-domain components (
@tetherto/mdk-react-devkit/foundation)