👾 Boss Level — Module 12

Boss Fight: Build a Real App

Hands-on

The Capstone: Build a 3-Page App

Combine everything you've learned into one app:

Page 1: Overview — KPI cards + CPU timeseries chart
Page 2: Host Explorer — DataTable with row actions + intent navigation
Page 3: External Feed — App function proxying an external API

Page 1: Overview

export const Overview = () => {
  const kpis = useDql({ query: `fetch dt.entity.host | summarize count()` });
  const cpu = useDql({
    query: `timeseries avg(dt.host.cpu.usage), from:-2h`
  });

  return (
    <Flex flexDirection="column" gap={16}>
      <KpiCard title="Total Hosts" value={kpis.data?.records[0]?.count} />
      <div style={{ height: 300 }}>
        <TimeseriesChart data={convertToTimeseries(cpu.data)} />
      </div>
    </Flex>
  );
};

Page 2: Host Explorer

export const HostExplorer = () => {
  const { data } = useDql({
    query: `fetch dt.entity.host | fields entity.name, cpuCores, osType`
  });

  return (
    <DataTable data={data?.records} columns={convertToColumns(data)}>
      <DataTable.RowActions>
        {(row) => (
          <IntentButton appId="dynatrace.notebooks" intentId="view-query"
            payload={{ "dt.query": `fetch dt.entity.host | filter id == "${row.id}"` }}>
            Open in Notebooks
          </IntentButton>
        )}
      </DataTable.RowActions>
    </DataTable>
  );
};

Page 3: External Feed

// api/external-feed.function.ts
export default async function handler() {
  const res = await fetch("https://api.example.com/status");
  return new Response(JSON.stringify(await res.json()));
}

// ui/app/pages/Feed.tsx
const { data } = useAppFunction({ id: "external-feed" });

💡 This is the pattern for every production app: DQL for internal data, app functions for external data, intents for navigation.

What's Next

Module 13 — Secret levels: state persistence, filters, toasts, design tokens.