DevTools

A development overlay for your app. A button in the corner of the page opens three tabs: Inspect tells you what any Astralis component on the page is, Findings shows the validator's findings for your project, live, as you save, and Report sends a problem to the Astralis maintainers with the evidence they need to reproduce it.

It runs in development only. A production build contains none of it.

Why a UI library needs its own#

React DevTools shows the component tree, but it can only show what hydrates in the browser, and many Astralis components never do: 91 of the 238 components and parts in the system spec are Server Components that ship no JavaScript. It also knows nothing about your design system, such as which props a component was configured with, whether those values are valid, or where the component is documented.

The Astralis DevTools read the library itself. In development every component names itself on the element it renders, and a bridge in your dev server runs the same validator as astralis validate and CI.

Set up#

From your project's root:

npx astralis-cli init --devtools

It installs astralis-devtools as a devDependency and wires it in:

  • Next.js: <AstralisDevTools /> goes at the end of <body> in your root layout, and the bridge's route is written to app/api/astralis-devtools/[...path]/route.ts.
  • Vite: astralisDevtools() is added to the plugins of your vite.config.

Projects made with npm create astralis have the DevTools already; pass --no-devtools to leave them out. Running init --devtools again changes nothing.

By hand#

For Next.js, add the component to the root layout:

import { AstralisDevTools } from "astralis-devtools/next";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <AstralisDevTools />
      </body>
    </html>
  );
}

Then create app/api/astralis-devtools/[...path]/route.ts:

export { GET, POST } from "astralis-devtools/next/route";

For Vite, add the plugin:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { astralisDevtools } from "astralis-devtools/vite";

export default defineConfig({
  plugins: [react(), astralisDevtools()],
});

Inspect#

Press Pick a component, hover the page, and click. Clicks while picking go to the DevTools, not to your app, so a link does not navigate and a trigger does not open its menu. Press Esc to stop.

For the component you pick you see:

  • Its name, as you would write it: Card.Body, not div.

  • The props it was given: variant, size, colour scheme and style props, including responsive values such as p={{ base: "4", md: "8" }}. Children, text, links and event handlers are never shown.

  • How it reaches the browser, from the system spec:

    LabelMeaning
    Server ComponentRenders on the server and ships no library JavaScript
    Server shell, client islandRenders on the server; a small interactive part hydrates
    Client ComponentHydrates in the browser to be interactive

    A Vite app renders everything in the browser, so there the label tells you what the component would ship in a server-rendered app.

  • A link to its documentation.

  • What it sits inside: the Astralis components around it, each one click away.

When one component renders through another onto the same element, you see the whole chain. A Modal.Trigger wrapping a Button shows as Modal.Trigger → Button, with each one's props.

Findings#

The Findings tab lists every error and warning astralis validate would report for your project, with file, line and rule. It updates as you save, usually in well under a second. The badge on the button counts the errors, or the warnings when there are no errors.

On Next.js, the files that render the page you are looking at (its page file and every layout and template above it) are listed first, under This page.

Report#

When something in Astralis looks wrong, pick the component it is in and press Report a problem here, or open the Report tab. Write a title and, if you like, what happened and what you expected. The tab builds an issue snapshot:

  • the Astralis components under the one you picked, each with the props it was given (only those the spec describes; never links, image sources or event handlers);
  • the versions of astralis-ui, your framework and React, your browser and window size, and whether the page is light or dark;
  • the page's path, without its query string;
  • the validator's findings for the files that render the page (on Vite, for the project), unless you untick them.

Page text is replaced by placeholders unless you tick Include page text. Console errors from this session and a screenshot are left out unless you add them.

Below the form is exactly the JSON that would be sent, updated as you type. Nothing leaves your machine until you press Send; the snapshot then goes to Issues & Contributions, the Astralis issue platform, as a private draft, and its page opens so you can sign in with GitHub and submit it. A draft nobody submits is deleted after 24 hours. Copy JSON and Download keep the snapshot without sending it.

From the terminal, astralis report builds the same snapshot from your source files.

The snapshot's component tree is also a reproduction: the platform turns it into a small repro.tsx and runs the validator on it again. Before you submit, it compares the report with open issues: one with the same component, the same rule codes in its findings and the same minor version of astralis-ui is offered as the likely duplicate, and adding your report to it raises its report count instead of opening a second issue.

How it works#

In development, every astralis-ui component adds two attributes to the element it renders:

<div data-astralis="Card.Body" data-astralis-props='[{}]'>

They are part of the server-rendered HTML, which is how Server Components can be inspected. In production the attributes are never rendered: the library's production HTML is byte-for-byte what it would be without the DevTools, and a test holds it to that for every component.

The bridge runs inside your dev server. On Next.js that is the route handler above; on Vite it is dev-server middleware, fed by Vite's own file watcher. It validates your .tsx and .jsx files against the installed astralis-ui's system spec, re-validates each file when you save it, and streams the findings to the overlay.

Privacy and security#

  • Nothing leaves your machine unless you send it. The overlay talks only to your own dev server, and there is no telemetry or background request. The one request that leaves is a report you have read and pressed Send on.
  • The bridge answers this machine only. A request from another device, or from a page on another site, is refused, even when the dev server is open to your network (next dev -H 0.0.0.0).
  • Nothing runs in production. In a production build the Next.js route answers 404 without loading the bridge, and the Vite plugin applies only to vite dev.