Expert in creating React components for Obsidian plugins with proper TypeScript types and integration
From obsidian-plugin-buildernpx claudepluginhub jwplatta/agent-cubicle --plugin obsidian-plugin-builderThis skill uses the workspace's default tool permissions.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Migrates code, prompts, and API calls from Claude Sonnet 4.0/4.5 or Opus 4.1 to Opus 4.5, updating model strings on Anthropic, AWS, GCP, Azure platforms.
Orchestrates subagents to execute phased plans: deploys for implementation, verification, anti-pattern checks, code quality review, and commits only after passing checks.
You are an expert in building React components for Obsidian plugins.
import * as React from 'react';
import { useState, useEffect } from 'react';
interface MyComponentProps {
data: string;
onUpdate: (value: string) => void;
}
export const MyComponent: React.FC<MyComponentProps> = ({ data, onUpdate }) => {
const [value, setValue] = useState(data);
return (
<div className="my-component">
<input
value={value}
onChange={(e) => {
setValue(e.target.value);
onUpdate(e.target.value);
}}
/>
</div>
);
};
import { ItemView, WorkspaceLeaf } from 'obsidian';
import * as React from 'react';
import { createRoot, Root } from 'react-dom/client';
import { MyComponent } from './MyComponent';
export const VIEW_TYPE = 'my-view';
export class MyReactView extends ItemView {
root: Root | null = null;
constructor(leaf: WorkspaceLeaf) {
super(leaf);
}
getViewType() {
return VIEW_TYPE;
}
getDisplayText() {
return 'My View';
}
async onOpen() {
const container = this.containerEl.children[1];
container.empty();
container.addClass('my-view-container');
this.root = createRoot(container);
this.root.render(
<MyComponent
data="initial"
onUpdate={(value) => console.log(value)}
/>
);
}
async onClose() {
this.root?.unmount();
}
}
import { App, Modal } from 'obsidian';
import * as React from 'react';
import { createRoot, Root } from 'react-dom/client';
import { MyComponent } from './MyComponent';
export class MyReactModal extends Modal {
root: Root | null = null;
constructor(app: App) {
super(app);
}
onOpen() {
const { contentEl } = this;
this.root = createRoot(contentEl);
this.root.render(
<MyComponent
data="modal data"
onUpdate={(value) => {
console.log(value);
this.close();
}}
/>
);
}
onClose() {
this.root?.unmount();
}
}
{
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0"
}
}
Ensure esbuild.config.mjs handles JSX:
external: [
'obsidian',
'electron',
'@codemirror/*',
'react',
'react-dom'
],
When creating components: