---
name: docyrus-app-dev-react
description: Build Docyrus React TypeScript web applications end-to-end, combining authentication, API access, generated collections, TanStack Query/Form patterns, and production-grade UI implementation with preferred component libraries. Use when creating or modifying Docyrus-backed apps that use @docyrus/api-client, @docyrus/signin, Docyrus collections, queries, dashboards, forms, tables, layouts, or Docyrus UI components.
---

# Docyrus App Dev React

Build Docyrus React TypeScript applications end-to-end. This skill combines app architecture, authentication, data access, query patterns, and production-grade UI guidance in one place.

## Tech Stack

- React 19 + TypeScript + Vite
- TanStack Router (code-based), TanStack Query (server state), TanStack Form
- Tailwind CSS v4, shadcn/ui components
- `@docyrus/api-client` + `@docyrus/signin`
- Auto-generated collections from OpenAPI spec
- Preferred UI libraries: shadcn, diceui, animate-ui, docyrus-ui, reui

## When to Use This Skill

Use this skill when you are:

- Building or modifying a Docyrus-backed React app
- Setting up authentication with `@docyrus/signin`
- Fetching or mutating data with generated collections or `@docyrus/api-client`
- Designing feature UIs such as dashboards, forms, tables, layouts, dialogs, analytics, or detail pages
- Selecting between shadcn, diceui, animate-ui, docyrus-ui, and reui components
- Implementing complete feature flows that combine data access and polished UI

## End-to-End Feature Workflow

1. Set up app auth, routing, and query providers.
2. Use generated Docyrus collection hooks or the REST client for data access.
3. Define `columns`, filters, formulas, child queries, and mutations correctly.
4. Check preferred UI components before building anything custom.
5. Use Docyrus form and detail patterns for create, edit, and item detail flows.
6. Connect UI actions to TanStack Query mutations and invalidate relevant queries.

## Quick Start: App Bootstrap

### Root provider setup

```tsx
import { DocyrusAuthProvider } from '@docyrus/signin'

<DocyrusAuthProvider
  apiUrl={import.meta.env.VITE_API_BASE_URL}
  clientId={import.meta.env.VITE_OAUTH2_CLIENT_ID}
  redirectUri={import.meta.env.VITE_OAUTH2_REDIRECT_URI}
  scopes={['offline_access', 'Read.All', 'DS.ReadWrite.All', 'Users.Read']}
  callbackPath="/auth/callback"
>
  <QueryClientProvider client={queryClient}>
    <RouterProvider router={router} />
  </QueryClientProvider>
</DocyrusAuthProvider>
```

### Auth gate and current-user access

```tsx
const { status, user, hasRole, hasPermission } = useDocyrusAuth()

if (status === 'loading') return <Spinner />
if (status === 'unauthenticated') return <SignInButton />

// user is auto-fetched from /v1/users/me after authentication
// hasRole('super_admin') — check role by slug or uid
// hasPermission('edit', dataSourceId) — check ACL permission on a data source
```

### Data fetching with generated collections

```tsx
const { list } = useBaseProjectCollection()
const { data: projects } = useQuery({
  queryKey: ['projects'],
  queryFn: () =>
    list({
      columns: ['name', 'status', 'record_owner(firstname,lastname)'],
      filters: { rules: [{ field: 'status', operator: '!=', value: 'archived' }] },
      orderBy: 'created_on DESC',
      limit: 50,
    }),
})
```

## Common Docyrus Asset URL Templates

- `User avatar path template`: `https://api.docyrus.app/storage/v1/object/tenant-public/:tenantId/users/:userId/:user.photo`
- `Tenant logo path template`: `https://api.docyrus.app/storage/v1/object/tenant-public/:tenantId/:tenant.logo`

Use these templates when wiring user chips, assignee avatars, comments, activity feeds, app shell branding, workspace switchers, and any `DataGrid` user option payload that needs `avatarUrl`.

## Critical App/Data Rules

