From 9c438fa60418ed890b9455527ce801ac2a637737 Mon Sep 17 00:00:00 2001 From: Konstantin Wohlwend Date: Fri, 26 Jun 2026 18:48:33 -0700 Subject: [PATCH] Update RDE project keys --- .../[projectId]/(overview)/setup-page.tsx | 104 ++++++++++++++++-- .../[projectId]/project-keys/page-client.tsx | 74 ++++++++++++- 2 files changed, 165 insertions(+), 13 deletions(-) diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/setup-page.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/setup-page.tsx index b618fc3e9..eb7676ade 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/setup-page.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/setup-page.tsx @@ -73,12 +73,50 @@ function buildCloudSetupPrompt(options: { `; } +function buildCliDevSetupPrompt(options: { + docsBaseUrl: string, +}) { + const { docsBaseUrl } = options; + const normalizedDocsBaseUrl = docsBaseUrl.replace(/\/$/, ''); + const reminders = remindersPrompt.replaceAll(PROD_DOCS_BASE_URL, normalizedDocsBaseUrl); + + return deindent` + Install and set up Hexclave in this project by following these instructions: + + Read https://skill.hexclave.com and follow the setup instructions it gives for this project's specific framework and language. + + Follow skill.hexclave.com as written, but use the local dashboard / Hexclave CLI development setup. Do not use the cloud environment-variable setup for local development. + + Set up the app's dev command so Hexclave starts through the CLI: + + \`\`\`json + { + "scripts": { + "dev": "hexclave dev --config-file ./hexclave.config.ts -- npm run dev:inner", + "dev:inner": "" + } + } + \`\`\` + + If the Hexclave CLI is not installed globally, use \`npx @hexclave/cli dev --config-file ./hexclave.config.ts -- npm run dev:inner\` instead. + + Do not create Hexclave project keys or ask for Hexclave environment variables for local development. The \`hexclave dev\` command automatically creates or links the local config project and injects the project ID and secret server key into the child app process. + + Keep project configuration in \`hexclave.config.ts\`. Once setup is done, run \`npm run dev\` and create the first user in the app. + + After setup finishes, verify that the Hexclave MCP server is registered in your AI client config — name: \`hexclave\`, transport: \`http\`, URL: \`https://mcp.hexclave.com/mcp\`. If it is not registered, add it manually so future agents have live access to Hexclave docs and APIs. + + ${reminders} + `; +} + export default function SetupPage(props: { toMetrics: () => void }) { const adminApp = useAdminApp(); const [setupMode, setSetupMode] = useState("recommended"); const [keys, setKeys] = useState<{ projectId: string, publishableClientKey?: string, secretServerKey: string } | null>(null); const projectConfig = adminApp.useProject().useConfig(); const requirePublishableClientKey = projectConfig.project.requirePublishableClientKey; + const isRemoteDevelopmentEnvironment = getPublicEnvVar("NEXT_PUBLIC_STACK_IS_REMOTE_DEVELOPMENT_ENVIRONMENT") === "true"; const onGenerateKeys = async () => { const newKey = await adminApp.createInternalApiKey({ @@ -96,11 +134,16 @@ export default function SetupPage(props: { toMetrics: () => void }) { }); }; - const selectedInstallPrompt = buildCloudSetupPrompt({ - docsBaseUrl: getSetupDocsBaseUrl(), - projectId: adminApp.projectId, - apiBaseUrl: getSetupApiBaseUrl(), - }); + const setupDocsBaseUrl = getSetupDocsBaseUrl(); + const selectedInstallPrompt = isRemoteDevelopmentEnvironment + ? buildCliDevSetupPrompt({ + docsBaseUrl: setupDocsBaseUrl, + }) + : buildCloudSetupPrompt({ + docsBaseUrl: setupDocsBaseUrl, + projectId: adminApp.projectId, + apiBaseUrl: getSetupApiBaseUrl(), + }); const manualSetupDocsUrl = getManualSetupDocsUrl(); return ( @@ -130,13 +173,18 @@ export default function SetupPage(props: { toMetrics: () => void }) { variant='outline' size='sm' onClick={() => { - window.open(getSetupDocsBaseUrl(), '_blank'); + window.open(setupDocsBaseUrl, '_blank'); }} > Full Documentation + {isRemoteDevelopmentEnvironment && ( + + For local config projects, run your app with hexclave dev. It injects the project ID and secret key automatically, so you do not need to create project keys or write Hexclave environment variables. + + )} @@ -152,7 +200,31 @@ export default function SetupPage(props: { toMetrics: () => void }) { {setupMode === "recommended" ? (
    - {[ + {(isRemoteDevelopmentEnvironment ? [ + { + step: 1, + title: "Copy Setup Prompt", + content:
    + + {selectedInstallPrompt} + + } + title="Prompt for your AI agent" + icon="code" + maxHeight={480} + /> +
    , + }, + { + step: 2, + title: "Done", + content: , + }, + ] : [ { step: 1, title: "Copy Setup Prompt", @@ -186,7 +258,7 @@ export default function SetupPage(props: { toMetrics: () => void }) { title: "Done", content: , }, - ].map((item) => ( + ]).map((item) => (
  1. @@ -310,6 +382,22 @@ function SetupRecommendedDoneStep(props: { onExploreDashboard: () => void }) { ); } +function CliDevSetupStep() { + return ( +
    + + Start the app through the Hexclave CLI instead of copying project keys into an env file. + +
    + hexclave dev --config-file ./hexclave.config.ts -- <your-dev-command> +
    + + The CLI creates or links the local config project and injects the project ID and secret server key into the child process automatically. Use npx @hexclave/cli dev if the CLI is not installed globally. + +
    + ); +} + function HexclaveKeys(props: { keys: { projectId: string, publishableClientKey?: string, secretServerKey: string } | null, onGenerateKeys: () => Promise, diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-keys/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-keys/page-client.tsx index bccc0d1b6..79df4d7ce 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-keys/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-keys/page-client.tsx @@ -1,11 +1,13 @@ "use client"; import { InternalApiKeyTable } from "@/components/data-table/api-key-table"; -import { DesignAlert, DesignButton } from "@/components/design-components"; +import { DesignAlert, DesignButton, DesignCard } from "@/components/design-components"; import { EnvKeys } from "@/components/env-keys"; import { SmartFormDialog } from "@/components/form-dialog"; import { SelectField } from "@/components/form-fields"; +import { InlineCode } from "@/components/inline-code"; import { SettingSwitch } from "@/components/settings"; -import { ActionDialog, Button, Typography } from "@/components/ui"; +import { ActionDialog, Typography } from "@/components/ui"; +import { getPublicEnvVar } from "@/lib/env"; import { InternalApiKeyFirstView } from "@hexclave/next"; import { useSearchParams } from "next/navigation"; import { useState } from "react"; @@ -15,15 +17,32 @@ import { useAdminApp } from "../use-admin-app"; export default function PageClient() { + const hexclaveAdminApp = useAdminApp(); + const project = hexclaveAdminApp.useProject(); + const params = useSearchParams(); + const create = params.get("create") === "true"; + const isRemoteDevelopmentEnvironment = getPublicEnvVar("NEXT_PUBLIC_STACK_IS_REMOTE_DEVELOPMENT_ENVIRONMENT") === "true"; + const showLocalConfigInstructions = isRemoteDevelopmentEnvironment && project.isDevelopmentEnvironment; + + if (showLocalConfigInstructions) { + return ( + + + + ); + } + + return ; +} + +function ProjectKeysManagement(props: { create: boolean }) { const hexclaveAdminApp = useAdminApp(); const project = hexclaveAdminApp.useProject(); const config = project.useConfig(); const requirePublishableClientKey = config.project.requirePublishableClientKey; const apiKeySets = hexclaveAdminApp.useInternalApiKeys(); - const params = useSearchParams(); - const create = params.get("create") === "true"; - const [isNewApiKeyDialogOpen, setIsNewApiKeyDialogOpen] = useState(create); + const [isNewApiKeyDialogOpen, setIsNewApiKeyDialogOpen] = useState(props.create); const [returnedApiKey, setReturnedApiKey] = useState(null); return ( @@ -66,6 +85,51 @@ export default function PageClient() { ); } +function LocalConfigProjectKeysInstructions() { + const hexclaveAdminApp = useAdminApp(); + const project = hexclaveAdminApp.useProject(); + const config = project.useConfig(); + const requirePublishableClientKey = config.project.requirePublishableClientKey; + + return ( + <> + + + +
    + + Run your app through the CLI so Hexclave can keep hexclave.config.ts and your app environment in sync: + +
    + npx @hexclave/cli dev --config-file <path-to-hexclave.config.ts> -- <your-dev-command> +
    + + This will automatically provide the correct environment variables to the specified command. + + + If you have the CLI installed globally, the same command starts with hexclave dev. Keep project settings in the config file; the CLI provides the runtime keys automatically. + +
    +
    + + { + await project.update({ + requirePublishableClientKey: checked, + }); + }} + /> + + ); +} + const neverInMs = 1000 * 60 * 60 * 24 * 365 * 200; const expiresInOptions = { [1000 * 60 * 60 * 24 * 1]: "1 day",