# Solved: How to Use React Three Fiber (R3F) in a Grafana Panel Plugin

**URL:** <https://community.grafana.com/t/solved-how-to-use-react-three-fiber-r3f-in-a-grafana-panel-plugin/163393>\
**Category:** Share & showcase\
**Tags:** panel, plugins\
**Created:** [June 23, 2026, 3:59pm UTC](https://community.grafana.com/t/solved-how-to-use-react-three-fiber-r3f-in-a-grafana-panel-plugin/163393 "2026-06-23T15:59:13Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![ouhamouy10](https://avatars.discourse-cdn.com/v4/letter/o/c6cbf5/32.png) [@ouhamouy10](https://community.grafana.com/u/ouhamouy10)\
**Post date:** [June 23, 2026, 3:59pm UTC](https://community.grafana.com/t/solved-how-to-use-react-three-fiber-r3f-in-a-grafana-panel-plugin/163393/1 "2026-06-23T15:59:13Z")

</div>

I needed to use grafa for 3d visualisation and here are the steps I used to use r3f inside a panel plugin:

# 1: make a new panel plugin

htt ps://grafana.com/developers/plugin-tools/tutorials/build-a-panel-plugin  
if you haven’t already, I find myself needing to run `npm i` before `npm run dev`

# 2: intall compatible versions with grafana’s react.

grafana uses r18 so fiber8 works with it  
`npm install three @react-three/fiber@8 @react-three/drei@9`  
`npm install --save-dev @types/three`

# 3: change webpack config:

official docs (htt ps://grafana.com/developers/plugin-tools/how-to-guides/extend-configurations)  
add `webpack.config.ts` to your project root containing the following

```typescript
// webpack.config.ts (Project Root)
import type { Configuration } from 'webpack';
import { merge } from 'webpack-merge';
import grafanaConfig, { Env } from './.config/webpack/webpack.config';
import path from 'path';

const config = async (env: Env): Promise<Configuration> => {
  const baseConfig = await grafanaConfig(env);

  return merge(baseConfig, {
    resolve: {
      alias: {
        // Intercepts the dev build of react-reconciler to prevent the production flag crash
        'react-reconciler': path.resolve(__dirname, 'node_modules/react-reconciler/cjs/react-reconciler.production.min.js'),
      },
    },
  });
};

export default config;

```

then in `package.json` as in the docs(htt ps://grafana.com/developers/plugin-tools/how-to-guides/extend-configurations#3-update-the-packagejson-to-use-the-new-webpack-config)

```diff
-"build": "webpack -c ./.config/webpack/webpack.config.ts --env production",
+"build": "webpack -c ./webpack.config.ts --env production",
-"dev": "webpack -w -c ./.config/webpack/webpack.config.ts --env development",
+"dev": "webpack -w -c ./webpack.config.ts --env development",

```

# 4: use fiber

then in `src/components/SimplePanel.tsx`

```typescript
import React from 'react';
import { PanelProps } from '@grafana/data';
import { SimpleOptions } from 'types';
import { Canvas } from '@react-three/fiber';
import { CameraControls } from '@react-three/drei';

interface Props extends PanelProps<SimpleOptions> { }

export const SimplePanel: React.FC<Props> = ({ options, data, width, height, fieldConfig, id }) => {

  return (
    <div id="canvas-container" style={{ width, height, position: 'relative', overflow: 'hidden' }}>
      <Canvas>
        <directionalLight color="white" position={[0, 2, 5]} />

        <mesh position={[0, 0, 0]} onPointerOver={(e) => { e.stopPropagation() }}>
          <boxGeometry args={[1, 1, 1]} />
          <meshStandardMaterial />
        </mesh>

        <CameraControls />

      </Canvas>
    </div>
  );
};

```

and alhamdo li Allah everything is now working correctly:

 ![Screenshot from 2026-06-23 16-32-18](https://us1.discourse-cdn.com/grafana/original/3X/1/a/1acdd062a5b84eb489959ef95fc425b2e236eb35.png)

it solves [this topic](https://community.grafana.com/t/grafana-not-supports-react-three-fiber/124427) which was closed automatically. @tomglenn  
thanks to [this topic](https://community.grafana.com/t/problems-with-using-react-three-fiber/78128) for the start of the solution.

### extra

We could even do more complex things (for the job, won’t share more)

 ![Screenshot from 2026-06-23 16-55-00](https://us1.discourse-cdn.com/grafana/original/3X/5/7/57176f9693a83ffadeeb9c0562b4643dc68b7c2c.png)

---

<div class="post-metadata">

**Author:** ![vaduga](https://sea2.discourse-cdn.com/grafana/user_avatar/community.grafana.com/vaduga/32/57313_2.png) [@vaduga](https://community.grafana.com/u/vaduga)\
**Post date:** [June 24, 2026, 11:36am UTC](https://community.grafana.com/t/solved-how-to-use-react-three-fiber-r3f-in-a-grafana-panel-plugin/163393/2 "2026-06-24T11:36:38Z")

</div>

nice! How’s your dataframe for this scene look like?

---

<div class="post-metadata">

**Author:** ![ouhamouy10](https://avatars.discourse-cdn.com/v4/letter/o/c6cbf5/32.png) [@ouhamouy10](https://community.grafana.com/u/ouhamouy10)\
**Post date:** [June 24, 2026, 11:53am UTC](https://community.grafana.com/t/solved-how-to-use-react-three-fiber-r3f-in-a-grafana-panel-plugin/163393/3 "2026-06-24T11:53:10Z")

</div>

this scene is generated from JSON data as options

---

<div class="post-metadata">

**Author:** ![vaduga](https://sea2.discourse-cdn.com/grafana/user_avatar/community.grafana.com/vaduga/32/57313_2.png) [@vaduga](https://community.grafana.com/u/vaduga)\
**Post date:** [June 24, 2026, 1:12pm UTC](https://community.grafana.com/t/solved-how-to-use-react-three-fiber-r3f-in-a-grafana-panel-plugin/163393/4 "2026-06-24T13:12:33Z")

</div>

oh really? And what does it look like

---

<div class="post-metadata">

**Author:** ![ouhamouy10](https://avatars.discourse-cdn.com/v4/letter/o/c6cbf5/32.png) [@ouhamouy10](https://community.grafana.com/u/ouhamouy10)\
**Post date:** [June 25, 2026, 9:26am UTC](https://community.grafana.com/t/solved-how-to-use-react-three-fiber-r3f-in-a-grafana-panel-plugin/163393/5 "2026-06-25T09:26:34Z")

</div>

JSON looks something like:  
`rooms = [{ x: 0, y: 0, w: 20, h: 30, components: [{ x: 2, y: 2, rotation: 1, model: 'electric-motor' }] }]`

a room is just a boxGeometry: with side as BackSide

```auto
import { BackSide } from 'three';
...
      <mesh position={[data.width / 2, 5, data.height / 2]}>
        <boxGeometry args={[data.width, 10, data.height]} />
        <meshStandardMaterial side={BackSide} color='orange' />
      </mesh>

```

components:

```auto
const models: any = {
  "electric-motor": ElectricMotor,
} as const;

```

where `ElectricMotor` is r3f component made with the command  
`npx gltfjsx@6.5.3 ./electric-motor.glb --transform`

and modified the result for webpack

```auto
// import modelUrl from './electric-motor-transformed.glb?url'
const modelUrl = new URL('./electric-motor-transformed.glb', import.meta.url).href;

```
