taruvi-ai/skills · Archived

taruvi-refine-frontend

Build Refine.dev admin UIs backed by Taruvi using `@taruvi/refine-providers` v1.3.0. Six providers wrap the Taruvi data API, storage, app-level resources, users, auth (OAuth redirect), and Cerbos accessControl. Use for list/show/edit/create pages against Taruvi datatables, file browsers on storage buckets, role/user management UI, accessControl with useCan, OAuth login flow, useCustom against functions and analytics. TRIGGERS include "Refine page Taruvi", "useList Taruvi", "Taruvi admin UI", "d…

First seen Apr 17, 2026

Installation

$ npx skills add taruvi-ai/skills --skill taruvi-refine-frontend

Summary

  • Build Refine.dev admin UIs backed by Taruvi using `@taruvi/refine-providers` v1.3.0.
  • Six providers wrap the Taruvi data API, storage, app-level resources, users, auth (OAuth redirect), and Cerbos accessControl.
  • Use for list/show/edit/create pages against Taruvi datatables, file browsers on storage buckets, role/user management UI, accessControl with useCan, OAuth login flow, useCustom against functions and analytics.
  • TRIGGERS include "Refine page Taruvi", "useList Taruvi", "Taruvi admin UI", "dataProvider Taruvi", "@taruvi/refine-providers", "meta.populate", "meta.bucketName", "meta.idColumnName", "Taruvi accessControl Refine", "Taruvi useCustom meta.kind", "refine-providers upsert", "Taruvi OAuth Refine".
  • SKIP when provisioning backend (use taruvi-backend-provisioning) or writing Python function code (use taruvi-functions).
  • Covers all 6 providers, 24 filter operators, DataLoader batching, _cachedUser, 401/403 split, and the meta options consumers reach for.

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from taruvi-ai/skills.

npx skills add taruvi-ai/skills

Browse all from taruvi-ai/skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

License LICENSE
Default branch main
Open issues 0
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Version1.0.0
LicenseApache-2.0
CompatibilityRequires `@refinedev/core` ^5.0.0 (Refine v5) and `@taruvi/sdk` + `@taruvi/refine-providers` installed in the consuming React/Refine project.
More metadata
author
EOX Vantage
version
1.0.0
organization
Taruvi

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 13,829 B
  • docs SUMMARY.md 1,002 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 2 installs

SKILL.md

Taruvi Refine frontend

Use @taruvi/refine-providers to connect Refine.dev admin UIs to Taruvi. This skill covers the six providers, how to wire resources, the meta vocabulary that unlocks Taruvi-specific features (populate, aggregate, graph, upsert), and the gotchas that aren't obvious from the package API alone.

This skill is the frontend layer. If you're provisioning backend resources, switch to taruvi-backend-provisioning. If you're writing Python for a Taruvi function body, switch to taruvi-functions.

Core principles

  1. Resource name = datatable name by default. Override with meta.tableName when they must differ (e.g., resource: "active_users" queries tableName: "users" with a filter).
  2. Meta is the control surface. Refine's meta object is how you reach Taruvi-specific features (populate, aggregate, graph, bucketName, idColumnName, upsert, deleteByFilter). Don't try to push these through filters or query params.
  3. Multiple providers, one client. Register all six providers against the same Client instance. Select providers by dataProviderName in hooks.
  4. Auth is redirect-based. There is no credentials login in the default Refine flow. authProvider.login() redirects to Taruvi's login endpoint.
  5. AccessControl batches. Permission checks are debounced 50ms via DataLoader. Tests that don't await will flake.

Setup

import { Refine } from "@refinedev/core";
import { Client } from "@taruvi/sdk";
import {
  dataProvider,
  storageDataProvider,
  appDataProvider,
  userDataProvider,
  authProvider,
  accessControlProvider,
} from "@taruvi/refine-providers";

const client = new Client({
  apiKey: process.env.REACT_APP_TARUVI_KEY!,
  appSlug: process.env.REACT_APP_TARUVI_APP!,
  apiUrl: process.env.REACT_APP_TARUVI_API_URL!,
});

export function App() {
  return (
    <Refine
      dataProvider={{
        default: dataProvider(client),
        storage: storageDataProvider(client),
        app: appDataProvider(client),
        user: userDataProvider(client),
      }}
      authProvider={authProvider(client)}
      accessControlProvider={accessControlProvider(client)}
      resources={[
        { name: "posts", list: "/posts", create: "/posts/create", edit: "/posts/edit/:id" },
        { name: "authors" },
      ]}
    >
      {/* Routes, layouts, pages */}
    </Refine>
  );
}