1. **Always send `columns`** in `.list()` and `.get()` calls. Without it, only `id` is returned.
2. **Collections are React hooks** — call `useBaseProjectCollection()`, `useUsersCollection()`, and similar hooks inside React components.
3. **Data source endpoints are dynamic** — they only exist if the data source is defined in the tenant OpenAPI spec.
4. **Use `id` for `count` calculations**. Use actual field slugs for `sum`, `avg`, `min`, and `max`.
5. **Child query keys must appear in `columns`**.
6. **Formula keys must appear in `columns`**.
7. **Use `useUsersCollection().getMyInfo()`** for current user profile instead of making a direct profile call.
8. **Regenerate collections after schema changes** by rebuilding the tenant OpenAPI spec, downloading the latest `openapi.json`, and re-running the collection generator.

## Critical UI/UX Rules

1. **Always check preferred components first** before creating anything custom.
2. **Use `AwesomeCard` for dashboards** unless the user explicitly wants a different card style.
3. **Use animate-ui `Sidebar` for app layouts** unless another layout is requested.
4. **Prefer Recharts for charts**. shadcn chart primitives are the default wrapper.
5. **Use icons in this order**: hugeicons, then fontawesome light, then lucide.
6. **Use `AwesomeDialog` for item create forms**.
   - Small/simple forms: `container="sheet"` with `side="right"`
   - Long/complex forms: `container="modal"` or `container="drawer"`
7. **Choose detail containers based on item complexity**.
   - Large items: dedicated page
   - Small items: `AwesomeDialog` right sheet
8. **All forms must use TanStack Form + the Docyrus form system**. Do not build feature forms with plain HTML forms or React Hook Form directly.
9. **Use `EditableRecordDetail` for inline editing** in item detail views.
10. **Always enable `trackChanges`** for editable detail and grid experiences.
11. **When using Docyrus `DataGrid`, always set the correct `meta.cell` variant for the field type**. Do not reuse a generic text cell for typed Docyrus data.
12. **When rendering data source records in tables, cards, or lists, prefer the matching Docyrus value renderer** instead of handwritten display JSX.
13. **When editing inline, pass the real `IField` metadata into `EditableRecordDetailField` or `EditableValue`** so Docyrus can dispatch the correct editor and display pair from `field.type`.
14. **If a field type has no dedicated `DataGrid` cell variant, keep the grid cell read-only and move editing to a sheet, dialog, or detail page**.

## Default UI Choices

| Use Case | Default Component | Library |
|----------|-------------------|---------|
| Item create form | `AwesomeDialog` | docyrus |
| Quick record create | `CreateRecordDialog` | docyrus |
| Item detail (small) | `AwesomeDialog` sheet right | docyrus |
| Item detail (large) | Dedicated page | — |
| Inline editing | `EditableRecordDetail` | docyrus |
| Dashboard card | `AwesomeCard` | docyrus |
| Stat dashboards | `AwesomeStats` | docyrus |
| App navigation | `Sidebar` | animate-ui |
| Data table | `DataTable` | diceui |
| Editable grid | `Data Grid` | docyrus |
| Grid saved views | `DataGridViewSelect` | docyrus |
| Forms | Docyrus form fields + TanStack Form | docyrus |
| Charts | shadcn chart + Recharts | shadcn |
| File upload | File Upload | diceui |
| Gantt/project scheduling | `Gantt` | docyrus |
| Resource scheduling | `ResourceSchedulerPanel` | docyrus |
| Team chat | `TeamChatChannel` | docyrus |
| AI interface | `DocyrusAgent` | docyrus |
| Pricing / quoting | `PricingEnginePanel` | docyrus |
| Analytics / pivot | `PivotGrid` | docyrus |

## Data Source Field Type UI Mapping

If you already have Docyrus field metadata, prefer explicit Docyrus field-specific primitives over custom UI glue:

- Forms: use the specific `*FormField` for the field type
- Read-only display: matching value renderer / `DynamicValue`
- Inline editing: `EditableRecordDetailField` or `EditableValue`
- Editable grids: `DataGrid` with the matching `meta.cell` variant

