From c4e6b4a68bdd5e212a1f7deb12094df2704154e7 Mon Sep 17 00:00:00 2001 From: Madison Date: Thu, 4 Jun 2026 14:40:12 -0500 Subject: [PATCH] Adding dashboard jsdoc to page-clients --- .../analytics/queries/page-client.tsx | 15 +++++ .../analytics/tables/page-client.tsx | 15 +++++ .../[projectId]/api-keys-app/page-client.tsx | 24 ++++--- .../[projectId]/auth-methods/page-client.tsx | 36 ++++++++++ .../[projectId]/conversations/page-client.tsx | 15 +++++ .../projects/[projectId]/convex/page.tsx | 13 ++++ .../data-vault/stores/page-client.tsx | 33 ++++++++++ .../[projectId]/email-drafts/page-client.tsx | 16 +++++ .../[projectId]/email-sent/page-client.tsx | 18 +++++ .../email-settings/page-client.tsx | 19 ++++++ .../email-templates/page-client.tsx | 15 +++++ .../launch-checklist/page-client.tsx | 40 ++++++++++++ .../[projectId]/onboarding/page-client.tsx | 26 ++++++++ .../payments/customers/page-client.tsx | 20 ++++++ .../payments/payouts/page-client.tsx | 11 ++++ .../payments/product-lines/page-client.tsx | 15 +++++ .../payments/products/page-client.tsx | 22 +++++++ .../payments/settings/page-client.tsx | 14 ++++ .../payments/transactions/page-client.tsx | 11 ++++ .../project-permissions/page-client.tsx | 20 ++++++ .../session-replays/page-client.tsx | 19 ++++++ .../[projectId]/sign-up-rules/page-client.tsx | 27 ++++++++ .../team-permissions/page-client.tsx | 14 ++++ .../[projectId]/team-settings/page-client.tsx | 20 ++++++ .../[projectId]/teams/page-client.tsx | 47 ++++++++++++++ .../[projectId]/vercel/page-client.tsx | 19 ++++++ .../[projectId]/webhooks/page-client.tsx | 36 +++++++++- .../lib/dashboard-reference-nav-only-pages.ts | 65 +++++++++++++++++++ 28 files changed, 634 insertions(+), 11 deletions(-) create mode 100644 apps/dashboard/src/lib/dashboard-reference-nav-only-pages.ts diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/queries/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/queries/page-client.tsx index 90aca7f9b..757fdb60d 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/queries/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/queries/page-client.tsx @@ -835,6 +835,21 @@ function FolderItem({ ); } +/** + * @dashboardReference analytics/queries + * @dashboardReferenceDescription Saved ClickHouse queries and SQL editor. + * + * ## Sidebar + * + * Folder tree of saved queries (`config` analytics query folders). Create/rename/delete folders and queries; drag-free hierarchy with expand/collapse. + * + * ## Editor + * + * SQL textarea, **Run** executes against ClickHouse, results in `VirtualizedFlatTable`. States: empty prompt, loading, no rows, error display. **Save** persists SQL into the selected folder; **Save as** creates a new entry. + * + * Row click opens `RowDetailDialog` for JSON inspection. `AnalyticsEventLimitBanner` at top when limits apply. + */ + export default function PageClient() { return ( diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/page-client.tsx index 0ce61384d..96a2f9441 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/page-client.tsx @@ -224,6 +224,21 @@ function TableContent({ tableId }: { tableId: TableId }) { ); } +/** + * @dashboardReference analytics/tables + * @dashboardReferenceDescription Browse ClickHouse analytics tables with optional AI SQL. + * + * ## Sidebar + * + * Fixed table list (desktop): Events, Users, Contact Channels, Teams, Team Member Profiles, Team Permissions, Team Invitations, Email Outboxes, Project Permissions, Notification Preferences, Refresh Tokens, Connected Accounts. Link to **Queries** for ad-hoc SQL. + * + * ## Table view + * + * Per table: `QueryDataGrid` runs the default `SELECT * FROM default.` with pagination, quick search, sort, export, and refresh. **AI query bar** can replace the query with a natural-language-generated ClickHouse statement (one-shot mode disables default sort/search). + * + * `AnalyticsEventLimitBanner` warns when event ingestion limits apply. + */ + export default function PageClient() { const [selectedTable, setSelectedTable] = useState("events"); 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 index 5bd1f353b..c77cb95dc 100644 --- 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 @@ -16,24 +16,28 @@ import { useAdminApp } from "../use-admin-app"; /** * @dashboardReference api-keys/api-keys - * @dashboardReferenceDescription Configure whether users and teams can create their own API keys. + * @dashboardReferenceDescription Configure whether end users and teams may create their own API keys. * - * The **API Keys** app controls whether your end users may create API keys scoped to their own account or to teams they belong to. + * ## Not project keys * - * ## About this page + * This page does **not** manage Hexclave **project keys** (publishable client key / secret server key for calling the Hexclave API). Use **Project Settings → Project Keys** for that. * - * This page is **not** where you manage Hexclave **project keys** (publishable client keys and secret server keys for calling the Stack API). Use **Project Keys** in project settings for that. + * ## Info alert * - * The info alert at the top links to the public [API Keys guide](https://docs.hexclave.com/docs/apps/api-keys) for SDK integration details. + * Explains the end-user API Keys product and links to the public [API Keys guide](https://docs.hexclave.com/docs/apps/api-keys) for SDK integration (`createApiKey`, validation, UI components). * - * ## API Key Settings + * ## API Key Settings card * - * Two toggles sit in a deferred-save grid (edit, then **Save** or **Discard**): + * Glassmorphic card with a **deferred-save** editable grid — toggle switches, then **Save** or **Discard** (only changed rows highlight). * - * - **User API Keys** — sets `apiKeys.enabled.user`. When enabled, users can create API keys for their accounts and the user-api-keys backend routes are available. - * - **Team API Keys** — sets `apiKeys.enabled.team`. When enabled, users can create API keys for teams they belong to and the team-api-keys backend routes are available. + * | Toggle | Config | Effect | + * | --- | --- | --- | + * | **User API Keys** | `apiKeys.enabled.user` | Users can create keys for their account; enables user-api-keys routes; shows API Keys tab in `` | + * | **Team API Keys** | `apiKeys.enabled.team` | Users with `$manage_api_keys` can create team keys; enables team-api-keys routes; shows API Keys section on team settings | * - * Both can be on at the same time. Turning one off does not delete existing keys; it prevents new key creation through those scopes. + * Both can be enabled together. Disabling a toggle does **not** revoke existing keys — it blocks new creation through that scope. + * + * Tooltips on each row summarize backend route and UI behavior. */ export default function PageClient() { const stackAdminApp = useAdminApp(); diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/auth-methods/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/auth-methods/page-client.tsx index da8d5a618..eec3d9a5a 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/auth-methods/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/auth-methods/page-client.tsx @@ -49,6 +49,42 @@ type OAuthAccountMergeStrategy = 'link_method' | 'raise_error' | 'allow_duplicat const SHARED_TOOLTIP = "Shared keys are automatically created by Stack, but show Stack's logo on the OAuth sign-in page.\n\nYou should replace these before you go into production."; +/** + * @dashboardReference authentication/auth-methods + * @dashboardReferenceDescription Configure sign-in methods, OAuth SSO, sign-up, and account deletion. + * + * Four stacked configuration areas. Most cards use **Save** / **Discard** after local edits. + * + * ## Sign-in methods + SSO (left card, wide) + * + * **Sign-in methods** toggles (`auth.password.allowSignIn`, `auth.otp.allowSignIn`, `auth.passkey.allowSignIn`): + * + * - Email/password authentication + * - Magic link (Email OTP) + * - Passkey + * + * **SSO Providers** list — one row per enabled provider (icon, name). **Shared keys** badge (orange) = dev credentials; replace before production. Row **⋮** menu: **Configure** (client ID/secret, callback URL), **Turn off**. + * + * - **Add SSO providers** — searchable dialog **Add New Auth Method**; pick providers to enable/configure + * - Empty state alert when none enabled + * + * ## Live preview (right card, large screens) + * + * Browser-frame mock of the hosted **sign-in** page reflecting current toggles and enabled providers (non-interactive). + * + * ## Sign-up card + * + * - **Allow new user sign-ups** (`auth.allowSignUp`) — confirm dialogs when enabling/disabling + * - **Require email verification** (`onboarding.requireEmailVerification`) — may preview affected users before enable (same as Onboarding app) + * - **Same-email social login policy** dropdown (`auth.oauth.accountMergeStrategy`): Link accounts / Create new account / Block sign-up + * + * ## User deletion card + * + * - **Allow users to delete their own accounts on the client-side** (`users.allowClientUserDeletion`) — adds delete control to account settings + * + * Production hardening: **Launch Checklist** for domains, custom OAuth keys, email. Guide: [Auth providers](https://docs.hexclave.com/docs/apps/authentication/auth-providers). + */ + // ─── Confirmation dialogs ───────────────────────────────────────────────── function ConfirmSignUpEnabledDialog(props: { diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/conversations/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/conversations/page-client.tsx index 1e930dbee..791668510 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/conversations/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/conversations/page-client.tsx @@ -895,6 +895,21 @@ function SupportComposer(props: { ); } +/** + * @dashboardReference support/conversations + * @dashboardReferenceDescription Support inbox: threads, replies, internal notes, and SLA hints. + * + * ## Inbox (no thread selected) + * + * Search by subject/message/email, **status tabs** (All / Open / Pending / Closed), optional **userId** filter from URL. **New Conversation** picks a user and opens a thread. + * + * ## Thread view + * + * Message timeline (customer vs team), composer for public replies, **internal notes** (team-only). Sidebar/sheet: assignee, priority, status, tags, SLA urgency badge, link to user profile. + * + * URL params: `conversationId` (or legacy `threadId`), `userId`. Refreshes via `listConversations` / `getConversation` API helpers. + */ + export default function PageClient() { const adminApp = useAdminApp(); const currentUser = useUser({ or: "redirect", projectIdMustMatch: "internal" }); diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/convex/page.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/convex/page.tsx index fc5853c99..1c05e9ef2 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/convex/page.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/convex/page.tsx @@ -1,5 +1,18 @@ import { redirect } from "next/navigation"; +/** + * @dashboardReference convex/convex-integration + * @dashboardReferenceDescription Hexclave + Convex integration (dashboard entry redirects to docs). + * + * ## Behavior + * + * Opening **Convex Integration** in the project sidebar immediately redirects to the public [Convex integration guide](https://docs.hexclave.com/guides/integrations/convex/overview). There is no in-dashboard configuration UI on this route. + * + * ## Setup (off-dashboard) + * + * Follow the linked docs to install the Convex component, wire auth, and sync users/teams. Enable the **Convex** app in the app store so the sidebar entry stays available. + */ + export default function Page() { redirect("https://docs.hexclave.com/guides/integrations/convex/overview"); } diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/data-vault/stores/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/data-vault/stores/page-client.tsx index fc82c8645..7dea1535d 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/data-vault/stores/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/data-vault/stores/page-client.tsx @@ -16,6 +16,39 @@ import { AppEnabledGuard } from "../../app-enabled-guard"; import { PageLayout } from "../../page-layout"; import { useAdminApp } from "../../use-admin-app"; +/** + * @dashboardReference data-vault/data-vault + * @dashboardReferenceDescription List and create Data Vault stores. + * + * Encrypted key-value namespaces for secrets your app stores via the SDK. Keys are hashed — you cannot list keys, only get/set by known key. + * + * ## Header + * + * - **Create Store** (page action) — same dialog as empty state CTA + * + * ## Empty state + * + * When no stores: icon, copy, **Create Your First Store** button. + * + * ## Store list + * + * Each **DesignListItemRow**: store ID (title), display name (subtitle). Click row → store detail (`/projects/…/data-vault/stores/[storeId]`). + * + * ## Create Store dialog + * + * - **Store ID** (required) — sanitized live; immutable after create; `dataVault.stores.` in config + * - **Display Name** (optional) — defaults to `Store ` if blank + * - Validation alerts for invalid ID format or duplicate ID + * + * ## Store detail page (separate route) + * + * - **Store ID** with copy button + * - **Display Name** — deferred save grid + * - **Delete Store** — must type store ID to confirm; irreversible + * - Info alert + code sample for `getDataVaultStore`, `getValue` / `setValue` with `STACK_DATA_VAULT_SECRET` / `HEXCLAVE_DATA_VAULT_SECRET` + * + * [Data Vault](https://docs.hexclave.com/docs/apps/data-vault) + */ export default function PageClient() { const stackAdminApp = useAdminApp(); const project = stackAdminApp.useProject(); diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-drafts/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-drafts/page-client.tsx index caef66ec5..9f49b5d51 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-drafts/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-drafts/page-client.tsx @@ -251,6 +251,22 @@ function EmptyState({ ); } +/** + * @dashboardReference emails/drafts + * @dashboardReferenceDescription Compose one-off emails and send them from the dashboard. + * + * ## Sections + * + * - **Active drafts** — cards with open/delete; click opens `email-drafts/[draftId]` editor + * - **History** — drafts that were sent (`sentAt` set); opens editor in read-only **sent** stage + * + * ## Header actions + * + * **New draft** dropdown: create blank draft or start from an existing **template** (blocked with warning dialog when using shared SMTP). + * + * Draft editor supports HTML preview, recipients, schedule/send, and duplicate-from-template flows on the child route. + */ + export default function PageClient() { const stackAdminApp = useAdminApp(); const project = stackAdminApp.useProject(); diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-sent/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-sent/page-client.tsx index 414e4ac8f..4084cec10 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-sent/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-sent/page-client.tsx @@ -181,6 +181,24 @@ function EmailSendDataTable() { ); } +/** + * @dashboardReference emails/sent + * @dashboardReferenceDescription Outbox delivery log and sending-domain reputation. + * + * ## Email log card + * + * **DesignPillToggle** switches views: + * + * - **List all** — paginated `DataGrid` (recipient, subject, time, status badge). Row click opens **email-viewer/[emailId]** + * - **Group by template/draft** — `GroupedEmailTable` clusters sends by source template or draft + * + * Status labels cover scheduled, sent, failed, etc. (`email-status-utils`). + * + * ## Domain reputation + * + * Right column (`DomainReputationCard`) shows DNS/SPF/DKIM health for configured sending domains. + */ + export default function PageClient() { const [viewMode, setViewMode] = useState("list"); diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-settings/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-settings/page-client.tsx index a6094189e..e47bc58ba 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-settings/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-settings/page-client.tsx @@ -5,6 +5,25 @@ import { PageLayout } from "../page-layout"; import { DomainSettings } from "./domain-settings"; import { ThemeSettings } from "./theme-settings"; +/** + * @dashboardReference emails/email-settings + * @dashboardReferenceDescription SMTP delivery, managed domains, and email themes. + * + * ## Theme settings (`ThemeSettings`) + * + * Pick the active email theme, preview rendered HTML at miniature scale, and open **email-themes** to edit layouts. Themes apply to templates and programmatic sends. + * + * ## Domain settings (`DomainSettings`) + * + * Configure delivery backend: + * + * - **Shared** / **Managed** / **Resend** / **Custom SMTP** + * - Managed domains: DNS records, verification status, sender local part + * - Test send, copy DNS records, download zone file helpers + * + * Saving updates `config.emails.server` via deferred dialogs and config push. + */ + export default function PageClient() { return ( diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/page-client.tsx index 55cb3b48a..4fca8c432 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/email-templates/page-client.tsx @@ -12,6 +12,21 @@ import { AppEnabledGuard } from "../app-enabled-guard"; import { PageLayout } from "../page-layout"; import { useAdminApp } from "../use-admin-app"; +/** + * @dashboardReference emails/templates + * @dashboardReferenceDescription Transactional email templates (HTML + variables). + * + * ## Template list + * + * Card per template with display name. **Open** navigates to `email-templates/[templateId]` editor. Row menu: **Delete** (blocked with error if template is in use). + * + * ## Warnings + * + * Orange alert when `emails.server` uses the **shared** SMTP server — custom templates require your own SMTP (**Email Settings**). + * + * **New Template** creates a template via dialog (requires non-shared SMTP). + */ + export default function PageClient() { const stackAdminApp = useAdminApp(); const project = stackAdminApp.useProject(); diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/launch-checklist/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/launch-checklist/page-client.tsx index 24a7c8e8c..6da841240 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/launch-checklist/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/launch-checklist/page-client.tsx @@ -23,6 +23,46 @@ import { AppEnabledGuard } from "../app-enabled-guard"; import { PageLayout } from "../page-layout"; import { useAdminApp } from "../use-admin-app"; +/** + * @dashboardReference launch-checklist/launch-checklist + * @dashboardReferenceDescription Pre-launch checklist before enabling production mode. + * + * ## Progress card (top) + * + * - Title shows `N/M Checks Completed` or **Everything is ready to launch.** + * - Progress bar (animated) across all sub-checks + * - **Up next** + rainbow **Go to {section}** button when work remains (jumps to that section’s primary CTA) + * - When all checks pass, message to enable production mode below + * + * Incomplete task sections are sorted **above** completed ones. Only one section expanded at a time (auto-opens the “up next” section). + * + * ## Task sections (expandable cards) + * + * Each card: title, subtitle, checklist rows (green check / empty circle), footer CTA, optional extra content. Click header to expand/collapse. + * + * ### 1. Domains & callbacks → **Open domain settings** (Domains) + * + * - Production domain saved (shows up to three `InlineCode` domains) + * - **Localhost callbacks disabled** (`allowLocalhost` off) + * + * ### 2. OAuth providers → **Configure providers** (Auth Methods) + * + * - **Custom client IDs and secrets** — no providers on shared dev keys (orange badges list offenders) + * - Expand **View guides**: provider tabs (Google, GitHub, …), external docs link, **Callback URL** `https://api.hexclave.com/api/v1/auth/oauth/callback/{provider}` + * + * ### 3. Email server → **Configure email server** (Emails) + * + * - **Custom SMTP or Resend in use** (not shared `sent-with-hexclave` sender) + * - Expand **View steps**: verify domain, switch SMTP/Resend, send test email + * + * ### 4. Production mode + * + * - **Automated checks passing** — lists `productionModeErrors` with **open setting** links if blocked + * - **Production mode enabled** — inline **Enable production mode** switch (disabled until checks pass); confetti when turned on + * - Footer **Open project settings** / **Review settings** + * + * Enable production mode only after domains, OAuth, and email sections are green. See [Launch checklist](https://docs.hexclave.com/docs/apps/launch-checklist). + */ type ProviderGuide = { label: string, docsUrl: string, diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/onboarding/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/onboarding/page-client.tsx index b52a2e8e1..58882fa73 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/onboarding/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/onboarding/page-client.tsx @@ -137,6 +137,32 @@ function EnableEmailVerificationDialog({ ); } +/** + * @dashboardReference onboarding/onboarding + * @dashboardReferenceDescription Gate app access until users verify their email. + * + * Single-setting page for the **Onboarding** app (separate from Auth Methods, though Auth Methods also exposes the same config toggle). + * + * ## Require email verification + * + * Compact settings row: + * + * - Label **Require email verification** + * - Description: verified primary email required before users continue after sign-up + * - **Switch** — maps to `onboarding.requireEmailVerification` (immediate save, loading state on toggle) + * + * ## Enabling (on → true) + * + * If existing unverified users would be affected, a confirmation dialog opens first: + * + * - Title **Enable email verification?** + * - Count + sample list of affected accounts (Unverified / Anonymous badges) + * - **Cancel** or **Enable** — then config updates + * + * Turning **off** applies immediately with no preview. + * + * Restricted users are filtered from normal API responses until they complete verification. Same field also appears under **Auth Methods → Sign-up** card. + */ export default function PageClient() { const stackAdminApp = useAdminApp(); const project = stackAdminApp.useProject(); diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/customers/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/customers/page-client.tsx index 4f397803d..1a98c6c2d 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/customers/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/customers/page-client.tsx @@ -45,6 +45,26 @@ type SelectedCustomer = { type ProductEntry = [string, CompleteConfig["payments"]["products"][string]]; +/** + * @dashboardReference payments/customers + * @dashboardReferenceDescription Grant products to users or teams and inspect entitlements. + * + * ## Customer picker + * + * Toggle **User** vs **Team**, then search and select a customer. Until selected, grant actions are disabled. + * + * ## Entitlements table + * + * `DataGrid` of active product grants for the selected customer: product, item/price, status, period end. Row actions can revoke or adjust grants (via config updates). + * + * ## Actions + * + * - **Grant product** — pick product + item, optional trial/discount fields + * - **Add item** — shortcut to create a new price in config (`ItemDialog`) + * + * URL state tracks customer type and selection for shareable support links. + */ + export default function PageClient() { const adminApp = useAdminApp(); const project = adminApp.useProject(); diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/payouts/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/payouts/page-client.tsx index 45773d1a9..0bdb3975d 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/payouts/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/payouts/page-client.tsx @@ -7,6 +7,17 @@ import { PageLayout } from "../../page-layout"; import { StripeConnectProvider } from "@/components/payments/stripe-connect-provider"; import { useAdminApp } from "../../use-admin-app"; +/** + * @dashboardReference payments/payouts + * @dashboardReferenceDescription Stripe Connect payouts for connected accounts. + * + * ## Availability + * + * Hidden in **development environments** and **preview deployments** (alert explains why). In production, renders Stripe **ConnectPayouts** inside `StripeConnectProvider` after Stripe is linked on **Settings**. + * + * Operators manage payout schedules and balances here; connect Stripe first under **Payments → Settings**. + */ + export default function PageClient() { const adminApp = useAdminApp(); const project = adminApp.useProject(); diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/product-lines/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/product-lines/page-client.tsx index 7a7e9f1bc..72be56825 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/product-lines/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/product-lines/page-client.tsx @@ -814,6 +814,21 @@ function OnboardingSlideshow() { ); } +/** + * @dashboardReference payments/product-lines + * @dashboardReferenceDescription Group products into mutually exclusive product lines. + * + * ## Empty state + * + * If the project has no products or items yet, shows an onboarding slideshow ending with **Create Your First Product** (links to `payments/products/new`). + * + * ## Product lines view + * + * When catalog exists, lists product lines from config. Each line is a set of products where a customer may hold at most one active product from that line. Create, rename, and assign products via `PageClientProductLinesView`. + * + * Configure lines before scaling the catalog — they enforce exclusivity at checkout and grant time. + */ + export default function PageClient() { const adminApp = useAdminApp(); const paymentsConfig = adminApp.useProject().useConfig().payments; diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/page-client.tsx index fb38f8db0..8fedcddfd 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/products/page-client.tsx @@ -3,6 +3,28 @@ import { PageLayout } from "../../page-layout"; import PageClientListView from "./page-client-list-view"; +/** + * @dashboardReference payments/products-and-items + * @dashboardReferenceDescription Manage products, prices (items), and checkout URLs. + * + * ## Layout + * + * Two-column list: **Products** (left) and **Items / prices** (right). Selecting a product filters its items. + * + * ## Product actions + * + * - **Create product** — dialog (display name, customer type user/team, product line) + * - Row menu: **Edit**, **Copy checkout URL**, **Delete** + * - Row click opens product detail (`payments/products/[productId]`) + * + * ## Item actions + * + * - **Create item** — price, billing interval, entitlements + * - **Edit** / **Delete** per item; checkout URL validation surfaces config errors inline + * + * Revenue sparklines may appear on product rows when analytics data exists. + */ + export default function PageClient() { return ( diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/settings/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/settings/page-client.tsx index 32470f6c7..73e0eae4a 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/settings/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/settings/page-client.tsx @@ -13,6 +13,20 @@ import { PaymentMethods } from "./payment-methods"; import { StripeConnectionCheck } from "./stripe-connection-check"; import { TestModeToggle } from "./test-mode-toggle"; +/** + * @dashboardReference payments/settings + * @dashboardReferenceDescription Stripe connection, test mode, payment methods, and checkout guardrails. + * + * ## Sections (top to bottom) + * + * - **Stripe connection** — link or view Connect account status (`StripeConnectionCheck`) + * - **Test mode** — toggle sandbox vs live charges (`TestModeToggle`) + * - **Payment methods** — enable/disable card and other methods (`PaymentMethods`) + * - **Checkout controls** — **Block new purchases** toggle (`payments.blockNewPurchases`); stops new checkouts while keeping existing subscriptions + * + * All toggles save to project config with optimistic UI on the block-purchases switch. + */ + export default function PageClient() { const adminApp = useAdminApp(); const project = adminApp.useProject(); diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/transactions/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/transactions/page-client.tsx index 8c5b73880..503a83b8d 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/transactions/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/payments/transactions/page-client.tsx @@ -3,6 +3,17 @@ import { TransactionTable } from "@/components/data-table/transaction-table"; import { PageLayout } from "../../page-layout"; +/** + * @dashboardReference payments/transactions + * @dashboardReferenceDescription Browse payment and subscription transactions for this project. + * + * ## Transactions table + * + * Uses the shared `TransactionTable` component: paginated `DataGrid` of purchases, refunds, and subscription events with filters and row detail. Sort and search state sync to the URL. + * + * Use **Customers** to grant products; this page is read-only history for reconciliation and support. + */ + export default function PageClient() { return ( diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-permissions/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-permissions/page-client.tsx index 6d3642739..220f0eab6 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-permissions/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/project-permissions/page-client.tsx @@ -9,6 +9,26 @@ import { AppEnabledGuard } from "../app-enabled-guard"; import { PageLayout } from "../page-layout"; import { useAdminApp } from "../use-admin-app"; +/** + * @dashboardReference rbac/project-permissions + * @dashboardReferenceDescription Define project-scoped permission IDs and compose them into roles. + * + * ## Header + * + * **Create Permission** opens a dialog with **ID** (lowercase, numbers, `_`, `:`), **Description**, and **Contained permissions** (inherit other project permissions). + * + * ## Permissions table (`DataGrid`) + * + * Paginated, searchable list of project permission definitions. Row actions: + * + * - **Edit** — update description and contained permissions (ID is read-only) + * - **Delete** — remove the permission definition + * + * Permission IDs map directly to `$permission_id` checks in the SDK (`user.hasPermission`, etc.). + * + * Public guide: [RBAC](https://docs.hexclave.com/docs/apps/rbac). + */ + export default function PageClient() { const [createPermissionModalOpen, setCreatePermissionModalOpen] = React.useState(false); const [tableVersion, setTableVersion] = React.useState(0); diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/session-replays/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/session-replays/page-client.tsx index 900c56db3..35c2d9ab8 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/session-replays/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/session-replays/page-client.tsx @@ -49,6 +49,25 @@ const LEGACY_PLAYER_SPEED_STORAGE_KEY = "stack.session-replay.speed"; type RrwebEventWithTime = import("rrweb/typings/types").eventWithTime; type RrwebReplayer = InstanceType; +/** + * @dashboardReference analytics/replays + * @dashboardReferenceDescription Watch rrweb session recordings tied to users and teams. + * + * ## Layout + * + * Split view: session list (left) + player (right). Standalone `/session-replays/[id]` deep-links one replay with back link. + * + * ## Session list + * + * Infinite scroll (`PAGE_SIZE` 50), filters for user, team, duration, last active, click count. Each row shows user, duration, event/chunk counts, relative time. + * + * ## Player + * + * rrweb replayer with play/pause, speed, skip inactive, timeline scrubber, multi-tab streams, and event inspector. Settings persist in `localStorage`. + * + * Embedded mode hides chrome when opened from a user profile. `SessionReplayLimitBanner` when replay quota applies. + */ + type RecordingRow = { id: string, projectUser: { diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sign-up-rules/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sign-up-rules/page-client.tsx index 4ee2a0433..7b295bdc6 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sign-up-rules/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/sign-up-rules/page-client.tsx @@ -1757,6 +1757,33 @@ function OrderChangeActions({ // Page client — owns all state; passes handlers to PageBody // ───────────────────────────────────────────────────────────────────────────── +/** + * @dashboardReference authentication/sign-up-rules + * @dashboardReferenceDescription Fraud-protection sign-up rules (CEL conditions, ordered evaluation). + * + * ## Rule list + * + * Rules stored in `auth.signUpRules`, sorted by **priority** (top = first match). Drag-and-drop reorder with **Save order** / **Discard** when `pendingOrder` is set. Each row: enable toggle, action badge (Allow / Reject / Restrict / Log), sparkline + trigger counts, menu **Edit** / **Delete**. + * + * ## Default outcome + * + * **If no rules match** → configurable **Allow** or **Reject** (`auth.signUpRulesDefaultAction`). + * + * ## Rule editor (inline) + * + * Three steps: name, **When** (visual CEL condition builder), **Then** (action + message). Conditions can reference email domain, country, auth method, OAuth provider, Turnstile, risk scores. + * + * ## Trigger history + * + * Per-rule dialog queries ClickHouse `$sign-up-rule-trigger` events (paginated). + * + * ## Test rules + * + * **Test rules** card simulates a sign-up payload against current rules without affecting production (email, auth method, overrides for country/Turnstile/risk). + * + * Also available as the **Fraud Protection** sub-app (same page, `sign-up-rules` route). + */ + export default function PageClient() { const stackAdminApp = useAdminApp(); const project = stackAdminApp.useProject(); diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/team-permissions/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/team-permissions/page-client.tsx index 2c606eac0..25758f42e 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/team-permissions/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/team-permissions/page-client.tsx @@ -9,6 +9,20 @@ import { AppEnabledGuard } from "../app-enabled-guard"; import { PageLayout } from "../page-layout"; import { useAdminApp } from "../use-admin-app"; +/** + * @dashboardReference rbac/team-permissions + * @dashboardReferenceDescription Define team-scoped permission IDs used in team membership checks. + * + * ## Header + * + * **Create Permission** — same shape as project permissions: unique **ID**, **Description**, optional **Contained permissions** from existing team permissions. + * + * ## Permissions table (`DataGrid`) + * + * Lists team permission definitions with search, pagination, **Edit**, and **Delete**. Team permission IDs are referenced in team settings defaults and in SDK team-scoped authorization. + * + * Pair with **Teams → Team Settings** for default creator/member grants. + */ export default function PageClient() { const [createPermissionModalOpen, setCreatePermissionModalOpen] = React.useState(false); diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/team-settings/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/team-settings/page-client.tsx index bab425b27..016a2505a 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/team-settings/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/team-settings/page-client.tsx @@ -16,6 +16,26 @@ import { AppEnabledGuard } from "../app-enabled-guard"; import { PageLayout } from "../page-layout"; import { useAdminApp } from "../use-admin-app"; +/** + * @dashboardReference teams/team-settings + * @dashboardReferenceDescription Control team creation behavior and default RBAC grants. + * + * ## Team Creation card + * + * Deferred-save editable grid (toggle → **Save** / **Discard**): + * + * | Toggle | Config | Effect | + * | --- | --- | --- | + * | **Client Team Creation** | `teams.allowClientTeamCreation` | Users can create teams from account settings / team switcher | + * | **Personal Team on Sign-up** | `teams.createPersonalTeamOnSignUp` | Auto-creates a personal team for each new user (not retroactive) | + * + * ## Default permissions cards + * + * Two cards — **Team Creator** and **Team Member** — show badges for permissions in `rbac.defaultPermissions.teamCreator` / `teamMember`. **Edit** opens a checkbox dialog over the team permission graph (inheritance shown inline). + * + * Changes push to project config immediately on save. + */ + function PermissionSelectDialog(props: { trigger: React.ReactNode, type: "creator" | "member", diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/teams/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/teams/page-client.tsx index 320a84ba0..1aa8a6dc3 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/teams/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/teams/page-client.tsx @@ -15,6 +15,53 @@ type CreateDialogProps = { onOpenChange: (open: boolean) => void, }; +/** + * @dashboardReference teams/teams + * @dashboardReferenceDescription List, search, and manage teams for this project. + * + * ## Header + * + * - **Create Team** (top right) — opens a dialog with **Display Name** only; Hexclave assigns the team ID on create. + * + * ## Info banner + * + * When the project has **no teams yet**, an alert may link to **project membership** invites (`/projects?team_settings=…`) — that is for inviting dashboard collaborators, not the customer teams in this table. + * + * ## KPI cards (four) + * + * Sparkline metric cards above the table (from project analytics): + * + * - **New Active Teams** — recently active teams (new in the activity window) + * - **Daily Active Teams** (DAT) + * - **Returning Team Rate** + * - **Total Teams** — all-time count + * + * ## Teams table (`DataGrid`) + * + * Paginated list (infinite scroll, 25 per page). Default sort: **Created At** descending. Toolbar **quick search** filters by team (server-side `listTeams` query). State syncs to URL (`teams` prefix). + * + * | Column | Notes | + * | --- | --- | + * | **ID** | Team UUID (monospace) | + * | **Display Name** | Editable via row actions | + * | **Created At** | Sortable | + * | **Actions** | Row menu (see below) | + * + * **Row click** navigates to the team detail page (`/projects/…/teams/[teamId]`). + * + * ### Row action menu + * + * - **View Members** — same destination as row click + * - **Edit** — change display name (ID shown read-only in dialog) + * - **Create Checkout** — opens payments checkout dialog for this team (when Payments is in use) + * - **Delete** — destructive; requires typing that removal cannot be undone (members are removed from the team) + * + * ## Team detail page (after row click) + * + * Separate route: edit display name inline, **Members** tab (invite by email, member table), **Metadata**, and sections for enabled apps (e.g. analytics, payments). Not rendered on this list page. + * + * Public integration guide: [Teams](https://docs.hexclave.com/docs/apps/teams). + */ export default function PageClient() { const stackAdminApp = useAdminApp(); const teams = stackAdminApp.useTeams({ limit: 1 }); diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/vercel/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/vercel/page-client.tsx index e58dd8603..248071125 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/vercel/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/vercel/page-client.tsx @@ -55,6 +55,25 @@ const STATUS_META: Record< }, }; +/** + * @dashboardReference vercel/setup + * @dashboardReferenceDescription Step-by-step checklist to deploy Hexclave on Vercel. + * + * ## Progress card + * + * Accordion steps with manual checkboxes (stored in local UI state). Progress bar and confetti when all items are marked done. + * + * | Step | Tasks | + * | --- | --- | + * | **Project** | Confirm Hexclave project | + * | **Keys** | Generate publishable + secret keys (`createInternalApiKey`) | + * | **Env vars** | Copy `EnvKeys` snippet into Vercel | + * | **Deploy** | Trigger redeploy on preview + production | + * | **Verify** | Test `/handler/signup` on deployed URL | + * + * Keys display once — copy before navigating away. Requires **Vercel** app enabled. + */ + export default function PageClient() { const adminApp = useAdminApp(); const project = adminApp.useProject(); diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/page-client.tsx index 8d1e73996..d8e8bd5a0 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/webhooks/page-client.tsx @@ -27,7 +27,41 @@ import { type DataGridColumnDef, } from "@hexclave/dashboard-ui-components"; - +/** + * @dashboardReference webhooks/webhooks + * @dashboardReferenceDescription Manage Svix webhook endpoints for user and team events. + * + * Syncs user/team lifecycle events to your servers. Page subtitle explains purpose. + * + * ## Modes + * + * - **Preview deployments** — info alert only; webhooks unavailable + * - **AppPortal URL** — full embedded Svix UI (replaces inline grid) + * - **Default** — inline **Endpoints** card below (Svix React SDK) + * + * ## Endpoints card + * + * Subtitle warns endpoints receive sensitive data — must be URLs you control. + * + * - **Add new endpoint** — dialog: URL (validated), optional description, HTTP warning for `http://`; on success offers **Test endpoint** or close + * - **DataGrid** (client-side list, quick search, URL state prefix `webhooks`) + * + * | Column | Notes | + * | --- | --- | + * | **Endpoint URL** | Destination | + * | **Description** | Optional label | + * | **Status** | Active / Disabled badge | + * | **Actions** | Row menu | + * + * ### Row menu + * + * - **View Details** → `/projects/…/webhooks/[endpointId]` (secrets, delivery attempt history) + * - **Test** — sends sample test event; dialog shows payload preview and delivery result + * - **Edit** — update description only (URL fixed) + * - **Delete** — confirm removal from Svix + * + * Verify payloads server-side with your webhook secret — [Webhooks](https://docs.hexclave.com/docs/apps/webhooks). + */ export default function PageClient() { const stackAdminApp = useAdminApp(); const svixToken = stackAdminApp.useSvixToken(); diff --git a/apps/dashboard/src/lib/dashboard-reference-nav-only-pages.ts b/apps/dashboard/src/lib/dashboard-reference-nav-only-pages.ts new file mode 100644 index 000000000..5a268ba34 --- /dev/null +++ b/apps/dashboard/src/lib/dashboard-reference-nav-only-pages.ts @@ -0,0 +1,65 @@ +/** + * Dashboard reference docs for apps that appear in the sidebar but do not have a + * dedicated `page-client.tsx` under the project route yet. + */ + +/** + * @dashboardReference neon/neon-integration + * @dashboardReferenceDescription Connect a Neon Postgres project to Hexclave (OAuth + API key provisioning). + * + * ## Dashboard entry + * + * Enabling the **Neon** app in the app store opens the Neon OAuth flow. After authorization, Hexclave creates a project API key scoped to your selected Stack project and links it to the Neon database. + * + * ## In-product flow + * + * - **OAuth confirm** (`/integrations/neon/confirm`) — pick or create the Hexclave project to link + * - **Transfer confirm** (`/integrations/neon/projects/transfer/confirm`) — approve moving an existing Neon-linked project + * + * ## Operator notes + * + * The integration grants Neon read/write access to users, teams, and permissions for the linked project. Revoke keys under **Project Settings → Project Keys** if you disconnect Neon. + * + * Public guide: [Neon integration](https://docs.hexclave.com/guides/integrations/neon/overview). + */ + +/** + * @dashboardReference catalyst/catalyst + * @dashboardReferenceDescription Hexclave Catalyst — AI-assisted project setup (app store entry). + * + * ## Dashboard entry + * + * **Catalyst** is listed in the app store. Enabling it routes operators to Catalyst-powered onboarding flows (experimental). There is no separate project-scoped configuration screen in the dashboard today. + * + * Use the app store card to enable/disable the app for the project (`apps.installed.catalyst`). + */ + +/** + * @dashboardReference tv-mode/tv-mode + * @dashboardReferenceDescription Full-screen dashboard display for office TVs and status walls. + * + * ## Dashboard entry + * + * **TV mode** is a navigable app with a dedicated route (`tv-mode`). It is intended for read-only, large-format views of project metrics and health — not day-to-day configuration. + * + * Enable the app from the app store, then open **TV mode** from the sidebar to launch the display UI. + */ + +/** + * @dashboardReference email-api/email-api + * @dashboardReferenceDescription Programmatic email sending via the Hexclave server SDK. + * + * ## Dashboard entry + * + * The **Email API** app documents how to send transactional email from server code using templates and themes configured in the **Emails** app. The sidebar entry points at the Email API overview; delivery logs live under **Emails → Sent**. + * + * ## Typical workflow + * + * 1. Configure SMTP or managed delivery in **Emails → Email Settings** + * 2. Author templates in **Emails → Templates** (and themes in Email Settings) + * 3. Call the Email API from your backend with the secret server key + * + * Public guide: [Email API](https://docs.hexclave.com/docs/apps/email-api). + */ + +export {};