A reactive @wordpress/data store and React hooks library for reading, querying, and mutating Frappe DocType resources (Frappe Framework & Frappe CRM) from WordPress and React applications.
Caution
Project is currently under active development.
npm install @lubusin/wp-frappe-data-store @wordpress/data @wordpress/element reactRegister the store once in your application entry point (main.tsx or plugin bootstrapper):
import { registerFrappeDataStore } from '@lubusin/wp-frappe-data-store';
export const frappeStore = registerFrappeDataStore({
storeName: 'my-app/frappe',
baseUrl: import.meta.env.DEV
? '/api/frappe-proxy'
: 'https://myfrappe.example.com',
headers: () => {
const token = localStorage.getItem('frappe_api_token');
return token ? { Authorization: `token ${token}` } : {};
},
credentials: 'include',
});Tip
For production WordPress plugins, route calls through a WordPress REST API endpoint (/wp-json/my-plugin/v1/frappe) using X-WP-Nonce to keep your API tokens securely on the server (wp-config.php). See the WordPress REST Proxy Guide.
Subscribe to list queries, single records, and mutations. Re-renders happen automatically when background fetches resolve or when caches are invalidated:
import {
useFrappeResourceList,
useFrappeResourceActions,
} from '@lubusin/wp-frappe-data-store';
import { frappeStore } from './store';
export function OpenTasks() {
const { resources, isResolving, error } = useFrappeResourceList(
frappeStore,
'Task',
{
fields: ['name', 'subject', 'status'],
filters: [['status', '=', 'Open']],
orderBy: 'modified desc',
limit: 20,
}
);
const { saveResource, deleteResource } = useFrappeResourceActions(frappeStore);
if (isResolving && !resources) return <p>Loading tasks…</p>;
if (error) return <p>Error loading tasks: {error.message}</p>;
return (
<div>
<ul>
{resources?.map((task) => (
<li key={task.name}>
{task.subject}
<button onClick={() => deleteResource('Task', task.name)}>
Delete
</button>
</li>
))}
</ul>
<button
onClick={() =>
saveResource('Task', { subject: 'New task', status: 'Open' })
}
>
Add Task
</button>
</div>
);
}Inspect Frappe (DocType) field definitions normalized specifically for UI rendering (label, type, placeholder, required, options):
import { useDocTypeDefinition } from '@lubusin/wp-frappe-data-store';
import { frappeStore } from './store';
export function LeadForm() {
const { docTypeDefinition, isResolving, error } = useDocTypeDefinition(
frappeStore,
'CRM Lead'
);
if (isResolving && !docTypeDefinition) return <p>Loading schema…</p>;
if (error || !docTypeDefinition) return null;
return (
<form>
<h3>Create {docTypeDefinition.name}</h3>
{docTypeDefinition.fields.map((field) => (
<label key={field.id} style={{ display: 'block', margin: '8px 0' }}>
{field.label}
{field.type === 'select' ? (
<select name={field.id} required={field.required}>
<option value="">Select option...</option>
{field.options?.map((opt) => (
<option key={opt} value={opt}>
{opt}
</option>
))}
</select>
) : (
<input
type={field.type === 'number' ? 'number' : 'text'}
name={field.id}
required={field.required}
readOnly={field.readOnly}
placeholder={field.placeholder}
/>
)}
</label>
))}
</form>
);
}See DocType Metadata & Forms Guide for detailed normalization rules and usage outside React components.
We provide two production-ready open-source starter repositories:
| Template | Description |
|---|---|
wpui-frappe-plugin-starter |
WordPress Admin Plugin featuring full-screen sidebar navigation across Frappe CRM entities (@wordpress/boot), server-side REST proxying, and instant WordPress Playground testing (npm run playground). |
wpui-frappe-app-starter |
Standalone SPA / DataViews featuring a WordPress-style app shell (@wordpress/dataviews), dynamic DocType form generation, Vite local proxying, and Vitest setup. |
For full setup instructions and comparison, check the Starter Templates Guide.
We have dedicated, comprehensive documentation hosted at wp-frappe-data.lubus.in:
- Getting Started: Setup, configuration, and environment handling
- React Hooks Guide: Detailed examples of list queries, item fetching, and mutations
- Proxy & CORS Setup: Vite dev proxying and WordPress server-side REST API proxy patterns
- DocType Metadata & Forms: Auto-generating UI forms using normalized schema definitions
- Starter Templates: Standalone architectures for WordPress plugins & SPAs
- API Reference: Full TypeScript classes, interfaces, hooks, and selectors
This library uses a modern TypeScript build and testing pipeline (tsup, vitest, and @wordpress/data).
Clone the repository and install dependencies using npm:
git clone https://github.com/lubusIN/wp-frappe-data-store.git
cd wp-frappe-data-store
npm install| Command | Description |
|---|---|
npm test |
Runs the full unit test suite using Vitest (tests/*.test.ts). |
npm run coverage |
Runs unit tests with V8 code coverage reports and checks threshold enforcement. |
npm run typecheck |
Performs strict TypeScript static type checking (tsc --noEmit). |
npm run build |
Compiles dual ES Module (.js) and CommonJS (.cjs) bundles along with TypeScript declaration files (.d.ts) to dist/. |
npm run docs:dev |
Auto-generates TypeDoc API documentation and starts a local VitePress dev server with live reload. |
Contributions are welcome! Please feel free to submit a Pull Request.
For issues and feature requests, please use the GitHub issue tracker.
LUBUS is a web design agency based in Mumbai.
WP Frappe Data Store is open-sourced licensed under the MIT License.