Use the table below as the default mapping guide.

| Field type(s) | `DataGrid` cell variant | Form field | Inline edit | Value renderer | Notes |
|---------------|-------------------------|------------|-------------|----------------|-------|
| `field-text` | `short-text` | `TextFormField` | `EditableValue` with `field-text` | `TextValue` | Default single-line text |
| `field-textarea` | `long-text` | `TextareaFormField` | `EditableValue` with `field-textarea` | `TextValue` | Multi-line content |
| `field-email` | `email` | `EmailFormField` | `EditableValue` with `field-email` | `EmailValue` | Use for clickable email cells |
| `field-url` | `url` | `UrlFormField` | `EditableValue` with `field-url` | `UrlValue` | Prefer typed URL rendering over plain text |
| `field-phone` | `phone` | `PhoneFormField` | `EditableValue` with `field-phone` | `PhoneValue` | Supports phone-specific display and editing |
| `field-number` | `number` | `NumberFormField` | `EditableValue` with `field-number` | `NumberValue` | Standard numeric input |
| `field-money` | `currency` | `MoneyFormField` | `EditableValue` with `field-money` | `MoneyValue` | Use money-specific formatting |
| `field-currency` | `currency-code` | `CurrencyCodeFormField` | `EditableValue` with `field-currency` | `CurrencyCodeValue` | ISO currency codes |
| `field-duration` | `duration` | `DurationFormField` | `EditableValue` with `field-duration` | `DurationValue` | Duration editing/display |
| `field-rating` | `rating` | `RatingFormField` | `EditableValue` with `field-rating` | `RatingValue` | Star rating |
| `field-select` | `select` | `SelectFormField` | `EditableValue` with `field-select` | `SelectValue` | Single select with Docyrus enum options |
| `field-radioGroup` | `select` | `RadioGroupFormField` | `EditableValue` with `field-radioGroup` | `SelectValue` | In grids, use a select-style cell |
| `field-enum` | `enum` | `EnumFormField` | `EditableValue` with `field-enum` | `SelectValue` | Backend-driven enum values |
| `field-status` | `status` | `StatusFormField` | `EditableValue` with `field-status` | `StatusValue` | Preserves status metadata such as description/follow-up |
| `field-multiSelect` | `multi-select` | `MultiSelectFormField` | `EditableValue` with `field-multiSelect` | `MultiSelectValue` | Multi-badge selection |
| `field-tagSelect` | `tag-select` | `TagSelectFormField` | `EditableValue` with `field-tagSelect` | `MultiSelectValue` | Colored tag chips |
| `field-userSelect` | `user` | `UserSelectFormField` | `EditableValue` with `field-userSelect` | `UserValue` | Populate `CellUserOption.avatarUrl` using the user avatar template |
| `field-userMultiSelect` | `user-multi-select` | `UserMultiSelectFormField` | `EditableValue` with `field-userMultiSelect` | `UserMultiValue` | Use the avatar template for each selected user |
| `field-relation` | `relation` | `RelationFormField` | `EditableValue` with `field-relation` | `RelationValue` | Prefer Docyrus relation lookup behavior |
| `field-date` | `date` | `DateFormField` | `EditableValue` with `field-date` | `DateValue` | Date-only |
| `field-dateTime` | `datetime` | `DateTimeFormField` | `EditableValue` with `field-dateTime` | `DateTimeValue` | Date + time |
| `field-time` | `time` | `TimeFormField` | `EditableValue` with `field-time` | `TimeValue` | Time-only |
| `field-dateRange` | `date-range` | `DateRangeFormField` | `EditableValue` with `field-dateRange` | `DateRangeValue` | Start/end pairs |
| `field-checkbox` | `checkbox` | `CheckboxFormField` | `EditableValue` with `field-checkbox` | `CheckboxValue` | Boolean checkbox |
| `field-switch` | `switch` | `SwitchFormField` | `EditableValue` with `field-switch` | `SwitchValue` | Boolean toggle |
| `field-color` | `color` | `ColorFormField` | `EditableValue` with `field-color` | `ColorValue` | Use the swatch-aware UI |
| `field-icon` | `icon` | `IconFormField` | `EditableValue` with `field-icon` | `IconValue` | Keep icon selection/rendering typed |
| `field-file` | `file` | `FileFormField` | `EditableValue` with `field-file` when inline file editing is acceptable | `FileValue` | Grid editing is fine only when upload UX fits the workflow |
| `field-image` | `image` | `ImageFormField` | `EditableValue` with `field-image` when inline image editing is acceptable | `ImageValue` | Prefer preview-aware image handling |
| `field-locationSelect` | `—` | `LocationSelectFormField` | `EditableValue` with `field-locationSelect` | `LocationValue` | No dedicated `DataGrid` cell variant in current docs; prefer detail editing |
| `field-docEditor` | `—` | `DocEditorFormField` | `EditableValue` with `field-docEditor` | `DocEditorValue` | Avoid dense grid editing; use a detail view or sheet |
| `field-htmlEditor` | `—` | `HtmlEditorFormField` | `EditableValue` with `field-htmlEditor` | `RichTextValue` | Prefer detail editing over grid editing |
| `field-emailEditor` | `—` | `EmailEditorFormField` | `EditableValue` with `field-emailEditor` | `RichTextValue` | Better in a drawer/modal editor |
| `field-codeEditor` | `long-text` or `—` | `CodeEditorFormField` | `EditableValue` with `field-codeEditor` | `CodeValue` | Prefer a detail editor if syntax-aware editing matters |
| `field-taskList` | `—` | `TaskListFormField` | `EditableValue` with `field-taskList` | `TaskListValue` | Better in detail surfaces than grids |
| `field-queryBuilder` | `—` | `QueryBuilderFormField` | `EditableValue` with `field-queryBuilder` | `—` | Use dedicated query-builder UI |
| `field-dynamic` | `—` | `DynamicConfigFormField` | `EditableValue` with `field-dynamic` | `—` | Specialized config UX |
| `field-schemaRepeater` | `—` | `SchemaRepeaterFormField` | `EditableValue` with `field-schemaRepeater` | `—` | Repeater editing belongs in a form/detail surface |
| `field-approvalStatus` | `—` | `ApprovalStatusFormField` | `EditableValue` with `field-approvalStatus` | `ApprovalStatusValue` | No dedicated `DataGrid` cell variant in current docs |
| `field-inlineData`, `field-inlineForm`, `field-todo` | `—` | `—` | Use `EditableValue` only if the field has a supported dedicated inline experience | `InlineDataValue`, `TodoValue` | Prefer specialized detail UI over grid editing |
| `field-display`, `field-formula`, `field-relatedField`, `field-button`, `field-identity`, `field-autonumber`, `field-list` | `—` | `—` | Keep read-only by default | `TextValue`, `FormulaValue`, `RelatedFieldValue`, `ButtonValue`, `IdentityValue`, `ListValue` | These are commonly display/virtual/system-driven rather than user-editable |
| `field-code` | `—` | `—` | Keep read-only or build a custom feature-specific editor intentionally | `TextValue` | Do not force this into a generic grid editor unless the simplification is intentional |

