Wire a React app
[⏱️ ~5 min] Step-by-step walkthrough — scaffold an app, wrap in MdkProvider, and use adapter hooks with foundation components
This tutorial walks you through the full React stack: three workspace packages, <MdkProvider>, and adapter hooks.
For a faster path that renders one presentational component without the provider, see Your first component.
Prerequisites
- Node.js >=24
- npm >=11
- React 19+ and react-dom 19+
Clone and build
The mdk/ui directory is the npm workspace root. Clone the repository, install at the workspace root,
and build all packages before adding an app or running the demo.
1.1 Clone the repository
git clone https://github.com/tetherto/mdk.git
cd mdk/ui1.2 Install and build
npm install
npm run buildThis builds @tetherto/mdk-react-devkit and the other packages in the ui/ workspace.
Create your app
2.1 Scaffold a Vite React app
Create a new React app in the apps/ folder:
cd apps
npm create vite@latest my-app -- --template react-ts
cd my-appIgnore the CLI "Now run" instructions — follow the MDK-specific steps below.
2.2 Add MDK to package.json
Open package.json and add all three workspace packages:
"@tetherto/mdk-react-devkit": "*",
"@tetherto/mdk-react-adapter": "*",
"@tetherto/mdk-ui-core": "*",2.3 Install from the workspace root
cd ../.. # from apps/my-app back up to the workspace root mdk/ui
npm installWrap your app in MdkProvider
<MdkProvider> wires the headless stores from @tetherto/mdk-ui-core into React and sets up the TanStack QueryClient. It is required for adapter hooks and connected foundation components. See also Quickstart — Wrap your app in MdkProvider.
3.1 Update main.tsx
import { MdkProvider } from '@tetherto/mdk-react-adapter'
import '@tetherto/mdk-react-devkit/styles.css'Wrap <App />:
<MdkProvider apiBaseUrl="https://app-node.example.com">
<App />
</MdkProvider>Use adapter hooks and render a component
Adapter hooks subscribe to Zustand stores and re-render when the selected slice changes. This example uses useAuth and useDevices from the adapter, then renders a presentational SingleStatCard from foundation.
4.1 Replace App.tsx
import { Button } from '@tetherto/mdk-react-devkit/core'
import { SingleStatCard } from '@tetherto/mdk-react-devkit/foundation'
import { useAuth, useDevices } from '@tetherto/mdk-react-adapter'
function App() {
const { permissions } = useAuth()
const { selectedDevices } = useDevices()
return (
<div style={{ padding: '2rem', display: 'grid', gap: '1rem', maxWidth: 360 }}>
<h1>Operator dashboard</h1>
<p>Selected devices: {selectedDevices?.length ?? 0}</p>
<p>Permissions loaded: {permissions ? 'yes' : 'no'}</p>
<SingleStatCard
name="Inlet temperature"
value={28}
unit="°C"
variant="primary"
/>
<Button onClick={() => console.log('Ready for connected components')}>
Log readiness
</Button>
</div>
)
}
export default AppConnected foundation components (device explorers, pool manager, settings dashboards) expect <MdkProvider> and often read multiple stores. Start with presentational imports while you wire your API; swap in connected components as your backend comes online.
Run your app
From the workspace root mdk/ui:
npm -w my-app run devOr from the app folder:
cd apps/my-app
npm run devYou should see the operator dashboard with device and permission readouts plus a temperature card. The adapter hooks confirm <MdkProvider> is wired — without it, they would throw.
Next steps
- Quickstart: install reference, store hooks, and theming
- Core: primitives reference (
@tetherto/mdk-react-devkit/core) - Foundation: mining-domain components (
@tetherto/mdk-react-devkit/foundation)
Run the demo app
If you are already at the workspace root mdk/ui:
npm run dev:catalogIf your shell is still in the app folder:
cd ../.. # apps/my-app → apps → workspace root mdk/ui
npm run dev:catalogOpen http://localhost:5173/mdk to browse examples.