Databricks Apps (AppKit)
Skill: databricks-app-appkit
What You Can Build
Section titled “What You Can Build”You can build full-stack TypeScript/React applications on the Databricks Apps platform using AppKit — a framework that gives you type-safe SQL queries, ECharts-based visualization components, tRPC for server-side logic, and Lakebase PostgreSQL for persistent storage. Ask your AI coding assistant to scaffold a project and it will generate the init config, SQL query files, typed React components, and deployment config in one pass.
In Action
Section titled “In Action”“Scaffold an AppKit analytics app that connects to my SQL warehouse and shows a bar chart of monthly revenue from catalog.schema.orders”
# Initialize the project with analytics featuresdatabricks apps init my-dashboard \ --features analytics \ --set analytics.sql-warehouse.id=abc123def456-- config/queries/monthly_revenue.sqlSELECT DATE_TRUNC('month', order_date) AS month, SUM(total_amount) AS revenue, COUNT(*) AS order_countFROM catalog.schema.ordersWHERE order_date >= :start_dateGROUP BY DATE_TRUNC('month', order_date)ORDER BY monthimport { BarChart, PageLayout } from "@databricks/appkit-ui";
export default function App() { return ( <PageLayout title="Revenue Dashboard"> <BarChart queryKey="monthly_revenue" params=\{{ start_date: "2024-01-01" }} xKey="month" yKey="revenue" colors={["#FF3621"]} /> </PageLayout> );}Key decisions:
- SQL files in
config/queries/— AppKit auto-generates TypeScript types from your SQL. Reference queries by filename (queryKey="monthly_revenue"), never write manual fetch logic. npm run typegenbefore UI code — types don’t exist until you run typegen. Write SQL first, generate types, then build the React components.- ECharts components via props —
BarChart,LineChart,DataTableare configured through props (xKey,yKey,colors), not children. These are not Recharts. - Colon-prefix parameters —
:start_datein SQL becomes a typed prop in the component. AppKit binds them at execution time.
More Patterns
Section titled “More Patterns”Add Lakebase for read/write storage
Section titled “Add Lakebase for read/write storage”“Add a Lakebase feature to my AppKit app so users can save and load dashboard preferences”
databricks apps init my-app \ --features analytics,lakebase \ --set analytics.sql-warehouse.id=abc123 \ --set lakebase.postgres.branch=main// server/server.ts — tRPC mutation for Lakebase writesimport { initTRPC } from "@trpc/server";import { getExecutionContext } from "@databricks/appkit";import { z } from "zod";
const t = initTRPC.create();
export const appRouter = t.router({ savePreference: t.procedure .input(z.object({ key: z.string(), value: z.string() })) .mutation(async ({ input }) => { const { lakebasePool } = getExecutionContext(); await lakebasePool.query( "INSERT INTO preferences (key, value) VALUES ($1, $2) ON CONFLICT (key) DO UPDATE SET value = $2", [input.key, input.value] ); return { success: true }; }),});Use SQL query files for warehouse reads (analytics) and tRPC + Lakebase for writes (mutations). Never use tRPC for SELECT queries against the SQL warehouse — useAnalyticsQuery handles that with caching and type safety.
Call a model serving endpoint
Section titled “Call a model serving endpoint”“Add a tRPC endpoint that sends a prompt to my model serving endpoint and returns the response”
queryModel: t.procedure .input(z.object({ prompt: z.string() })) .query(async ({ input: { prompt } }) => { const { serviceDatabricksClient: client } = getExecutionContext(); return await client.servingEndpoints.query({ name: "my-agent-endpoint", messages: [{ role: "user", content: prompt }], }); }),getExecutionContext() provides a pre-authenticated Databricks client — no manual token management. Use it for any Databricks API call: serving endpoints, jobs, MLflow, Unity Catalog.
Deploy with validation
Section titled “Deploy with validation”“Validate and deploy my AppKit app”
# Validate app.yaml and configdatabricks apps validate --profile my-workspace
# Deploydatabricks apps deploy my-dashboard --profile my-workspaceAlways validate before deploying. The validator catches missing permissions, invalid SQL warehouse references, and malformed app.yaml before you hit runtime errors.
Watch Out For
Section titled “Watch Out For”- Writing UI before typegen — types in
appKitTypes.d.tsdon’t exist until you runnpm run typegen. Write SQL files first, generate types, then build React components. Skipping this gives youanytypes and no autocomplete. - Using tRPC for SQL SELECTs —
useAnalyticsQueryconnects SQL files to components with caching and pagination built in. tRPC is for mutations, API calls, and server-side logic only. - SQL numbers arriving as strings — Databricks SQL may return numeric columns as strings in the TypeScript layer. Always convert with
Number(row.amount)before math or chart rendering. - Recharts patterns on ECharts components — AppKit charts are ECharts-based and use props (
xKey,yKey,colors), not JSX children. Passing<Bar dataKey="value" />children does nothing.