### Field-Type Mapping Notes

- `EditableValue` is the low-level inline editor. The important choice is the `field.type` you pass in; Docyrus uses that metadata to choose the correct inline form/display behavior.
- If a field type does not have a documented `DataGrid` cell variant, do not approximate it with a text cell unless the simplification is intentional and acceptable for the feature.
- For large rich-content or structured fields, prefer `AwesomeDialog`, dedicated detail pages, or `EditableRecordDetail` instead of dense grid editing.
- The current shared `FIELD_TYPES` list in the platform is the authoritative source. If UI docs mention a field type not present in the tenant schema/runtime, do not assume it is available.
- Reference docs:
  - `https://ui.docy.app/docs/web/docyrus/value-renderers/llms.txt`
  - `https://ui.docy.app/docs/web/docyrus/form-fields/llms.txt`
  - `https://ui.docy.app/docs/web/docyrus/editable-value/llms.txt`
  - `https://ui.docy.app/docs/web/docyrus/data-grid/llms.txt`

## Quick UI Patterns

### Item create form

```tsx
<AwesomeDialog open={open} onOpenChange={setOpen} container="sheet" side="right" size="default">
  <AwesomeDialogHeader title="Create Task" icon="far-plus" />
  <AwesomeDialogBody>
    <form.Field name="title">{(field) => <TextFormField field={field} label="Title" />}</form.Field>
    <form.Field name="status">{(field) => <SelectFormField field={field} label="Status" />}</form.Field>
  </AwesomeDialogBody>
  <AwesomeDialogFooter>
    <Button variant="outline" onClick={() => setOpen(false)}>Cancel</Button>
    <Button onClick={handleSubmit}>Create</Button>
  </AwesomeDialogFooter>
</AwesomeDialog>
```