The six providers

1. dataProvider (default)

CRUD against Taruvi datatables. Covers getList, getOne, getMany, create, createMany, update, updateMany, deleteOne, deleteMany, custom.

See [references/data-provider.md](references/data-provider.md) for full API.

Filter operators ([references/filter-operators.md](references/filter-operators.md)): 24 supported — eq, ne, lt/lte/gt/gte, in/nin, contains/containss (case-insensitive), startswith/endswith (plus s suffix for case-insensitive), negated forms (ncontains, nstartswith, etc.), between/nbetween, null/nnull.

2. storageDataProvider

Buckets and objects. Resource name = bucket name (or override via meta.bucketName).

  • getList — list files in bucket, supports size/date/prefix filters.
  • getOne — download file as Blob (default) or get metadata (meta.metadata: true).
  • create — upload files: values: { files: File[], paths?: string[], metadatas?: object[] }.
  • update — update file metadata.
  • deleteOne / deleteMany — delete by path.

See [references/provider-quickref.md](references/provider-quickref.md).

3. appDataProvider

App-level resources: roles, settings, secrets; plus useCustom for function and analytics execution.

Supported resources:

  • getList("roles") — list app roles.
  • getList("secrets") — batch fetch by meta.keys: string[].
  • getOne("settings") — app settings.
  • getOne("secrets", key) — single secret.

useCustom for execution:

  • meta.kind: "function" → executes url as function slug.
  • meta.kind: "analytics" → executes url as analytics query slug.

4. userDataProvider

Users, roles (per user), user-apps. resource: "users" with id: "me" fetches current user. resource: "roles" with meta.username fetches that user's roles. resource: "apps" with meta.username fetches accessible apps.

5. authProvider

Refine AuthProvider interface backed by Taruvi's OAuth redirect flow.

  • login(callbackUrl?) — redirects to Taruvi login endpoint. No credentials flow.
  • logout(callbackUrl?) — clears cached user, redirects.
  • check() — token presence check (local); server validation happens on API call failure.
  • register(callbackUrl?) — redirect to signup.
  • getIdentity() — current user, cached to _cachedUser.
  • getPermissions() — reuses _cachedUser to avoid a second call.
  • onError(error) — 401 → logout + redirect to /login; 403 → surface error only.

See [references/auth-access-control.md](references/auth-access-control.md).

6. accessControlProvider

Cerbos permission checks via Taruvi Policy. DataLoader batches checks within a 50ms window (configurable via options.batchDelayMs).

const { data: canCreate } = useCan({
  resource: "posts",
  action: "create",
});

Returns { can: boolean, reason?: string }. Falls back gracefully if user is unauthenticated.

The meta vocabulary

See [references/meta-options-cookbook.md](references/meta-options-cookbook.md) for the full list.

Quick reference:

Meta field Purpose Example
populate Expand FK relations "author,category" or "*" or ["author", "comments"]
select Field projection (return only listed fields) ["id", "total", "status"]
headers Custom request headers { "X-Request-ID": "..." }
idColumnName Override default "id" PK "user_id"
tableName Override resource → table mapping "users" (when resource is "active_users")
bucketName Override resource → bucket mapping (storage) "user-uploads"
aggregate Aggregate expressions ["sum(total)", "count(*)"]
groupBy Group-by fields ["status", "category"]
having Filters on aggregates [{field: "sum(total)", operator: "gte", value: 1000}]
format Graph format "tree" \ "graph"
include Graph direction "descendants" \ "ancestors" \ "both"
depth Graph traversal depth 3
graph_types Filter edge types in graph ["parent_of", "related"]
upsert Use upsert on create true
deleteByFilter Delete matching filters true (plus meta.filters)
allowedActions Request per-row permissions ["update", "delete"]
metadata Storage: return metadata vs blob true
kind App provider: function vs analytics "function" \ "analytics"
keys App provider secrets: which to fetch ["STRIPEKEY", "APIURL"]
username User provider: for roles/apps "alice"

Common patterns

List with populate and filters

const { data, isLoading } = useList({
  resource: "posts",
  filters: [
    { field: "status", operator: "eq", value: "published" },
    { field: "author_id", operator: "in", value: [1, 2, 3] },
  ],
  sorters: [{ field: "created_at", order: "desc" }],
  pagination: { currentPage: 1, pageSize: 20 },
  meta: {
    populate: ["author", "category"],
  },
});

Upsert on create

const { mutate } = useCreate();

