diff --git a/.agents/skills/design/storybook-links.md b/.agents/skills/design/storybook-links.md index ace2d69..c3daa0f 100644 --- a/.agents/skills/design/storybook-links.md +++ b/.agents/skills/design/storybook-links.md @@ -1,21 +1,23 @@ -# Aura Storybook Links +# Design System Component Links -Canonical reference for all Aura Storybook URLs. If the Storybook +Canonical reference for all design system Storybook URLs. If the design system domain or path structure changes, update this file and propagate to individual skills. -Base URL: `https://cognitedata.github.io/aura/storybook/` +Base URL: `https://your-organization.github.io/design-system/storybook/` -Last verified against Storybook: 2026-03-13 +Last verified: 2026-05-31 + +> Note: Replace `your-organization` and `design-system` with your actual organization and design system names. ## Foundations | Foundation | URL | |-----------|-----| -| Colors | https://cognitedata.github.io/aura/storybook/?path=/docs/foundations-colors--docs | -| Effects | https://cognitedata.github.io/aura/storybook/?path=/docs/foundations-effects--docs | -| Layout | https://cognitedata.github.io/aura/storybook/?path=/docs/foundations-layout--docs | -| Typography | https://cognitedata.github.io/aura/storybook/?path=/docs/foundations-typography--docs | +| Colors | https://your-organization.github.io/design-system/storybook/?path=/docs/foundations-colors--docs | +| Effects | https://your-organization.github.io/design-system/storybook/?path=/docs/foundations-effects--docs | +| Layout | https://your-organization.github.io/design-system/storybook/?path=/docs/foundations-layout--docs | +| Typography | https://your-organization.github.io/design-system/storybook/?path=/docs/foundations-typography--docs | ## Components — Actions and Inputs diff --git a/AGENTS.md b/AGENTS.md index 4a46113..1967801 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,19 +6,19 @@ This app uses [github/spec-kit](https://github.com/github/spec-kit) for spec-dri - To start a new feature, run `/speckit.specify ` in Claude Code or Cursor. It generates a properly numbered feature directory and a spec to fill in. Then run `/speckit.clarify` → `/speckit.plan` → `/speckit.tasks` → `/speckit.implement`. - When user-visible behavior changes in an existing feature, update its `specs/-/spec.md` before or alongside the code change. -- When a feature touches Cognite Data Fusion data, the spec must document existing CDF views read from, new views needed, and spaces used. +- When a feature integrates with backend data sources, the spec must document data models, APIs, and data contracts involved. --- ## 1. UI Components -Always check `@cognite/aura/components` before reaching for a raw HTML element or custom CSS/Tailwind solution. If Aura has a component that covers the need, use it. Only fall back to custom solutions when Aura genuinely doesn't cover the use case. +Always check your chosen component library (e.g., Aura, shadcn/ui, Material-UI, Chakra UI) before reaching for a raw HTML element or custom CSS/Tailwind solution. If your component library has a component that covers the need, use it. Only fall back to custom solutions when the library genuinely doesn't cover the use case. --- -## 2. Host integration (`@cognite/app-sdk`) +## 2. Host/Platform integration -The Fusion host exposes a `HostAppAPI` (imported as `HostAppAPI` from `@cognite/app-sdk`) via `connectToHostApp(...)`. Reach for it whenever the situation calls for it — don't hand-roll an equivalent or read browser globals directly. +When deploying to a host platform (Fusion, portal, dashboard, or embedded context), use the platform's official API to access host capabilities like navigation, auth, and state management. Reach for it whenever the situation calls for it — don't hand-roll an equivalent or read browser globals directly. ### Decision rule for any new piece of state @@ -32,28 +32,28 @@ When in doubt, host-synced is the safer default — over-syncing is cheap, under ### API surface - **Host-synced UI state** → on startup, seed your state from the `initialState` string returned by `connectToHostApp`. On every change, call `api.syncInternalState(JSON.stringify(state))`. The host serializes this into the URL so reloads and shared links restore the same state. **Do not** hold state from the "host-synced" category above in plain `useState` / `useRef` / a local store. -- **Navigating elsewhere in Fusion** (another app, a Fusion route) → `api.navigateInternal({ path, queryParams, hash })`. Never set `window.location` directly. -- **Navigating to an external URL** → `api.navigateExternal({ url, openInNewTab })`. Only `https:` is allowed. -- **Needing a CDF base URL or access token** for API requests → `api.getBaseUrl()` / `api.getAccessToken()`. Never hardcode the cluster URL. -- **Needing the current CDF project name** → `api.getProject()`. Don't read it from config or URL params. -- **Exposing the app's capabilities to a Fusion agent** → register a custom agent server with `api.registerAgentServer(handle)` and clean up on unmount with `api.unregisterAgentServer(uri)`. +- **Navigating to another app or internal route** → use the platform's `navigateInternal()` API instead of `window.location` to maintain state and context. +- **Navigating to an external URL** → use the platform's `navigateExternal()` API where available; ensure only safe URLs (`https:`) are allowed. +- **Needing a base URL or access token** for API requests → call the platform's `getBaseUrl()` / `getAccessToken()` helpers instead of hardcoding or reading from globals. +- **Needing the current project/workspace identifier** → call the platform's getter (e.g., `getProject()`) instead of reading from config or URL params. +- **Exposing the app's capabilities to an agent or AI system** → use the platform's agent registration API and clean up on unmount. -Get `api` once at app startup and surface it to the rest of the app via React context so view models can depend on it through the patterns below. +Get the platform API instance once at app startup and surface it to the rest of the app via React context so view models can depend on it through the patterns below. ### Round-trip example: host-synced state ```typescript -import { connectToHostApp, type HostAppAPI } from '@cognite/app-sdk'; +import { connectToHost, type HostAPI } from './platform'; // or your platform SDK type AppState = { page: 'a' | 'b'; filters: string[] }; const DEFAULT_STATE: AppState = { page: 'a', filters: [] }; // On startup — seed from initialState, not from a hardcoded default. -const { api, initialState } = await connectToHostApp({ applicationName: 'watercourse-dm' }); +const { api, initialState } = await connectToHost({ applicationName: 'my-app' }); const seeded: AppState = initialState ? (JSON.parse(initialState) as AppState) : DEFAULT_STATE; // On every change — push the new state to the host so the URL stays in sync. -async function updateState(next: AppState, api: HostAppAPI) { +async function updateState(next: AppState, api: HostAPI) { setState(next); // your local React/store setter await api.syncInternalState(JSON.stringify(next)); } @@ -277,9 +277,9 @@ const mock = { postMessage: vi.fn() } as Partial as Window; --- -## 8. CogniteClient / authentication +## 8. SDK / API client and authentication -Auth is handled by `CogniteSdkProvider` from `@cognite/app-sdk/react` (see `App.tsx`). Nested components get the client via `useCogniteSdk()`. To wire up or migrate auth, run the `/setup-flows-auth` skill. +Auth and API client setup should be handled at the app root via a provider (e.g., `SdkProvider`, `AuthProvider`, etc.). Nested components access the client via a context hook (e.g., `useSdk()`, `useClient()`). Centralize all authentication logic in one place for consistency and testability. --- diff --git a/CLAUDE.md b/CLAUDE.md index 4a46113..1967801 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,19 +6,19 @@ This app uses [github/spec-kit](https://github.com/github/spec-kit) for spec-dri - To start a new feature, run `/speckit.specify ` in Claude Code or Cursor. It generates a properly numbered feature directory and a spec to fill in. Then run `/speckit.clarify` → `/speckit.plan` → `/speckit.tasks` → `/speckit.implement`. - When user-visible behavior changes in an existing feature, update its `specs/-/spec.md` before or alongside the code change. -- When a feature touches Cognite Data Fusion data, the spec must document existing CDF views read from, new views needed, and spaces used. +- When a feature integrates with backend data sources, the spec must document data models, APIs, and data contracts involved. --- ## 1. UI Components -Always check `@cognite/aura/components` before reaching for a raw HTML element or custom CSS/Tailwind solution. If Aura has a component that covers the need, use it. Only fall back to custom solutions when Aura genuinely doesn't cover the use case. +Always check your chosen component library (e.g., Aura, shadcn/ui, Material-UI, Chakra UI) before reaching for a raw HTML element or custom CSS/Tailwind solution. If your component library has a component that covers the need, use it. Only fall back to custom solutions when the library genuinely doesn't cover the use case. --- -## 2. Host integration (`@cognite/app-sdk`) +## 2. Host/Platform integration -The Fusion host exposes a `HostAppAPI` (imported as `HostAppAPI` from `@cognite/app-sdk`) via `connectToHostApp(...)`. Reach for it whenever the situation calls for it — don't hand-roll an equivalent or read browser globals directly. +When deploying to a host platform (Fusion, portal, dashboard, or embedded context), use the platform's official API to access host capabilities like navigation, auth, and state management. Reach for it whenever the situation calls for it — don't hand-roll an equivalent or read browser globals directly. ### Decision rule for any new piece of state @@ -32,28 +32,28 @@ When in doubt, host-synced is the safer default — over-syncing is cheap, under ### API surface - **Host-synced UI state** → on startup, seed your state from the `initialState` string returned by `connectToHostApp`. On every change, call `api.syncInternalState(JSON.stringify(state))`. The host serializes this into the URL so reloads and shared links restore the same state. **Do not** hold state from the "host-synced" category above in plain `useState` / `useRef` / a local store. -- **Navigating elsewhere in Fusion** (another app, a Fusion route) → `api.navigateInternal({ path, queryParams, hash })`. Never set `window.location` directly. -- **Navigating to an external URL** → `api.navigateExternal({ url, openInNewTab })`. Only `https:` is allowed. -- **Needing a CDF base URL or access token** for API requests → `api.getBaseUrl()` / `api.getAccessToken()`. Never hardcode the cluster URL. -- **Needing the current CDF project name** → `api.getProject()`. Don't read it from config or URL params. -- **Exposing the app's capabilities to a Fusion agent** → register a custom agent server with `api.registerAgentServer(handle)` and clean up on unmount with `api.unregisterAgentServer(uri)`. +- **Navigating to another app or internal route** → use the platform's `navigateInternal()` API instead of `window.location` to maintain state and context. +- **Navigating to an external URL** → use the platform's `navigateExternal()` API where available; ensure only safe URLs (`https:`) are allowed. +- **Needing a base URL or access token** for API requests → call the platform's `getBaseUrl()` / `getAccessToken()` helpers instead of hardcoding or reading from globals. +- **Needing the current project/workspace identifier** → call the platform's getter (e.g., `getProject()`) instead of reading from config or URL params. +- **Exposing the app's capabilities to an agent or AI system** → use the platform's agent registration API and clean up on unmount. -Get `api` once at app startup and surface it to the rest of the app via React context so view models can depend on it through the patterns below. +Get the platform API instance once at app startup and surface it to the rest of the app via React context so view models can depend on it through the patterns below. ### Round-trip example: host-synced state ```typescript -import { connectToHostApp, type HostAppAPI } from '@cognite/app-sdk'; +import { connectToHost, type HostAPI } from './platform'; // or your platform SDK type AppState = { page: 'a' | 'b'; filters: string[] }; const DEFAULT_STATE: AppState = { page: 'a', filters: [] }; // On startup — seed from initialState, not from a hardcoded default. -const { api, initialState } = await connectToHostApp({ applicationName: 'watercourse-dm' }); +const { api, initialState } = await connectToHost({ applicationName: 'my-app' }); const seeded: AppState = initialState ? (JSON.parse(initialState) as AppState) : DEFAULT_STATE; // On every change — push the new state to the host so the URL stays in sync. -async function updateState(next: AppState, api: HostAppAPI) { +async function updateState(next: AppState, api: HostAPI) { setState(next); // your local React/store setter await api.syncInternalState(JSON.stringify(next)); } @@ -277,9 +277,9 @@ const mock = { postMessage: vi.fn() } as Partial as Window; --- -## 8. CogniteClient / authentication +## 8. SDK / API client and authentication -Auth is handled by `CogniteSdkProvider` from `@cognite/app-sdk/react` (see `App.tsx`). Nested components get the client via `useCogniteSdk()`. To wire up or migrate auth, run the `/setup-flows-auth` skill. +Auth and API client setup should be handled at the app root via a provider (e.g., `SdkProvider`, `AuthProvider`, etc.). Nested components access the client via a context hook (e.g., `useSdk()`, `useClient()`). Centralize all authentication logic in one place for consistency and testability. ---