### Item detail with inline editing

```tsx
<AwesomeDialog open={open} onOpenChange={setOpen} container="sheet" side="right" size="lg" fullscreenable>
  <AwesomeDialogHeader
    title="Task Detail"
    description="Review and edit task fields inline"
    headerButtons={<Button variant="outline" size="sm" onClick={switchToFullForm}>Edit All</Button>}
  />
  <AwesomeDialogBody>
    <EditableRecordDetail fields={fields} record={record} onSave={handleSave} trackChanges>
      <EditableRecordDetailField slug="title" />
      <EditableRecordDetailField slug="status" />
      <EditableRecordDetailField slug="assignee" />
      <EditableRecordDetailField slug="due_date" />
    </EditableRecordDetail>
  </AwesomeDialogBody>
</AwesomeDialog>
```

## TanStack Query Pattern

```typescript
function useProjects(params?: ICollectionListParams) {
  const { list } = useBaseProjectCollection()
  return useQuery({
    queryKey: ['projects', 'list', params],
    queryFn: () => list({ columns: PROJECT_COLUMNS, ...params }),
  })
}

function useCreateProject() {
  const { create } = useBaseProjectCollection()
  const qc = useQueryClient()
  return useMutation({
    mutationFn: (data: Record<string, unknown>) => create(data),
    onSuccess: () => {
      void qc.invalidateQueries({ queryKey: ['projects'] })
    },
  })
}
```

## Collection CRUD Methods

```typescript
const { list, get, create, update, delete: deleteOne, deleteMany } = useBaseProjectCollection()

list(params?: ICollectionListParams)
get(id, { columns })
create(data)
update(id, data)
deleteOne(id)
deleteMany({ recordIds })
```

API endpoint pattern: `/v1/apps/{appSlug}/data-sources/{slug}/items`

## Query Capabilities Summary

The `.list()` method supports:

- `columns`
- `filters`
- `filterKeyword`
- `orderBy`
- `limit` and `offset`
- `fullCount`
- `calculations`
- `formulas`
- `childQueries`
- `pivot`
- `expand`

## Component Installation Pattern

```bash
pnpm dlx shadcn@latest add button
pnpm dlx shadcn@latest add @diceui/data-table
pnpm dlx shadcn@latest add @animate-ui/sidebar
pnpm dlx @docyrus/cli add @docyrus/ui-awesome-card
pnpm dlx shadcn@latest add @reui/file-upload-default
```

## References

For deep dives, read:

- `references/README.md` — merged reference map for app development and UI design
- `references/api-client-and-auth.md`
- `references/collections-and-patterns.md`
- `../docyrus-api-dev/references/data-source-query-guide.md`
- `../docyrus-api-dev/references/formula-design-guide-llm.md`
- `../docyrus-api-dev/references/query-guide.md`
- `references/preferred-components-catalog.md`
- `references/component-selection-guide.md`
- `references/icon-usage-guide.md`
