# React + TypeScript + Vite

## Apps architecture (how your apps are built)

This repo is structured like a **library of independent apps** (React components) that share a common `Layout`, common Zustand store pieces, and common API clients.

### Where apps live

- **Apps**: `src/apps/<AppName>/`
- **Shared layout & UI**: `src/shared/`
- **Shared hooks**: `src/hooks/`
- **Shared Zustand store**: `src/store/`
- **Generated API clients (OpenAPI)**: `src/api/`

### App “contract” (what an app exports)

Each app exposes a single top-level React component that typically takes:

- `deploymentId: string` (required)
- `baseUrl?: string` (optional; forwarded into shared OpenAPI client BASE configuration together with `initConboAppDbQuery`)
- `getAccessToken?: () => Promise<string | undefined>` (optional; OAuth2 **access** token for APIs — e.g. Logto `getAccessToken(resource)`; omit only when your gateway accepts anonymous or cookie auth)
- `isAdmin?: boolean` (optional; often affects left sidebar options)
- `onHomeClick?: () => void` (optional; passed into the header)
- `UserComponent?: React.FC` or `() => JSX.Element` (optional; rendered in the header right side)

Most apps follow this shape:

- call `useConboAppDbQueryHostSync({ baseUrl, getAccessToken })`, or rely on a host-level `initConboAppDbQuery` / `<ConboAppDbQueryProvider>`
- call `useAppConfigurationsEffect(deploymentId)` (loads feeds/site/deployment config/reference points into the shared store)
- set `document.title = APPS_TITLE.<...>`
- render `Layout` with `header`, `sidebarLeft`, `content`, `sidebarRight`

### How apps are wired/consumed

- **Dev/demo mounting**: `src/main.tsx` mounts exactly **one** app component (others are commented out). This is how you run a specific app locally.
- **Public exports (library entry)**: `src/build/index.ts` re-exports app components. This is what consumers import from when this package is built/published.
- **Meta registry (titles/descriptions)**: `src/helpers/applicationsMeta.ts`
- **Titles enum-ish constants**: `src/helpers/constants.ts` (`APPS_TITLE`)

## Adding a new app (checklist)

When you add a new app, follow these steps:

### 1) Create the app folder

Create `src/apps/<NewApp>/` with at least:

- `src/apps/<NewApp>/<NewApp>.tsx` (root component)
- `src/apps/<NewApp>/index.ts` (re-export)

Root component should accept `deploymentId` and optionally `baseUrl`, `getAccessToken`, `isAdmin`, `onHomeClick`, `UserComponent`.

### 2) Re-export it from the build entry

Update `src/build/index.ts`:

- `export { NewApp } from "@/apps/<NewApp>";`

### 3) Add the app title constant

Update `src/helpers/constants.ts`:

- add `APPS_TITLE.NEW_APP = "New App"` (or your exact name)

### 4) Add app meta (optional but consistent)

Update `src/helpers/applicationsMeta.ts`:

- add `{ title, description }` entry for the new app

### 5) Run it locally in `main.tsx`

Temporarily mount it in `src/main.tsx` for development, similar to the existing examples:

- import your app from `@/apps/<NewApp>`
- render `<NewApp deploymentId={"..."} baseUrl="https://api.dev.conbo.app" />`

## Authenticated embedding (hosts using OAuth / Logto)

All generated OpenAPI clients share one **`OpenAPI.TOKEN` resolver** (`src/api/conboApiToken.ts`). Helpers such as `fetchWithErrorHandling` and `conboFetch` attach the same bearer header so manual `fetch` calls do not bypass auth.

Configure once at the host:

1. **`initConboAppDbQuery({ getAccessToken, apiBaseUrl })`** — `getAccessToken` should return the **resource/API access token** (not the Logto ID token). For Logto: use `getAccessToken(logtoResource)` with the same resource identifier your API validates as audience.
2. **`ConboAppDbQueryProvider`** — exported from this package; wraps children and reapplies when props change.
3. **Per-app props** — pass `getAccessToken` (and usually `baseUrl`) into any exported app component; values are forwarded into `initConboAppDbQuery` before descendants run effects.

If **`getAccessToken` is omitted** while your gateway requires bearer auth, requests go out **without** `Authorization` (legacy behaviour).

Regenerating clients (`yarn generate-*`): preserve **`TOKEN: conboOpenApiTokenResolver`** and the **`@/api/conboApiToken`** import in each `src/api/*/core/OpenAPI.ts`.

Public helpers also exported from `src/build/index.ts`: `initConboAppDbQuery`, `conboFetch`, `buildConboAuthorizedHeaders`, `getConboApiBaseUrl`.

Dev OpenAPI codegen URLs and samples target **`https://api.dev.conbo.app`** as the canonical API origin.

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh

## Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:

- Configure the top-level `parserOptions` property like this:

```js
export default {
  // other rules...
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
    project: ['./tsconfig.json', './tsconfig.node.json'],
    tsconfigRootDir: __dirname,
  },
}
```

- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
