Skip to content

Create a dev toolbar app

Astro includes a development toolbar that you can use to inspect your site, check for accessibility and performance issues, and more. This toolbar can be extended with custom apps.

Build a motivational dev toolbar app

Section titled Build a motivational dev toolbar app

In this recipe, you’ll learn how to create a dev toolbar app that helps you stay motivated while working on your site. This app will display a motivational message every time you toggle it on.

Creating the Astro integration

Section titled Creating the Astro integration

Dev toolbar apps can only be added by Astro Integrations using the astro:config:setup hook. You will need to create both a toolbar app and the integration that will add it to the toolbar of your existing Astro project.

  1. In the root of your existing Astro project, create a new folder named my-toolbar-app/ for your app and integration files. Create two new files in this folder: app.ts and my-integration.ts.

    • Directorymy-toolbar-app/
      • app.ts
      • my-integration.ts
    • Directorysrc/
      • Directorypages/
    • astro.config.mjs
    • package.json
    • tsconfig.json
  2. In my-integration.ts, add the following code to provide both the name of your integration and the addDevToolbarApp() function needed to add your dev toolbar app with the astro:config:setup hook:

    my-toolbar-app/my-integration.ts
    import { fileURLToPath } from 'node:url';
    import type { AstroIntegration } from 'astro';
    export default {
    name: 'my-astro-integration',
    hooks: {
    'astro:config:setup': ({ addDevToolbarApp }) => {
    addDevToolbarApp({
    id: "my-toolbar-app",
    name: "My Toolbar App",
    icon: "🚀",
    entrypoint: fileURLToPath(new URL('./app.ts', import.meta.url))
    });
    },
    },
    } satisfies AstroIntegration;
  3. To use this integration in your project, add it to the integrations array in your astro.config.mjs file.

    astro.config.mjs
    import { defineConfig } from 'astro/config';
    import myIntegration from './my-toolbar-app/my-integration.ts';
    export default defineConfig({
    integrations: [myIntegration],
    })
  4. If not already running, start the dev server. If your integration has been successfully added to your project, you should see a new “undefined” app in the dev toolbar.

    But, you will also see an error message that your dev toolbar app has failed to load. This is because you have not yet built the app itself. You will do that in the next section.

See the Astro Integration API documentation for more about building Astro integrations.

Dev toolbar apps are defined using the defineToolbarApp() function from the astro/toolbar module. This function takes an object with an init() function that will be called when the dev toolbar app is loaded.

This init() function contains your app logic to render elements to the screen, send and receive client-side events from the dev toolbar, and communicate with the server.

app.ts
import { defineToolbarApp } from "astro/toolbar";
export default defineToolbarApp({
init(canvas, app, server) {
// ...
},
});

To display motivational messages on the screen, you will use the canvas property to access a standard ShadowRoot. Elements can be created and added to the ShadowRoot using the standard DOM APIs.

  1. Copy the following code into my-toolbar-app/app.ts. This provides a list of motivational messages, and the logic to create a new <h1> element with a random message:

    my-toolbar-app/app.ts
    import { defineToolbarApp } from "astro/toolbar";
    const motivationalMessages = [
    "You're doing great!",
    "Keep up the good work!",
    "You're awesome!",
    "You're a star!",
    ];
    export default defineToolbarApp({
    init(canvas) {
    const h1 = document.createElement('h1');
    h1.textContent = motivationalMessages[Math.floor(Math.random() * motivationalMessages.length)];
    canvas.append(h1);
    },
    });
  2. Start the dev server if it is not already running and toggle the app on in the dev toolbar. If your app is working successfully, you will see a motivational message displayed in the top-left corner of the screen. (And, it’s true!)

    However, this message will not change when the app is toggled on and off, as the init() function is only called once when the app is loaded.

  3. To add client-side interactivity to your app, add the app argument and use onAppToggled() to select a new random message each time your toolbar app is toggled on:

    app.ts
    import { defineToolbarApp } from "astro/toolbar";
    const motivationalMessages = [
    "You're doing great!",
    "Keep up the good work!",
    "You're awesome!",
    "You're a star!",
    ];
    export default defineToolbarApp({
    init(canvas, app) {
    const h1 = document.createElement('h1');
    h1.textContent = motivationalMessages[Math.floor(Math.random() * motivationalMessages.length)];
    canvas.append(h1);
    // Display a random message when the app is toggled
    app.onToggled(({ state }) => {
    const newMessage = motivationalMessages[Math.floor(Math.random() * motivationalMessages.length)];
    h1.textContent = newMessage;
    });
    },
    });
  4. In your browser preview, toggle your app on and off several times. With this change, a new random message will be selected every time you toggle the app on, providing you with an infinite source of motivation!

