From 09a9686878298d2430b2e96ba14e6557f43b4b63 Mon Sep 17 00:00:00 2001 From: Konstantin Wohlwend Date: Tue, 28 Oct 2025 00:03:48 -0700 Subject: [PATCH] Move Project Keys into sidebar --- AGENTS.md | 2 + .../[projectId]/api-keys-app/page-client.tsx | 52 +++++++++++++++++++ .../[projectId]/api-keys-app/page.tsx | 11 ++++ .../projects/[projectId]/api-keys/page.tsx | 18 +++---- .../page-client.tsx | 46 ++++++++-------- .../[projectId]/project-keys/page.tsx | 11 ++++ .../projects/[projectId]/sidebar-layout.tsx | 7 +++ apps/dashboard/src/lib/apps-frontend.tsx | 2 +- 8 files changed, 115 insertions(+), 34 deletions(-) create mode 100644 apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys-app/page-client.tsx create mode 100644 apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys-app/page.tsx rename apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/{api-keys => project-keys}/page-client.tsx (82%) create mode 100644 apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-keys/page.tsx diff --git a/AGENTS.md b/AGENTS.md index ec46954fd..6b875247b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -77,6 +77,8 @@ To see all development ports, refer to the index.html of `apps/dev-launchpad/pub - Whenever you learn something new, or at the latest right before you call the `Stop` tool, write whatever you learned into the ./claude/CLAUDE-KNOWLEDGE.md file, in the Q&A format in there. You will later be able to look up knowledge from there (based on the question you asked). - Animations: Keep hover/click transitions snappy and fast. Don't delay the action with a pre-transition (e.g. no fade-in when hovering a button) — it makes the UI feel sluggish. Instead, apply transitions after the action, like a smooth fade-out when the hover ends. - Whenever you make changes in the dashboard, provide the user with a deep link to the dashboard page that you've just changed. Usually, this takes the form of `http://localhost:01/projects/-selector-/...`, although sometimes it's different. If $NEXT_PUBLIC_STACK_PORT_PREFIX is set to 91, 92, or 93, use `a.localhost`, `b.localhost`, and `c.localhost` for the domains, respectively. +- To update the list of apps available, edit `apps-frontend.tsx` and `apps-config.tsx`. When you're tasked to implement a new app or a new page, always check existing apps for inspiration on how you could implement the new app or page. +- NEVER use Next.js dynamic functions if you can avoid them. Instead, prefer using a client component to make sure the page remains static (eg. prefer `usePathname` instead of `await params`). ### Code-related - Use ES6 maps instead of records wherever you can. diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys-app/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys-app/page-client.tsx new file mode 100644 index 000000000..457d9e6f3 --- /dev/null +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys-app/page-client.tsx @@ -0,0 +1,52 @@ +"use client"; +import { SettingCard, SettingSwitch } from "@/components/settings"; +import { Typography } from "@stackframe/stack-ui"; +import { AppEnabledGuard } from "../app-enabled-guard"; +import { PageLayout } from "../page-layout"; +import { useAdminApp } from "../use-admin-app"; + +export default function PageClient() { + const stackAdminApp = useAdminApp(); + const project = stackAdminApp.useProject(); + + return ( + + + + { + await project.update({ + config: { + allowUserApiKeys: checked + } + }); + }} + /> + + Enable to allow users to create API keys for their accounts. Enables user-api-keys backend routes. + + + { + await project.update({ + config: { + allowTeamApiKeys: checked + } + }); + }} + /> + + Enable to allow users to create API keys for their teams. Enables team-api-keys backend routes. + + + + + ); +} diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys-app/page.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys-app/page.tsx new file mode 100644 index 000000000..f8b59f27c --- /dev/null +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys-app/page.tsx @@ -0,0 +1,11 @@ +import PageClient from "./page-client"; + +export const metadata = { + title: "API Keys", +}; + +export default function Page() { + return ( + + ); +} diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys/page.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys/page.tsx index f8b59f27c..96c4f739d 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys/page.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys/page.tsx @@ -1,11 +1,11 @@ -import PageClient from "./page-client"; +// This page used to be the location of Project Keys before it was moved to /project-keys +// Redirecting to the new location +import { redirect } from 'next/navigation'; -export const metadata = { - title: "API Keys", -}; - -export default function Page() { - return ( - - ); +export default function Page({ + params, +}: { + params: { projectId: string }, +}) { + redirect(`/projects/${params.projectId}/project-keys`); } diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-keys/page-client.tsx similarity index 82% rename from apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys/page-client.tsx rename to apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-keys/page-client.tsx index 127208378..a0e23bd80 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/api-keys/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-keys/page-client.tsx @@ -23,29 +23,27 @@ export default function PageClient() { const [returnedApiKey, setReturnedApiKey] = useState(null); return ( - - setIsNewApiKeyDialogOpen(true)}> - Create Stack Auth Keys - - } - > - + setIsNewApiKeyDialogOpen(true)}> + Create Project Keys + + } + > + - - setReturnedApiKey(null)} - /> + + setReturnedApiKey(null)} + /> - - + ); } @@ -80,7 +78,7 @@ function CreateDialog(props: { return { @@ -110,7 +108,7 @@ function ShowKeyDialog(props: { return (
- Here are your Stack Auth keys.{" "} + Here are your project keys.{" "} Copy them to a safe place. You will not be able to view them again. diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-keys/page.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-keys/page.tsx new file mode 100644 index 000000000..505202a85 --- /dev/null +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-keys/page.tsx @@ -0,0 +1,11 @@ +import PageClient from "./page-client"; + +export const metadata = { + title: "Project Keys", +}; + +export default function Page() { + return ( + + ); +} diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsx index caea6921c..ddba3c141 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sidebar-layout.tsx @@ -28,6 +28,7 @@ import { ChevronDown, ChevronRight, Globe, + KeyRound, LucideIcon, Menu, Settings, @@ -79,6 +80,12 @@ const bottomItems: BottomItem[] = [ icon: Blocks, regex: /^\/projects\/[^\/]+\/apps(\/.*)?$/, }, + { + name: 'Project Keys', + href: '/project-keys', + icon: KeyRound, + regex: /^\/projects\/[^\/]+\/project-keys(\/.*)?$/, + }, { name: 'Project Settings', href: '/project-settings', diff --git a/apps/dashboard/src/lib/apps-frontend.tsx b/apps/dashboard/src/lib/apps-frontend.tsx index 9277fb302..0ceedf2a2 100644 --- a/apps/dashboard/src/lib/apps-frontend.tsx +++ b/apps/dashboard/src/lib/apps-frontend.tsx @@ -97,7 +97,7 @@ export const ALL_APPS_FRONTEND = { }, "api-keys": { icon: KeyRound, - href: "api-keys", + href: "api-keys-app", navigationItems: [ { displayName: "API Keys", href: "." }, ],