mutate({
  resource: "users",
  values: { id: 42, email: "[email protected]" },
  meta: { upsert: true },
});

Graph traversal

const { data } = useList({
  resource: "categories",
  meta: {
    format: "tree",
    include: "descendants",
    depth: 3,
  },
});

Aggregation

const { data } = useList({
  resource: "orders",
  meta: {
    aggregate: ["sum(total)", "count(*)"],
    groupBy: ["status"],
    having: [{ field: "sum(total)", operator: "gte", value: 1000 }],
  },
});

File upload

const { mutate } = useCreate();

mutate({
  dataProviderName: "storage",
  resource: "user-uploads",
  values: {
    files: [file1, file2],
    paths: [`${userId}/avatar.png`, `${userId}/cover.png`],
    metadatas: [{ kind: "avatar" }, { kind: "cover" }],
  },
});

Execute a function from the UI

const { refetch: sendEmail } = useCustom({
  dataProviderName: "app",
  url: "send-welcome-email",
  method: "post",
  config: { payload: { user_id: userId } },
  meta: { kind: "function" },
  queryOptions: { enabled: false },
});

Access control on a button

const { data: canDelete } = useCan({
  resource: "posts",
  action: "delete",
  params: { id: postId },
});

return canDelete?.can ? <DeleteButton id={postId} /> : null;

Gotchas

  1. meta.idColumnName defaults to "id". Tables with a different PK must pass idColumnName on every hook that needs it (useOne, useUpdate, useDelete).
  2. Resource vs table name. Refine's resource name goes straight to Taruvi unless meta.tableName overrides. If you name your resource active-users but the table is users, you'll get a 404.
  3. _cachedUser staleness. After a role change, the cached user is stale until logout or page refresh. Force re-fetch via useGetIdentity with queryOptions: { refetchOnMount: true } if you need fresh permissions.
  4. 401 vs 403 onError semantics. 401 triggers logout + redirect; 403 does not. Handle 403 UX yourself (toast, error page).
  5. authProvider.login() without callbackUrl goes to the default callback. Pass one if you want to land back on the originating page.
  6. useCan fires for every row. A list of 100 rows calling useCan per row → 100 batched checks in one request via DataLoader, but that first render is 50ms delayed. Test with await in tests.
  7. useCustom with meta.kind: "function" ignores method. Functions are always POST under the hood.
  8. Storage getOne returns a Blob by default. Pass meta.metadata: true to get the file's metadata object instead.
  9. Graph format="tree" requires hierarchy.enabled on the table. Graph format requires graph.enabled. See the backend-provisioning skill for schema setup.
  10. user-invocable: false-style skills don't apply here — this is a client-side library, not an agent skill runtime. Don't confuse consumer app configuration with agent skill metadata.

Verification checklist

Before reporting a frontend feature as done:

  • Every new Refine resource is registered in the <Refine resources={[...]}> array with at least a name.
  • Resources whose name doesn't match the Taruvi datatable have meta.tableName set on every hook — or the resource is renamed to match.
  • Tables with non-id primary keys pass meta.idColumnName on every hook (useOne, useUpdate, useDelete, useUpdateMany).
  • Dashboard / KPI widgets aggregate server-side (meta.aggregate/meta.groupBy for single-table, or useCustom with meta.kind: "analytics" for multi-table) — never full row fetches derived in React.
  • List pages use backend pagination, server-side filters, server-side sort. No client-side filtering of backend results.
  • useCan or meta.allowedActions gates the right UI elements; 403 vs 401 errors render as expected (403 stays on page, 401 redirects to login).
  • Storage batch uploads surface the all-or-nothing failure mode correctly in UX; batch deletes surface per-file status.
  • Notifications go through Refine's notificationProvider — no ad-hoc toast libraries.
  • node scripts/validate-resource-map.js <path-to-app> passes (or was skipped with a documented reason).

When you get stuck

  • Full API reference for the default provider: [references/data-provider.md](references/data-provider.md).
  • Every filter operator: [references/filter-operators.md](references/filter-operators.md).
  • All meta options in context: [references/meta-options-cookbook.md](references/meta-options-cookbook.md).
  • Auth + access control details: [references/auth-access-control.md](references/auth-access-control.md).
  • Direct @taruvi/sdk usage when providers don't fit: [references/sdk-primer.md](references/sdk-primer.md).
  • Exported types and utility functions: [references/types-and-utilities.md](references/types-and-utilities.md).
  • Validate Refine resources match Taruvi datatables: node scripts/validate-resource-map.js (see script header for usage).