See the Astro Dev Toolbar API documentation for more about building dev toolbar apps.

Building apps with a UI framework

Section titled Building apps with a UI framework

UI frameworks like React, Vue, or Svelte can also be used to create dev toolbar apps. These frameworks provide a more declarative way to create UIs and can make your code more maintainable and easier to read.

The same motivational dev toolbar app built into your existing Astro project earlier on this page with JavaScript can be built using a UI framework (e.g. Preact) instead. Depending on your chosen framework, you may or may not require a build step.

If your framework supports it, you can create a dev toolbar app without a build step. For example, you can use Preact’s h function to create elements and render them directly to the ShadowRoot:

app.ts
import { defineToolbarApp } from "astro/toolbar";
import { render, h } from "preact";
const motivationalMessages = [
"You're doing great!",
"Keep up the good work!",
"You're awesome!",
"You're a star!",
];
export default defineToolbarApp({
init(canvas) {
const message = motivationalMessages[Math.floor(Math.random() * motivationalMessages.length)];
render(h('h1', null, message), canvas);
},
});

Alternatively, the htm package is a good choice for creating dev toolbar apps without a build step, offering native integration for React and Preact and support for other frameworks:

app.ts
import { defineToolbarApp } from "astro/toolbar";
import { render } from "preact";
import { html } from 'htm/preact';
const motivationalMessages = [
"You're doing great!",
"Keep up the good work!",
"You're awesome!",
"You're a star!",
];
export default defineToolbarApp({
init(canvas) {
const message = motivationalMessages[Math.floor(Math.random() * motivationalMessages.length)];
render(html`<h1>${message}</h1>`, canvas);
},
});

In both cases, you can now start your project and see the motivational message displayed in the top-left corner of the screen when you toggle the app on.

Astro does not preprocess JSX code in dev toolbar apps, so a build step is required in order to use JSX components in your dev toolbar app.

The following steps will use TypeScript to do this, but any other tools that compile JSX code will also work (e.g. Babel, Rollup, ESBuild).

  1. Install TypeScript inside your project:

    Terminal window
    npm install --save-dev typescript
  2. Create a tsconfig.json file in the root of your toolbar app’s folder with the appropriate settings to build and for the framework you’re using (React, Preact, Solid). For example, for Preact:

    my-toolbar-app/tsconfig.json
    {
    "compilerOptions": {
    "skipLibCheck": true,
    "module": "NodeNext",
    "jsx": "react-jsx",
    "jsxImportSource": "preact",
    }
    }
  3. Adjust the entrypoint in your integration to point to the compiled file, remembering that this file is relative to the root of your Astro project:

    my-integration.ts
    addDevToolbarApp({
    id: "my-toolbar-app",
    name: "My Toolbar App",
    icon: "🚀",
    entrypoint: join(__dirname, "./app.js"),
    });
  4. Run tsc to build your toolbar app, or tsc --watch to automatically rebuild your app when you make changes.

    With these changes, you can now rename your app.ts file to app.tsx (or .jsx) and use JSX syntax to create your dev toolbar app:

    app.tsx
    import { defineToolbarApp } from "astro/toolbar";
    import { render } from "preact";
    const motivationalMessages = [
    "You're doing great!",
    "Keep up the good work!",
    "You're awesome!",
    "You're a star!",
    ];
    export default defineToolbarApp({
    init(canvas) {
    const message = motivationalMessages[Math.floor(Math.random() * motivationalMessages.length)];
    render(<h1>{message}</h1>, canvas);
    },
    });

You should now have all the tools you need to create a dev toolbar app using a UI framework of your choice!