Skip to content
Closed
Show file tree
Hide file tree
Changes from 109 commits
Commits
Show all changes
141 commits
Select commit Hold shift + click to select a range
9e41309
added external-db-sync
aadesh18 Nov 30, 2025
3879001
stopped using yupArray
aadesh18 Nov 30, 2025
937db90
fixed build errors
aadesh18 Nov 30, 2025
3f2a8ef
Revert "fixed build errors"
aadesh18 Nov 30, 2025
dcda402
Update apps/backend/scripts/run-cron-jobs.ts
aadesh18 Dec 1, 2025
9e954b9
Update apps/backend/src/app/api/latest/internal/external-db-sync/poll…
aadesh18 Dec 1, 2025
f0cc311
Update apps/backend/src/app/api/latest/internal/external-db-sync/poll…
aadesh18 Dec 1, 2025
1d7a0de
pr changes
aadesh18 Dec 2, 2025
8c2d1c3
merge dev
BilalG1 Jan 28, 2026
409d89b
Merge remote-tracking branch 'origin/dev' into external-db-sync
BilalG1 Jan 29, 2026
0d2b3b9
fix pnpm lock
BilalG1 Jan 29, 2026
ef8f74e
fix typecheck
BilalG1 Jan 29, 2026
8cdd107
prisma fix
BilalG1 Jan 29, 2026
871fe12
fix tests
BilalG1 Jan 29, 2026
5d6bde2
fix lint
BilalG1 Jan 29, 2026
c4ed09a
fix
BilalG1 Jan 29, 2026
b102db3
fix tests
BilalG1 Jan 29, 2026
2eeb537
fix tests
BilalG1 Jan 29, 2026
c61a2b9
fix test
BilalG1 Jan 30, 2026
ac261d2
increase session test time
BilalG1 Jan 30, 2026
0c1a02e
fix flaky test and external sot sync
BilalG1 Jan 30, 2026
79e330f
comment resolving
BilalG1 Jan 30, 2026
939b1a9
resolve pr comments
BilalG1 Jan 30, 2026
2974c83
retry
BilalG1 Jan 30, 2026
0799a0b
attempt test fixes
BilalG1 Jan 30, 2026
1f67742
fix env
BilalG1 Jan 30, 2026
bd788b4
fix env
BilalG1 Jan 30, 2026
4b7dd53
attempt test fixes
BilalG1 Jan 30, 2026
044377e
fix tests
BilalG1 Jan 30, 2026
744b871
Merge branch 'dev' into external-db-sync
BilalG1 Jan 30, 2026
74c634b
fix lint
BilalG1 Jan 30, 2026
ce5a1bb
fix tests
BilalG1 Jan 30, 2026
2c5440b
fix tests
BilalG1 Jan 30, 2026
f726f61
Merge remote-tracking branch 'origin/dev' into external-db-sync
BilalG1 Jan 31, 2026
665c084
fix tests
BilalG1 Jan 31, 2026
85bb893
Merge branch 'dev' into external-db-sync
BilalG1 Jan 31, 2026
856aaf3
fix tests
BilalG1 Jan 31, 2026
8f3ad45
m
BilalG1 Jan 31, 2026
fe393e9
merge dev
BilalG1 Feb 2, 2026
b9c0ef4
fix lockfile
BilalG1 Feb 2, 2026
b5781a1
Merge remote-tracking branch 'origin/dev' into external-db-sync
BilalG1 Feb 2, 2026
b841f7b
fix tests
BilalG1 Feb 2, 2026
2e0d8de
m
BilalG1 Feb 2, 2026
e5cbc1a
Merge branch 'dev' into external-db-sync
BilalG1 Feb 2, 2026
ba1df26
fix tests
BilalG1 Feb 2, 2026
093eaf0
e2e: isolate external DB sync cleanup per suite (#1148)
BilalG1 Feb 3, 2026
5192875
CI: run dev tests single-worker (#1153)
BilalG1 Feb 3, 2026
686a1e6
Merge branch 'dev' into external-db-sync
BilalG1 Feb 3, 2026
8910138
fixes
BilalG1 Feb 3, 2026
62171dc
single test run
BilalG1 Feb 3, 2026
1038d1a
Merge branch 'dev' into external-db-sync
BilalG1 Feb 3, 2026
3370e63
test fixes (#1155)
BilalG1 Feb 3, 2026
d04e944
concurrent fix
BilalG1 Feb 3, 2026
61f2b79
Merge branch 'external-db-sync' of https://github.com/stack-auth/stac…
BilalG1 Feb 3, 2026
bbac70e
Merge branch 'dev' into external-db-sync
BilalG1 Feb 3, 2026
8e92205
fix routes, external-db dashboard
BilalG1 Feb 4, 2026
3b9c22e
merge dev
BilalG1 Feb 4, 2026
c0a3f7a
replace trigger
BilalG1 Feb 4, 2026
d34a2c7
fusebox
BilalG1 Feb 4, 2026
c91998e
add tracing
BilalG1 Feb 4, 2026
64d9d93
remove old tests
BilalG1 Feb 4, 2026
7fd7886
fix sot test
BilalG1 Feb 4, 2026
719d1c2
Merge remote-tracking branch 'origin/dev' into external-db-sync
BilalG1 Feb 4, 2026
43c1f15
clickhouse user sync
BilalG1 Feb 4, 2026
04970c2
Update vercel.json
N2D4 Feb 4, 2026
4abd410
Various fixes
N2D4 Feb 4, 2026
8247481
test: disable direct external db sync in CI
BilalG1 Feb 5, 2026
362e1fb
merge dev
BilalG1 Feb 5, 2026
98d451d
increase test timeout
BilalG1 Feb 5, 2026
6b89370
cmd k query analytics (#1160)
BilalG1 Feb 5, 2026
ff370b6
Merge branch 'external-db-sync' into external-db-sync-clickhouse-default
BilalG1 Feb 5, 2026
8be639d
Merge branch 'dev' into external-db-sync
BilalG1 Feb 5, 2026
caa3dca
remove fusebox sync engine col
BilalG1 Feb 5, 2026
445e889
Merge branch 'external-db-sync' of https://github.com/stack-auth/stac…
BilalG1 Feb 5, 2026
63df87a
fix test
BilalG1 Feb 5, 2026
9c340f4
Merge branch 'external-db-sync' into external-db-sync-clickhouse-default
BilalG1 Feb 5, 2026
45e7d2d
merge dev
BilalG1 Feb 5, 2026
925a865
fix zod version
BilalG1 Feb 5, 2026
b83063c
move test
BilalG1 Feb 5, 2026
b673ab5
fix lint
BilalG1 Feb 5, 2026
fcf493e
Merge branch 'dev' into external-db-sync-clickhouse-default
BilalG1 Feb 6, 2026
8534caa
Merge branch 'dev' into external-db-sync-clickhouse-default
BilalG1 Feb 9, 2026
2f7acb4
Add STACK_OPENAI_API_KEY to .env.development
N2D4 Feb 10, 2026
cf5558e
pr comment fixes
BilalG1 Feb 12, 2026
4ab4be8
merge dev
BilalG1 Feb 12, 2026
1421461
Add TEST_TIMEOUT to ClickHouse sync tests
BilalG1 Feb 12, 2026
90eb9ae
Merge branch 'dev' into external-db-sync-clickhouse-default
BilalG1 Feb 12, 2026
afa76be
token refresh event change (#1162)
BilalG1 Feb 12, 2026
a509be3
fix type issue
BilalG1 Feb 12, 2026
02b6ef6
Merge branch 'dev' into external-db-sync-clickhouse-default
BilalG1 Feb 12, 2026
62d054e
fix tests
BilalG1 Feb 12, 2026
558d0f6
Merge branch 'external-db-sync-clickhouse-default' of https://github.…
BilalG1 Feb 12, 2026
0dc2e94
fix clickhouse needsResync
BilalG1 Feb 12, 2026
3db832e
Increase ClickHouse poll interval from 500ms to 2s
BilalG1 Feb 12, 2026
3cde6fa
fix test ordering
BilalG1 Feb 13, 2026
a2033bc
added ai custom dashboards
aadesh18 Feb 12, 2026
b01d17b
Update apps/dashboard/src/components/commands/create-dashboard/dashbo…
aadesh18 Feb 12, 2026
0fcc37c
Update apps/dashboard/src/components/commands/create-dashboard/dashbo…
aadesh18 Feb 12, 2026
7c6173e
Update apps/dashboard/src/components/commands/create-dashboard/dashbo…
aadesh18 Feb 12, 2026
416051f
Update apps/dashboard/src/components/commands/create-dashboard/create…
aadesh18 Feb 12, 2026
8cff361
added greptile suggestion
aadesh18 Feb 12, 2026
e107078
fixed conflict
aadesh18 Feb 12, 2026
5accb8b
updated imports
aadesh18 Feb 12, 2026
c52bdd1
Merge commit 'd09a180dfe800a471ca1fb8ea101fd0cdeef0d4d' into custom-d…
N2D4 Feb 17, 2026
ad6eb03
Merge branch 'custom-dashboards-last-from-bilal-2' into custom-dashbo…
N2D4 Feb 17, 2026
579c723
Update apps/dashboard/scripts/bundle-type-definitions.ts
aadesh18 Feb 17, 2026
59f6998
Update apps/dashboard/src/app/api/create-dashboard/route.ts
aadesh18 Feb 17, 2026
4799b34
Update apps/dashboard/src/lib/ai-dashboard/contracts.ts
aadesh18 Feb 17, 2026
bb94e48
Apply suggestion from @N2D4
aadesh18 Feb 17, 2026
3dac1cd
Apply suggestion from @N2D4
aadesh18 Feb 17, 2026
805a78f
Apply suggestion from @N2D4
aadesh18 Feb 17, 2026
e89989e
Apply suggestion from @N2D4
aadesh18 Feb 17, 2026
183ce10
Apply suggestion from @N2D4
aadesh18 Feb 17, 2026
593cb26
dynamic esm versioning
aadesh18 Feb 17, 2026
7c96c52
changes based on the pr review
aadesh18 Feb 17, 2026
64cc8ab
minor bug fix
aadesh18 Feb 17, 2026
4309859
bug fixes
aadesh18 Feb 18, 2026
00c01b3
pnpm lock
aadesh18 Feb 18, 2026
f764f50
Merge remote-tracking branch 'origin/dev' into custom-dashboards
aadesh18 Feb 18, 2026
aaeab15
removed temp file
aadesh18 Feb 18, 2026
44f4303
saving dashboards + dashboard package
aadesh18 Feb 21, 2026
fc45436
bug fixes
aadesh18 Feb 23, 2026
90701e8
Merge branch 'unified-ai-endpoint' into custom-dashboards
aadesh18 Feb 23, 2026
5acb916
using unified ai endpoint for custom dashboards as well
aadesh18 Feb 23, 2026
91c6bcb
bug fixes
aadesh18 Feb 24, 2026
56c4951
Merge remote-tracking branch 'origin/unified-ai-endpoint' into custom…
aadesh18 Feb 24, 2026
66ba625
using unified endpoint
aadesh18 Feb 24, 2026
0b895f9
removed local testing
aadesh18 Feb 24, 2026
261feaf
minor changes
aadesh18 Feb 24, 2026
c031124
more changes
aadesh18 Feb 24, 2026
3fa91d5
minor bug fix
aadesh18 Feb 24, 2026
bcb2534
pnpm changes
aadesh18 Feb 24, 2026
fad9ef4
Merge remote-tracking branch 'origin/unified-ai-endpoint' into custom…
aadesh18 Feb 25, 2026
b92a8e9
merge changes
aadesh18 Feb 25, 2026
b412b68
ui changes
aadesh18 Feb 25, 2026
93f7984
fixed bug
aadesh18 Feb 25, 2026
33d9e44
unused file
aadesh18 Feb 25, 2026
a7aa24c
refactoring changes
aadesh18 Feb 25, 2026
6d39d36
Fix casing of allowTransparency attribute
aadesh18 Feb 25, 2026
d866df4
Type cast dashboard variable for better type safety
aadesh18 Feb 25, 2026
e418165
Update allowTransparency prop to use boolean syntax
aadesh18 Feb 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apps/dashboard/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

# Generated files
src/generated
6 changes: 5 additions & 1 deletion apps/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@
"repository": "https://github.com/stack-auth/stack-auth",
"private": true,
"scripts": {
"clean": "rimraf .next && rimraf node_modules",
"clean": "rimraf .next && rimraf node_modules && rimraf src/generated",
"typecheck": "tsc --noEmit",
"with-env": "dotenv -c development --",
"with-env:prod": "dotenv -c --",
"dev": "next dev --turbopack --port ${NEXT_PUBLIC_STACK_PORT_PREFIX:-81}01",
"predev": "pnpm run bundle-type-definitions",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of predev, let's use concurrently with a watch mode (see the backend package.json for some examples)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i removed the predev hook and switched to the same concurrently + watch pattern used in the backend

"bundle-type-definitions": "tsx scripts/bundle-type-definitions.ts",
"prebuild": "pnpm run bundle-type-definitions",
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The predev and prebuild scripts run bundle-type-definitions on every dev start and build. This could significantly slow down the development workflow if the bundled file is large. Consider:

  1. Using a watch mode or file system watcher to only regenerate when source files change
  2. Adding caching to skip regeneration if source files haven't changed
  3. Moving this to a postinstall script instead of running it on every dev/build

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can just put this into build itself (it's part of the build process)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep okay

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fyi, these three will probably move to the backend as soon as the unified AI endpoint lands (no hurry for now tho)

"build": "next build",
"docker-build": "next build --experimental-build-mode compile",
"analyze-bundle": "next experimental-analyze",
Expand All @@ -17,6 +20,7 @@
"lint": "eslint ."
},
"dependencies": {
"@ai-sdk/anthropic": "^3.0.41",
"@ai-sdk/openai": "^3.0.25",
"@ai-sdk/react": "^3.0.72",
"@assistant-ui/react": "^0.10.24",
Expand Down
64 changes: 64 additions & 0 deletions apps/dashboard/scripts/bundle-type-definitions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { writeFileSyncIfChanged } from '@stackframe/stack-shared/dist/utils/fs';
import { glob } from 'glob';
import * as fs from 'node:fs/promises';
import * as path from 'node:path';

type TypeDefinitionFile = {
path: string,
content: string,
};

async function main() {
console.log('[Bundle Type Definitions] Finding Stack SDK type definition files...');

const rootPath = path.resolve(process.cwd(), '../..');
const stackAppPath = path.join(rootPath, 'packages/template/src/lib/stack-app');
const outputPath = path.join(rootPath, 'apps/dashboard/src/generated/bundled-type-definitions.ts');

const files = await glob(`${stackAppPath}/**/*.ts`, {
ignore: [
`${stackAppPath}/**/implementations/**`,
`${stackAppPath}/**/utils/**`,
`${stackAppPath}/**/*.d.ts`,
`${stackAppPath}/**/global.css`,
],
});

console.log(`[Bundle Type Definitions] Found ${files.length} type definition files`);

const bundledFiles: TypeDefinitionFile[] = [];

for (const filePath of files) {
const relativePath = path.relative(stackAppPath, filePath);
const content = await fs.readFile(filePath, 'utf8');

bundledFiles.push({
path: relativePath,
content,
});
}

console.log('[Bundle Type Definitions] Generating bundled-type-definitions.ts...');

const output = `// This file is auto-generated by scripts/bundle-type-definitions.ts
// Do not edit manually - changes will be overwritten

export type TypeDefinitionFile = {
path: string,
content: string,
};

export const BUNDLED_TYPE_DEFINITIONS: TypeDefinitionFile[] = ${JSON.stringify(bundledFiles, null, 2)};
Comment thread
coderabbitai[bot] marked this conversation as resolved.
`;

await fs.mkdir(path.dirname(outputPath), { recursive: true });
writeFileSyncIfChanged(outputPath, output);
Comment thread
aadesh18 marked this conversation as resolved.

console.log(`[Bundle Type Definitions] Generated ${outputPath}`);
console.log(`[Bundle Type Definitions] Total size: ${(output.length / 1024).toFixed(2)} KB, ${bundledFiles.length} files bundled`);
Comment thread
aadesh18 marked this conversation as resolved.
}

main().catch((...args) => {
console.error('[Bundle Type Definitions] ERROR! Failed to bundle type definitions:', ...args);
process.exit(1);
});
28 changes: 28 additions & 0 deletions apps/dashboard/src/app/api/create-dashboard/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { generateDashboardRuntimeCodegen } from "@/lib/ai-dashboard/model";
import { stackServerApp } from "@/stack";
import { throwErr } from "@stackframe/stack-shared/dist/utils/errors";
import { yupObject, yupString } from "@stackframe/stack-shared/dist/schema-fields";

const requestSchema = yupObject({
projectId: yupString().defined().nonEmpty(),
prompt: yupString().defined().nonEmpty(),
}).defined();

export async function POST(req: Request) {
Comment thread
aadesh18 marked this conversation as resolved.
Outdated
const user = await stackServerApp.getUser({ or: "redirect" });
const payload = await requestSchema.validate(await req.json());
Comment thread
aadesh18 marked this conversation as resolved.
Outdated

const projects = await user.listOwnedProjects();
const project = projects.find((p: { id: string }) => p.id === payload.projectId);
if (!project) {
return Response.json({ error: "You do not own this project" }, { status: 403 });
}

const runtimeCodegen = await generateDashboardRuntimeCodegen(payload.prompt);

return Response.json({
prompt: payload.prompt,
projectId: payload.projectId,
runtimeCodegen,
});
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The route lacks proper error handling. If generateDashboardRuntimeCodegen() fails (e.g., due to LLM API errors, timeout, or invalid output), the error will propagate as a generic 500 error without useful context for the user. Consider wrapping the LLM call in try-catch and returning appropriate error responses with helpful messages.

Suggested change
const runtimeCodegen = await generateDashboardRuntimeCodegen(payload.prompt);
return Response.json({
prompt: payload.prompt,
projectId: payload.projectId,
runtimeCodegen,
});
try {
const runtimeCodegen = await generateDashboardRuntimeCodegen(payload.prompt);
return Response.json({
prompt: payload.prompt,
projectId: payload.projectId,
runtimeCodegen,
});
} catch (error: unknown) {
// Log the error for server-side diagnostics
console.error("Failed to generate dashboard runtime codegen:", error);
const message =
error && typeof error === "object" && "message" in error
? String((error as { message?: unknown }).message ?? "Failed to generate dashboard runtime codegen.")
: "Failed to generate dashboard runtime codegen.";
return Response.json(
{ error: message },
{ status: 502 },
);
}

Copilot uses AI. Check for mistakes.
}
33 changes: 1 addition & 32 deletions apps/dashboard/src/components/cmdk-commands.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { runAsynchronouslyWithAlert } from "@stackframe/stack-shared/dist/utils/
import Image from "next/image";
import React, { memo, useEffect, useMemo } from "react";
import { AIChatPreview } from "./commands/ask-ai";
import { CreateDashboardPreview } from "./commands/create-dashboard/create-dashboard-preview";
import { RunQueryPreview } from "./commands/run-query";

export type CmdKPreviewProps = {
Expand All @@ -31,38 +32,6 @@ export type CmdKPreviewProps = {
pathname: string,
};

// Create Dashboard Preview Component - shows a TODO message for now
const CreateDashboardPreview = memo(function CreateDashboardPreview({
query,
}: CmdKPreviewProps) {
return (
<div className="flex flex-col h-full w-full items-center justify-center p-6">
<div className="flex flex-col items-center gap-4 max-w-md text-center">
<div className="w-16 h-16 rounded-2xl bg-cyan-500/10 flex items-center justify-center">
<LayoutIcon className="h-8 w-8 text-cyan-500" />
</div>
<div>
<h3 className="text-lg font-semibold text-foreground mb-2">Create Dashboard</h3>
<p className="text-sm text-muted-foreground mb-4">
Generate custom dashboards for your users.
</p>
</div>
<div className="w-full p-4 rounded-xl bg-cyan-500/5 border border-cyan-500/20">
<p className="text-xs text-cyan-600 dark:text-cyan-400 font-medium mb-2">Your query:</p>
<p className="text-sm text-foreground italic">&ldquo;{query}&rdquo;</p>
</div>
<div className="mt-4 p-4 rounded-xl bg-muted/50 border border-border">
<p className="text-xs text-muted-foreground">
🚧 <span className="font-medium">Coming Soon</span> — This feature is under development.
Soon you&apos;ll be able to create custom dashboards like &ldquo;analytics overview&rdquo;,
&ldquo;user management panel&rdquo;, or &ldquo;team activity feed&rdquo;.
</p>
</div>
</div>
</div>
);
});

// Available App Preview Component - shows app store page in preview panel
const AvailableAppPreview = memo(function AvailableAppPreview({
appId,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
"use client";

import { useProjectId } from "@/app/(main)/(protected)/projects/[projectId]/use-admin-app";
import { Button } from "@/components/ui";
import { useDebouncedAction } from "@/hooks/use-debounced-action";
import {
CreateDashboardResponse,
CreateDashboardResponseSchema,
} from "@/lib/ai-dashboard/contracts";
import { cn } from "@/lib/utils";
import { runAsynchronouslyWithAlert } from "@stackframe/stack-shared/dist/utils/promises";
import { memo, useCallback, useState } from "react";
import { CmdKPreviewProps } from "../../cmdk-commands";
import { DashboardSandboxHost } from "./dashboard-sandbox-host";

type GenerationState = "idle" | "generating" | "ready" | "error";

export function CreateDashboardPreview({ query, ...rest }: CmdKPreviewProps) {
return <CreateDashboardPreviewInner key={query} query={query} {...rest} />;
}

const CreateDashboardPreviewInner = memo(function CreateDashboardPreviewInner({
query,
}: CmdKPreviewProps) {
const projectId = useProjectId();
const prompt = query.trim();

const [state, setState] = useState<GenerationState>("idle");
const [errorText, setErrorText] = useState<string | null>(null);
const [artifact, setArtifact] = useState<CreateDashboardResponse | null>(null);

const generateDashboard = useCallback(async () => {
if (!projectId || !prompt) {
return;
}
setState("generating");
setErrorText(null);
setArtifact(null);

const response = await fetch("/api/create-dashboard", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
projectId,
prompt,
}),
});
if (!response.ok) {
const responseText = await response.text();
setState("error");
setErrorText(responseText || `Request failed with status ${response.status}`);
return;
}

const json = await response.json();
const parsed = CreateDashboardResponseSchema.safeParse(json);
if (!parsed.success) {
setState("error");
setErrorText(`Failed to parse generation response: ${parsed.error.issues[0]?.message ?? "Unknown error"}`);
return;
}
setArtifact(parsed.data);
setState("ready");
}, [projectId, prompt]);
Comment thread
aadesh18 marked this conversation as resolved.
Outdated

useDebouncedAction({
action: generateDashboard,
delayMs: 500,
skip: !projectId || !prompt,
});

if (!prompt) {
return (
<div className="flex flex-col h-full w-full items-center justify-center p-6 text-center">
<h3 className="text-base font-semibold text-foreground">Create Dashboard</h3>
<p className="text-xs text-muted-foreground mt-1">Describe the dashboard you want and we will generate it in a sandbox.</p>
</div>
);
}

return (
<div className="flex h-full w-full flex-col">
<div className="px-3 py-2 border-b border-foreground/[0.08] space-y-2">
<div className="flex items-center justify-between gap-3">
<div>
<div className="text-[12px] font-medium text-foreground">Create Dashboard</div>
<div className="text-[10px] text-muted-foreground truncate">{prompt}</div>
</div>
<Button
size="sm"
variant="secondary"
Comment thread
vercel[bot] marked this conversation as resolved.
Outdated
disabled={state === "generating"}
onClick={() => runAsynchronouslyWithAlert(generateDashboard())}
>
{state === "generating" ? "Generating..." : "Regenerate"}
</Button>
</div>
{state === "error" && errorText && (
<div className={cn("rounded-md border px-2 py-1.5 text-[10px]", "border-red-500/30 bg-red-500/10 text-red-200")}>
{errorText}
</div>
)}
Comment thread
aadesh18 marked this conversation as resolved.
</div>

<div className="flex-1 min-h-0 p-2">
{state === "generating" && (
<div className="flex h-full items-center justify-center text-xs text-muted-foreground">Generating dashboard...</div>
)}
{state !== "generating" && artifact && (
<DashboardSandboxHost artifact={artifact} />
)}
{state !== "generating" && !artifact && state !== "error" && (
<div className="flex h-full items-center justify-center text-xs text-muted-foreground">Waiting for generation...</div>
)}
</div>
</div>
);
});
Loading
Loading