@datadog/apps-frontend
Frontend capabilities for Datadog Apps.
npm install @datadog/apps-frontend
The package root exposes nothing: React capabilities live in this package's subpath entries.
@datadog/apps-frontend/embedding/react—DatadogAppProviderconnects an app to its host, installs this package's default modules, and shares one embedding connection with every module hook beneath it;useDatadogAppEmbeddingreads that connection's state.@datadog/apps-frontend/inputs/react—useDatadogAppInputreads a typed input the host provides.@datadog/apps-frontend/inputs/schema— the input schemas themselves, such asdatadogThemeanddatadogDashboard, passed touseDatadogAppInput.@datadog/apps-frontend/parameters—defineDatadogAppParametersdeclares the settings someone can choose each time they embed the app.@datadog/apps-frontend/parameters/react—useDatadogAppParametersreads the values chosen for the current embed.@datadog/apps-frontend/visualizations/react—DatadogVisualizationrenders a native Datadog widget, embedded or underdatadog-apps dev.@datadog/apps-frontend/visualizations— widget-definition and time-frame types, plusDatadogVisualizationError.
Usage
Mount the provider near your app root; it installs this package's default modules and shares one embedding connection with every module hook beneath it:
import { DatadogAppProvider } from '@datadog/apps-frontend/embedding/react';
export function App() {
return <DatadogAppProvider>{/* app UI */}</DatadogAppProvider>;
}
Additional modules are installed by passing them in modules. A module is a
startup capability, not a UI layer: on mount the provider runs each one's
install with the shared connection and a dispose signal, and the app's UI
renders untouched:
<DatadogAppProvider modules={[someModule({ option: true })]}>
{/* app UI */}
</DatadogAppProvider>
disabledModules accepts exactly the ids of this package's default modules —
type-checked and autocompleted from the default set, so a misspelled id is a
compile error. Deep links ('datadog.deep-links') is installed by default and
can be excluded when an app must opt out. At runtime an unknown id only warns,
so a frozen app compiled against an older default set keeps rendering.
Parameters
Parameters let one app be embedded in several places with different settings, such as an environment or a row limit. Declare them where you read them:
import { defineDatadogAppParameters } from '@datadog/apps-frontend/parameters';
import { useDatadogAppParameters } from '@datadog/apps-frontend/parameters/react';
function Results() {
const parameters = useDatadogAppParameters(
defineDatadogAppParameters({
environment: {
type: 'string',
label: 'Environment',
default: 'production',
options: ['production', 'staging'],
},
limit: { type: 'number', label: 'Rows', default: 10 },
}),
);
if (parameters.status !== 'ready') {
return null;
}
const { environment, limit } = parameters.values; // 'production' | 'staging', number
// ...
}
The Datadog Vite plugin finds these declarations when the app is built and records them with each upload, so Datadog shows matching controls when someone adds or configures the embed. Write declarations literally (plain strings, numbers, and booleans, without variables or spreads) so the build can read them. A declaration can also live in its own module and be shared by several components; the same parameter may be declared in several places only if each declaration is identical.
Values always match the declaration: a missing or outdated value uses its default, and outside a configured embed every parameter has its default. Values are stored with the embed and sent to the browser, so parameters must never hold secrets.
React 18 and 19 are supported as peer dependencies. @datadog/druids is an
optional peer, needed by the druids/react entry and by visualizations;
@datadog/action-catalog is an optional peer, needed only by visualizations.
Visualizations
Render native Datadog visualizations in a Datadog App with DatadogVisualization from @datadog/apps-frontend/visualizations/react.
Charts need:
@datadog/action-cataloginstalled beside this package.@datadog/vite-plugin>= 3.4.0(which includes package-provided backend functions) to build the app. An older plugin bundles this package's backend function into the browser instead of running it on Datadog; its charts then show an error instead of data.- DRUIDS' stylesheet and environment, as the default app template sets up:
import
@datadog/druids/styles.cssonce in the app's entry, and render charts insideDruidsEnvironmentWithThemeInputfrom@datadog/apps-frontend/druids/react. Charts define no design tokens or fonts of their own; they use DRUIDS'--ui-*tokens, light and dark themes, and fonts from these.
Datadog's chart renderer, the current build of its v1 channel, loads at
runtime and runs in your app's page with its normal data handling. Each
request it makes runs as a backend function this package ships, through
Datadog's public query actions: the Datadog Apps build compiles it into your
app, so charts get the platform's identity, permissions, and limits wherever
the app runs, embedded or under datadog-apps dev. You write no backend code
for it, and no frame is nested.
import type { DatadogVisualizationDefinition } from '@datadog/apps-frontend/visualizations';
import { DatadogVisualization } from '@datadog/apps-frontend/visualizations/react';
const cpu: DatadogVisualizationDefinition = {
type: 'timeseries',
requests: [
{
response_format: 'timeseries',
queries: [
{
data_source: 'metrics',
name: 'cpu',
query: 'avg:system.cpu.user{*}',
},
],
formulas: [{ formula: 'cpu' }],
display_type: 'line',
},
],
};
<DatadogVisualization definition={cpu} height={300} />;
- Definitions use the public Dashboard API's widget format, as plain JSON.
- Charts query through Datadog's public query actions, so they support what
those actions take:
- Widgets whose data comes from timeseries or scalar formula queries, such
as
timeseriesandquery_value. A widget that needs any other Datadog endpoint shows an error in the chart. - Queries on the
metricsandcloud_costdata sources, andlogs,rumanddoraevents. The actions reject any other data source, such as APM spans or security signals, and the chart shows their error. - Scalar queries support sorting by a single formula; sorting a query table by a group column is not supported and shows an error.
- The actions take no
minimum_intervaland no heatmap pushdown parameters, so for those requests the API picks its own rollup.
- Widgets whose data comes from timeseries or scalar formula queries, such
as
timeFrameaccepts{ start, end, isLive }in milliseconds and is owned by your app, as a Datadog page owns its time. Omit it for the live past hour, refreshed on Datadog's dashboard schedule. When embedded in a dashboard, pass thedatadogDashboardinput'stimeframe.onTimeFrameChangeenables brushing to zoom a timeseries. The chart does not change its own range: keep the reported range in state and pass it back astimeFrame.themeaccepts'light'or'dark';heightdefaults to 300px.onErrorreports invalid inputs, a renderer that could not load, and definitions the renderer cannot display, once per failure. Widget and query failures appear inside the chart, as on Datadog dashboards, including a query that returns too much data for the platform, a timeout, and rate limiting.- The renderer is an ES module loaded from
https://static.datadoghq.comat runtime, so your app's Content Security Policy must allow scripts and styles fromhttps://static.datadoghq.com. Only one renderer build runs per page. Every copy of this package's major loads the same channel, so don't mix majors in one app.
Deep links
Deep links mirror the app's query string and fragment into the host page's URL, so navigation state can be shared and reopened. The module is installed by default; see the deep links guide for the URL format, how to construct shareable links, and how to read deep-link state on load.
Development
cd packages/published/apps-frontend
yarn build
yarn -T typecheck:workspace
yarn -T test-unit:workspace
Authoring Inputs schemas
Write one schema factory with its fields and publication policy, then register
that factory in src/inputs/schemas/. The module owns schema
registration, tooling, and generated host/consumer views. Public imports stay
inputs/schema; web-ui hosts use inputs/internal.
Releasing visualizations
Charts load the renderer (static-apps/apps-visualization-renderer) from its
v1 channel on Datadog's public static CDN,
https://static.datadoghq.com/apps-visualization-renderer/v1/renderer.js.
Each renderer deploy uploads an immutable build to v/<version>/, then
points the channel at it; the channel is cached for five minutes. A renderer
fix therefore reaches apps without a release of this package or an app
re-upload. The renderer must be deployed to production before the first
release whose charts load it.
Within v1, every renderer build must keep working with every uploaded app,
including the oldest backend function this package has shipped
(src/visualizations/data.backend.ts): it accepts only
/api/ui/query/timeseries and /api/ui/query/scalar with their current
data[].attributes request bodies, and returns the response shape the
renderer reads. Fixes to the backend function itself still need a release of
this package and an app re-upload.
A breaking change to the renderer contract ships as a v2 channel with a new
major of this package. For development, build against another renderer URL with
APPS_VISUALIZATION_RENDERER_URL=<module URL> yarn build.
License
Apache-2.0