--- name: docyrus-app-dev description: Build React TypeScript web applications using Docyrus as a backend. Use when creating or modifying apps that authenticate with Docyrus OAuth2, fetch/mutate data via the @docyrus/api-client library, use auto-generated collections for CRUD operations, or build queries with filters, aggregations, formulas, pivots, and child queries against Docyrus data sources. Triggers on tasks involving @docyrus/api-client, @docyrus/signin, Docyrus collections, data source queries, or Docyrus-backed React app development. --- # Docyrus App Developer Build React TypeScript web apps with Docyrus as the backend. Authenticate via OAuth2 PKCE, query data sources with powerful filtering/aggregation, and follow established patterns. ## Tech Stack - React 19 + TypeScript + Vite - TanStack Router (code-based), TanStack Query (server state) - Tailwind CSS v4, shadcn/ui components - `@docyrus/api-client` (REST client) + `@docyrus/signin` (auth provider) - Auto-generated collections from OpenAPI spec ## Quick Start: New App Setup 1. Wrap root with `DocyrusAuthProvider`: ```tsx import { DocyrusAuthProvider } from '@docyrus/signin' ``` 2. In App.tsx, sync API client for collections: ```tsx const { status } = useDocyrusAuth() const client = useDocyrusClient() useEffect(() => { if (client) setApiClient(client) }, [client]) if (status === 'loading') return if (status === 'unauthenticated') return ``` 3. Use collections in hooks: ```tsx const { data: projects } = useQuery({ queryKey: ['projects'], queryFn: () => baseProjectCollection.list({ columns: ['name', 'status', 'record_owner(firstname,lastname)'], filters: { rules: [{ field: 'status', operator: '!=', value: 'archived' }] }, orderBy: 'created_on DESC', limit: 50, }), }) ``` ## Critical Rules 1. **Always send `columns`** in `.list()` and `.get()` calls. Without it, only `id` is returned. 2. **Collections only work after auth** — `setApiClient(client)` must be called first. 3. **Data source endpoints are dynamic** — they only exist if the data source is defined in the tenant's OpenAPI spec. 4. **Use `id` field** for `count` calculations. Use the actual field slug for `sum`, `avg`, `min`, `max`. 5. **Child query keys must appear in `columns`** — e.g., if childQuery key is `orders`, include `'orders'` in the columns array. 6. **Formula keys must appear in `columns`** — e.g., if formula key is `total`, include `'total'` in the columns array. 7. **Use `UsersCollection.getMyInfo()`** for current user profile, not a direct API call. ## Regenerating Collections After Schema Changes When data sources or fields are created, updated, or deleted via the `docyrus-architect` MCP tools, the app's auto-generated collections become stale. To resync: 1. Call `regenerate_openapi_spec` (architect MCP) to rebuild and upload the tenant's OpenAPI spec 2. Download the new spec into the repo, overwriting the existing file: ```bash curl -o openapi.json "" ``` 3. Regenerate collections: ```bash pnpx @docyrus/tanstack-db-generator openapi.json ``` Always run all three steps together — a stale `openapi.json` or outdated collections will cause missing or incorrect endpoints at runtime. ## Collection CRUD Methods Every generated collection provides: ```typescript collection.list(params?: ICollectionListParams) // Query with filters, sort, pagination collection.get(id, { columns }) // Single record collection.create(data) // Create collection.update(id, data) // Partial update collection.delete(id) // Delete one collection.deleteMany({ recordIds }) // Delete many ``` API endpoint pattern: `/v1/apps/{appSlug}/data-sources/{slug}/items` ## Query Capabilities Summary The `.list()` method supports: | Feature | Purpose | |---------|---------| | `columns` | Select fields, expand relations `field(subfields)`, alias `alias:field`, spread `...field()` | | `filters` | Nested AND/OR groups with 50+ operators (comparison, date shortcuts, user-related) | | `filterKeyword` | Full-text search | | `orderBy` | Sort by fields with direction, including related fields | | `limit`/`offset` | Pagination (default 100) | | `fullCount` | Return total count alongside results | | `calculations` | Aggregations: count, sum, avg, min, max with grouping | | `formulas` | Computed virtual columns (simple functions, block AST, correlated subqueries) | | `childQueries` | Fetch related child records as nested JSON arrays | | `pivot` | Cross-tab matrix queries with date range series | | `expand` | Return full objects for relation/user/enum fields instead of IDs | **For query details, read**: `references/query-guide.md` ## TanStack Query Pattern ```typescript // Query hook function useItems(params?: ICollectionListParams) { return useQuery({ queryKey: ['items', 'list', params], queryFn: () => collection.list({ columns: COLUMNS, ...params }), }) } // Mutation hook function useCreateItem() { const qc = useQueryClient() return useMutation({ mutationFn: (data: Record) => collection.create(data), onSuccess: () => { void qc.invalidateQueries({ queryKey: ['items'] }) }, }) } ``` ## References Read these files when you need detailed information: - **`references/api-client-and-auth.md`** — RestApiClient API, @docyrus/signin hooks, auth provider config, interceptors, error handling, SSE/streaming, file upload/download - **`references/query-guide.md`** — Full query payload reference: column syntax, all filter operators, aggregations, simple/block/subquery formulas, child queries, pivot tables, expand - **`references/collections-and-patterns.md`** — Generated collection structure, UsersCollection, TanStack Query/mutation hook patterns, query key factories, app bootstrap flow, routing setup, API endpoints