diff --git a/apps/sim/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/dashboard-empty-state.tsx b/apps/sim/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/dashboard-empty-state.tsx
new file mode 100644
index 00000000000..0e161c0e1f7
--- /dev/null
+++ b/apps/sim/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/dashboard-empty-state.tsx
@@ -0,0 +1,130 @@
+import { cn } from '@sim/emcn'
+import { EmptyState } from '@/components/empty-state/empty-state'
+import { HAIRLINE } from '@/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/hairline'
+import { MASK_NO_REPEAT } from '@/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/mask'
+
+/**
+ * Skeleton ink — see the `INK` note in `tables-empty-state.tsx` for why not the surface
+ * ramp. `line` is the tables selection ring's opaque mix, so a chart stroke reads as the
+ * one drawn mark rather than more placeholder.
+ */
+const INK = {
+ strong: 'color-mix(in srgb, var(--text-secondary) 30%, transparent)',
+ soft: 'color-mix(in srgb, var(--text-secondary) 15%, transparent)',
+ area: 'color-mix(in srgb, var(--text-secondary) 7%, transparent)',
+ line: 'color-mix(in srgb, var(--text-secondary) 46%, var(--bg))',
+} as const
+
+/** The tables grid's corner fade: the trend panel keeps its meaning cropped. */
+const CORNER_FADE =
+ '[-webkit-mask-image:linear-gradient(to_right,#000_62%,transparent_100%),linear-gradient(to_bottom,#000_56%,transparent_100%)] [mask-image:linear-gradient(to_right,#000_62%,transparent_100%),linear-gradient(to_bottom,#000_56%,transparent_100%)] [-webkit-mask-composite:source-in] [mask-composite:intersect]'
+
+type Point = readonly [number, number]
+
+const SPARKLINE = [
+ [52, 62],
+ [66, 56],
+ [80, 59],
+ [94, 50],
+ [108, 53],
+ [122, 44],
+ [136, 47],
+ [150, 40],
+] as const
+
+const TREND = [
+ [52, 140],
+ [82, 128],
+ [112, 133],
+ [142, 112],
+ [172, 118],
+ [202, 98],
+ [232, 104],
+ [262, 86],
+ [292, 92],
+ [322, 76],
+] as const
+
+const LEGEND = [
+ { y: 33, width: 34, fill: INK.strong },
+ { y: 42, width: 44, fill: INK.soft },
+ { y: 51, width: 28, fill: INK.soft },
+] as const
+
+const DONUT = { cx: 202, cy: 44, r: 16, strokeWidth: 6 } as const
+
+function toPath(points: readonly Point[]): string {
+ return points.map(([x, y], i) => `${i === 0 ? 'M' : 'L'} ${x} ${y}`).join(' ')
+}
+
+const CHART_STROKE = {
+ stroke: INK.line,
+ strokeLinecap: 'round',
+ strokeLinejoin: 'round',
+} as const
+
+/** A stat tile, a donut tile, and a wide trend panel running off two edges. */
+function DashboardGraphic() {
+ const donutArc = {
+ cx: DONUT.cx,
+ cy: DONUT.cy,
+ r: DONUT.r,
+ strokeWidth: DONUT.strokeWidth,
+ pathLength: 100,
+ transform: `rotate(-90 ${DONUT.cx} ${DONUT.cy})`,
+ }
+ return (
+
+ )
+}
+
+/** Empty state for a workspace whose dashboard Sim has not built yet. */
+export function DashboardEmptyState() {
+ return (
+ }
+ title='Dashboard'
+ description='Sim will build your dashboard here once your workspace is set up.'
+ />
+ )
+}
diff --git a/apps/sim/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/index.ts b/apps/sim/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/index.ts
index e7d9ddd4474..488ce28e54e 100644
--- a/apps/sim/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/index.ts
+++ b/apps/sim/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/index.ts
@@ -1,3 +1,4 @@
+export { DashboardEmptyState } from '@/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/dashboard-empty-state'
export { DocumentsEmptyState } from '@/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/documents-empty-state'
export { FilesEmptyState } from '@/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/files-empty-state'
export { KnowledgeEmptyState } from '@/app/workspace/[workspaceId]/components/resource/components/resource-empty-state/knowledge-empty-state'
diff --git a/apps/sim/components/dashboards/dashboard-resource.tsx b/apps/sim/components/dashboards/dashboard-resource.tsx
index f0346b2b1b6..4d3df59dba5 100644
--- a/apps/sim/components/dashboards/dashboard-resource.tsx
+++ b/apps/sim/components/dashboards/dashboard-resource.tsx
@@ -3,7 +3,7 @@
import { DashboardFeatureGate } from '@/components/dashboards/dashboard-feature-gate'
import { DashboardLoading } from '@/components/dashboards/dashboard-loading'
import { DashboardPreview } from '@/components/dashboards/dashboard-preview'
-import { EmptyState } from '@/components/empty-state/empty-state'
+import { DashboardEmptyState } from '@/app/workspace/[workspaceId]/components/resource/components/resource-empty-state'
import { Resource } from '@/app/workspace/[workspaceId]/components/resource/resource'
import { useWorkspaceFilesRoom } from '@/app/workspace/[workspaceId]/files/hooks/use-workspace-files-room'
import { useWorkspaceDashboard } from '@/hooks/queries/dashboards'
@@ -42,10 +42,7 @@ function EnabledDashboardResource({ workspaceId }: DashboardResourceProps) {
/>
) : (
-
+
)}
)