developing-preact by oaustegard/claude-skills
npx skills add https://github.com/oaustegard/claude-skills --skill developing-preact将 Claude 转变为专业的 Preact 开发者,专注于使用原生优先架构构建基于标准的 Web 应用程序。此技能优先考虑原生 JavaScript、HTML 和 Web API,而非外部依赖,从而能够以最小的工具开销创建高性能、可维护的应用程序。
原生优先开发:在寻求外部库之前,优先利用 ES 模块、导入映射、Web 组件、原生表单验证、Fetch API 和内置 DOM 方法。对于快速原型设计和小型到中型应用程序,默认采用零构建解决方案,结合 HTM 和本地托管的 ESM 导入。
始终以工件形式交付:所有代码都应创建为工件,以便跨会话进行迭代编辑。
在以下场景中触发此技能:
遵循此决策树来确定最佳架构:
特征:快速原型、演示、教育示例或概念验证
架构:
scripts/vendor.sh 从 npm 注册表获取)广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
开始方式:运行 bash scripts/vendor.sh 获取依赖,然后使用 assets/boilerplate.html 作为基础
特征:无现有构建基础设施的生产应用程序,组件数 <10,状态管理简单
架构:
状态管理:使用全局 signals 管理共享状态,使用 useSignal 管理组件本地状态
特征:大型代码库、需要 TypeScript、多个入口点、需要高级优化
架构:
何时推荐:仅在确认团队的开发环境和构建要求之后
方法:匹配现有模式和工具。在建议更改之前,先分析代码库以确定当前架构。
对于独立示例,始终使用此精确的导入映射结构。依赖项通过 scripts/vendor.sh 本地托管(从 registry.npmjs.org 获取):
<script type="importmap">
{
"imports": {
"preact": "./vendor/preact.module.js",
"preact/hooks": "./vendor/hooks.module.js",
"@preact/signals-core": "./vendor/signals-core.mjs",
"@preact/signals": "./vendor/signals.mjs",
"htm": "./vendor/htm.module.js",
"htm/preact": "./vendor/htm.module.js"
}
}
</script>
关键点 — 模块化文件,而非独立捆绑包:请不要使用 htm/preact/standalone.module.js。独立捆绑包嵌入了自己的 Preact 副本,这会导致 @preact/signals 获得不同的 Preact 实例(它通过裸说明符 from 'preact' 导入)。模块化文件 + 导入映射 = 所有内容共享一个 Preact 实例。
为什么是本地托管,而非 CDN:esm.sh 是整个 npm 注册表的直通通道 — 允许它打开会带来任意的代码执行面。registry.npmjs.org 已经在容器出口允许列表中,并提供有作用域、版本化的压缩包。
默认使用 HTM 标签模板字面量,除非:
在心理上将 React/JSX 模式转换为 HTM 时,应用以下规则:
HTM 使用 JavaScript 模板字面量。JSX 中所有 {expression} 都变为 ${expression}。组件名称也是表达式,因此是 <${Component}>。
| 模式 | JSX | HTM |
|---|---|---|
| 组件标签 | <Button /> | <${Button} /> |
| 带子组件的组件 | <Modal>...</Modal> | <${Modal}>...</${Modal}> |
| 闭合标签 | </Modal> | </${Modal}> |
| 表达式 | {value} | ${value} |
| 属性 | prop={val} | prop=${val} |
| 展开属性 | {...obj} | ...${obj} |
| 事件处理器 | onClick={fn} | onClick=${fn} |
| 条件渲染 | {show && <X />} | ${show && html\<${X} />} |
| 三元表达式 | {a ? <X /> : <Y />} | ${a ? html\<${X} /> : html<${Y} />} |
| 映射 | {items.map(i => <Li />)} | ${items.map(i => html\...)} |
组件引用需要 ${}:组件名称是一个 JavaScript 表达式
// JSX
<Button onClick={handleClick}>Save</Button>
// HTM
<${Button} onClick=${handleClick}>Save</${Button}>
条件渲染组件时需要嵌套模板:当有条件地渲染组件(而非 HTML 元素)时,用 `html``` 包裹
// JSX
{isOpen && <Modal title="Hello" />}
// HTM
${isOpen && html`<${Modal} title="Hello" />`}
展开操作符无需大括号:在 HTM 中,展开直接使用 ...${obj}
// JSX
<Input {...inputProps} />
// HTM
<${Input} ...${inputProps} />
class 与 className:两者在 Preact 中都有效,但为了保持一致性和更小的输出,建议使用 class
| 错误 | 错误示例 | 正确示例 |
|---|---|---|
组件缺少 ${} | <Button> | <${Button}> |
| 错误的闭合语法 | </MyComponent> | </${MyComponent}> |
| 使用大括号而非模板 | {count} | ${count} |
| 展开操作符带大括号 | {...props} | ...${props} |
| 条件渲染中缺少 html 包装器 | ${show && <${X} />} | ${show && html\<${X} />} |
使用函数组件,配合:
默认:通过 CLI 使用 Tailwind CSS — 使用 npm install tailwindcss@3 --save-dev 安装,然后使用 npx tailwindcss -o vendor/tailwind.css --content "*.html" --minify 生成已清除的 CSS。这将产生约 6KB 的 CSS,仅包含使用的类。
避免:Tailwind CDN (cdn.tailwindcss.com) — 不在容器出口允许列表中,并且会加载完整的 100KB+ JIT 编译器。
避免:内联样式,除非是那些无法通过工具类表达的动态值。
替代方案:仅在项目需要作用域样式时使用 CSS 模块或 styled-components。
在推荐任何外部包之前,请验证:
记录任何依赖包含所依据的特定性能或能力优势。
对于涉及以下内容的复杂决策:
在确定方法之前,明确评估权衡。在代码注释中记录推理过程。
确保核心功能在可行的情况下无需 JavaScript 也能工作:
澄清:
参考上面的项目类型决策树,选择适当的架构。
从以下开始:
assets/boilerplate.html)根据需要查阅捆绑的参考资料:
references/preact-v10-guide.md - 全面的 Preact API 参考references/architecture-patterns.md - 高级模式和最佳实践利用 assets/component-patterns.md 获取常见的 UI 模式:
对于数据密集型应用程序:
import { useSignal } from '@preact/signals';
function parseCSV(text) {
const lines = text.trim().split('\n');
const headers = lines[0].split(',').map(h => h.trim());
return lines.slice(1).map(line => {
const values = line.split(',').map(v => v.trim());
return Object.fromEntries(headers.map((h, i) => [h, values[i]]));
});
}
function DataAnalyzer() {
const data = useSignal([]);
const handleFile = async (e) => {
const text = await e.target.files[0].text();
data.value = parseCSV(text);
};
return html`
<input type="file" accept=".csv" onChange=${handleFile} />
<div>Loaded ${data.value.length} rows</div>
`;
}
对于基于着色器的可视化:
import { useEffect, useRef } from 'preact/hooks';
function ShaderCanvas({ fragmentShader }) {
const canvasRef = useRef(null);
useEffect(() => {
const canvas = canvasRef.current;
const gl = canvas.getContext('webgl2');
// 设置 WebGL 上下文、着色器、缓冲区
// 渲染循环
return () => {
// 清理
};
}, [fragmentShader]);
return html`<canvas ref=${canvasRef} class="w-full h-full" />`;
}
// state.js
import { signal, computed } from '@preact/signals';
export const users = signal([]);
export const currentUser = signal(null);
export const isAuthenticated = computed(() => currentUser.value !== null);
// 任何组件都可以导入和使用
import { users, isAuthenticated } from './state.js';
请勿:
请务必:
references/preact-v10-guide.md:完整的 Preact v10 API 参考,涵盖导入映射、HTM 语法、与 React 的差异、Signals API、Web 组件、SSR、性能模式、Context、错误边界和常见陷阱references/architecture-patterns.md:高级模式,包括零构建架构、状态管理策略、数据获取、路由、表单、渐进增强、可访问性、性能优化、测试和安全最佳实践assets/boilerplate.html:完整的 HTML 模板,包含导入映射、Tailwind CSS 和基本的 Preact 应用结构 - 用作所有独立示例的起点assets/component-patterns.md:可重用的组件实现,用于数据网格、文件上传、搜索、模态框、标签页、通知提示和 CSV 解析<!DOCTYPE html>
<html>
<head>
<!-- 运行: bash scripts/vendor.sh -->
<script type="importmap">
{
"imports": {
"preact": "./vendor/preact.module.js",
"preact/hooks": "./vendor/hooks.module.js",
"@preact/signals-core": "./vendor/signals-core.mjs",
"@preact/signals": "./vendor/signals.mjs",
"htm": "./vendor/htm.module.js",
"htm/preact": "./vendor/htm.module.js"
}
}
</script>
</head>
<body>
<div id="app"></div>
<script type="module">
import { render } from 'preact';
import { useSignal } from '@preact/signals';
import { html } from 'htm/preact';
function App() {
const count = useSignal(0);
return html`
<button onClick=${() => count.value++}>
Count: ${count}
</button>
`;
}
render(html`<${App} />`, document.getElementById('app'));
</script>
</body>
</html>
对于处理 CSV 数据并显示交互式图表的应用程序,请参考 assets/component-patterns.md 中的 DataGrid 模式,并结合 Chart.js 等图表库或使用原生 Canvas/SVG 进行自定义可视化。
对于使用 WebGL 着色器的数学可视化,创建一个 canvas 元素,初始化 WebGL2 上下文,编译着色器,并设置渲染循环。参考 MDN WebGL 文档获取着色器设置模式。
在交付代码之前,请验证:
使用 Playwright 在 Claude.ai 容器中本地测试 Preact 应用。此工作流完全避免外部 CDN — 所有依赖项都从 registry.npmjs.org 本地托管。
# 1. 本地托管 JS 依赖
bash scripts/vendor.sh
# 2. 生成 Tailwind CSS(如果使用 Tailwind)
npm install tailwindcss@3 --save-dev
npx tailwindcss -o vendor/tailwind.css --content "*.html" --minify
# 3. 本地服务
python3 -m http.server 8765 &
# 4. 使用 Playwright 测试
python3 << 'PYEOF'
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True, args=["--no-sandbox"])
page = browser.new_page()
errors = []
page.on("console", lambda m: errors.append(m.text) if m.type == "error" else None)
page.on("pageerror", lambda e: errors.append(str(e)))
page.goto("http://localhost:8765", wait_until="networkidle")
# 验证没有控制台错误(立即捕获导入失败)
assert not errors, f"Console errors: {errors}"
# 验证应用已渲染
assert page.locator("#app").inner_html() != "", "App did not render"
# 示例:测试交互
# page.click("button")
# assert "Count: 1" in page.content()
browser.close()
print("All tests passed")
PYEOF
python3 -m http.server 就足够了 — 不需要 npm 服务器page.on("console") 和 page.on("pageerror") 进行控制台错误捕获,可以立即捕获导入失败--no-sandbox立即开始实施:
bash scripts/vendor.sh 获取本地托管的依赖项npm install tailwindcss@3 --save-dev && npx tailwindcss -o vendor/tailwind.css --content "*.html" --minifyassets/boilerplate.html 作为起点references/preact-v10-guide.md 获取 API 详细信息assets/component-patterns.md 获取常见的 UI 模式references/architecture-patterns.md 获取高级场景此技能旨在以最小的摩擦和最大的标准合规性,快速开发高质量的 Preact 应用程序。
每周安装次数
81
仓库
GitHub 星标数
113
首次出现
2026年1月25日
安全审计
安装于
github-copilot75
opencode73
codex73
gemini-cli73
cursor65
kimi-cli63
Transform Claude into a specialized Preact developer with expertise in building standards-based web applications using native-first architecture. This skill prioritizes native JavaScript, HTML, and Web APIs over external dependencies, enabling creation of performant, maintainable applications with minimal tooling overhead.
Native-First Development : Leverage ES modules, Import Maps, Web Components, native form validation, Fetch API, and built-in DOM methods before reaching for external libraries. Default to zero-build solutions with HTM and vendored ESM imports for rapid prototyping and small-to-medium applications.
Always Deliver in Artifacts : All code should be created as artifacts to enable iterative editing across sessions.
Trigger this skill when working on:
Follow this decision tree to determine the optimal architecture:
Characteristics : Quick prototype, demo, educational example, or proof of concept
Architecture :
scripts/vendor.sh)Start with : Run bash scripts/vendor.sh to fetch dependencies, then use assets/boilerplate.html as the foundation
Characteristics : Production application without existing build infrastructure, <10 components, straightforward state management
Architecture :
State Management : Use global signals for shared state, useSignal for component-local state
Characteristics : Large codebase, TypeScript requirement, multiple entry points, advanced optimizations needed
Architecture :
When to Recommend : Only after confirming team's development environment and build requirements
Approach : Match existing patterns and tooling. Analyze the codebase to determine current architecture before suggesting changes.
Always use this exact import map structure for standalone examples. Dependencies are vendored locally via scripts/vendor.sh (fetched from registry.npmjs.org):
<script type="importmap">
{
"imports": {
"preact": "./vendor/preact.module.js",
"preact/hooks": "./vendor/hooks.module.js",
"@preact/signals-core": "./vendor/signals-core.mjs",
"@preact/signals": "./vendor/signals.mjs",
"htm": "./vendor/htm.module.js",
"htm/preact": "./vendor/htm.module.js"
}
}
</script>
Critical — modular files, not standalone bundle : Do NOT use htm/preact/standalone.module.js. The standalone bundle embeds its own Preact copy, which causes @preact/signals to get a different Preact instance (it imports from 'preact' as a bare specifier). Modular files + import map = one shared Preact instance for everything.
Why vendored, not CDN : esm.sh is a pass-through to the entire npm registry — allowlisting it opens arbitrary code execution surface. registry.npmjs.org is already on the container egress allowlist and provides scoped, versioned tarballs.
Default to HTM tagged template literals unless:
When mentally converting from React/JSX patterns to HTM, apply these rules:
HTM uses JavaScript template literals. Everything that was {expression} in JSX becomes ${expression}. Component names are also expressions, hence <${Component}>.
| Pattern | JSX | HTM |
|---|---|---|
| Component tag | <Button /> | <${Button} /> |
| Component with children | <Modal>...</Modal> | <${Modal}>...</${Modal}> |
| Closing tag | </Modal> | </${Modal}> |
| Expression | {value} |
Component references need${}: The component name is a JavaScript expression
// JSX <Button onClick={handleClick}>Save</Button>
// HTM
<${Button} onClick=${handleClick}>Save</${Button}>
2. Nested templates for conditional components : When conditionally rendering components (not HTML elements), wrap in `html```
// JSX
{isOpen && <Modal title="Hello" />}
// HTM
${isOpen && html`<${Modal} title="Hello" />`}
3. No braces for spread : In HTM, spread uses ...${obj} directly
// JSX
<Input {...inputProps} />
// HTM
<${Input} ...${inputProps} />
4. class vs className : Both work in Preact, but prefer class for consistency and smaller output
| Mistake | Wrong | Correct |
|---|---|---|
Missing ${} on component | <Button> | <${Button}> |
| Wrong closing syntax | </MyComponent> | </${MyComponent}> |
| Braces instead of template | {count} | ${count} |
Use function components with:
Default : Tailwind CSS via CLI — install with npm install tailwindcss@3 --save-dev, then generate purged CSS with npx tailwindcss -o vendor/tailwind.css --content "*.html" --minify. This produces ~6KB of CSS containing only used classes. Avoid : Tailwind CDN (cdn.tailwindcss.com) — not on container egress allowlist, and loads the full 100KB+ JIT compiler. Avoid : Inline styles except for dynamic values impossible to express through utilities. Alternative : CSS modules or styled-components only when project requires scoped styling.
Before recommending any external package, verify:
Document the specific performance or capability benefits that justify any dependency inclusion.
For complex decisions involving:
Evaluate trade-offs explicitly before committing to an approach. Document reasoning in code comments.
Ensure core functionality works without JavaScript where feasible:
Clarify:
Refer to the Project Type Decision Tree above to select the appropriate architecture.
Start with:
assets/boilerplate.html)Consult bundled references as needed:
references/preact-v10-guide.md - Comprehensive Preact API referencereferences/architecture-patterns.md - Advanced patterns and best practicesLeverage assets/component-patterns.md for common UI patterns:
For data-heavy applications:
import { useSignal } from '@preact/signals';
function parseCSV(text) {
const lines = text.trim().split('\n');
const headers = lines[0].split(',').map(h => h.trim());
return lines.slice(1).map(line => {
const values = line.split(',').map(v => v.trim());
return Object.fromEntries(headers.map((h, i) => [h, values[i]]));
});
}
function DataAnalyzer() {
const data = useSignal([]);
const handleFile = async (e) => {
const text = await e.target.files[0].text();
data.value = parseCSV(text);
};
return html`
<input type="file" accept=".csv" onChange=${handleFile} />
<div>Loaded ${data.value.length} rows</div>
`;
}
For shader-based visualizations:
import { useEffect, useRef } from 'preact/hooks';
function ShaderCanvas({ fragmentShader }) {
const canvasRef = useRef(null);
useEffect(() => {
const canvas = canvasRef.current;
const gl = canvas.getContext('webgl2');
// Setup WebGL context, shaders, buffers
// Render loop
return () => {
// Cleanup
};
}, [fragmentShader]);
return html`<canvas ref=${canvasRef} class="w-full h-full" />`;
}
// state.js
import { signal, computed } from '@preact/signals';
export const users = signal([]);
export const currentUser = signal(null);
export const isAuthenticated = computed(() => currentUser.value !== null);
// Any component can import and use
import { users, isAuthenticated } from './state.js';
DO NOT :
DO :
references/preact-v10-guide.md : Complete Preact v10 API reference covering import maps, HTM syntax, React differences, Signals API, Web Components, SSR, performance patterns, Context, error boundaries, and common gotchas
references/architecture-patterns.md : Advanced patterns including zero-build architecture, state management strategies, data fetching, routing, forms, progressive enhancement, accessibility, performance optimization, testing, and security best practices
assets/boilerplate.html : Complete HTML template with import maps, Tailwind CSS, and basic Preact app structure - use as starting point for all standalone examples
assets/component-patterns.md : Reusable component implementations for data grids, file uploads, search, modals, tabs, toast notifications, and CSV parsing
<!DOCTYPE html>
<html>
<head>
<!-- Run: bash scripts/vendor.sh -->
<script type="importmap">
{
"imports": {
"preact": "./vendor/preact.module.js",
"preact/hooks": "./vendor/hooks.module.js",
"@preact/signals-core": "./vendor/signals-core.mjs",
"@preact/signals": "./vendor/signals.mjs",
"htm": "./vendor/htm.module.js",
"htm/preact": "./vendor/htm.module.js"
}
}
</script>
</head>
<body>
<div id="app"></div>
<script type="module">
import { render } from 'preact';
import { useSignal } from '@preact/signals';
import { html } from 'htm/preact';
function App() {
const count = useSignal(0);
return html`
<button onClick=${() => count.value++}>
Count: ${count}
</button>
`;
}
render(html`<${App} />`, document.getElementById('app'));
</script>
</body>
</html>
For applications processing CSV data and displaying interactive charts, reference the DataGrid pattern in assets/component-patterns.md and combine with a charting library like Chart.js or use native Canvas/SVG for custom visualizations.
For mathematical visualizations using WebGL shaders, create a canvas element, initialize WebGL2 context, compile shaders, and set up a render loop. Reference MDN WebGL documentation for shader setup patterns.
Before delivering code, verify:
Test Preact apps locally in Claude.ai containers using Playwright. This workflow avoids external CDNs entirely — all dependencies are vendored from registry.npmjs.org.
# 1. Vendor JS dependencies
bash scripts/vendor.sh
# 2. Generate Tailwind CSS (if using Tailwind)
npm install tailwindcss@3 --save-dev
npx tailwindcss -o vendor/tailwind.css --content "*.html" --minify
# 3. Serve locally
python3 -m http.server 8765 &
# 4. Test with Playwright
python3 << 'PYEOF'
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True, args=["--no-sandbox"])
page = browser.new_page()
errors = []
page.on("console", lambda m: errors.append(m.text) if m.type == "error" else None)
page.on("pageerror", lambda e: errors.append(str(e)))
page.goto("http://localhost:8765", wait_until="networkidle")
# Verify no console errors (catches import failures immediately)
assert not errors, f"Console errors: {errors}"
# Verify app rendered
assert page.locator("#app").inner_html() != "", "App did not render"
# Example: test interaction
# page.click("button")
# assert "Count: 1" in page.content()
browser.close()
print("All tests passed")
PYEOF
python3 -m http.server is sufficient — no npm server neededpage.on("console") and page.on("pageerror") catches import failures immediately--no-sandbox is required in container environmentsFor immediate implementation:
bash scripts/vendor.sh to fetch vendored dependenciesnpm install tailwindcss@3 --save-dev && npx tailwindcss -o vendor/tailwind.css --content "*.html" --minifyassets/boilerplate.html as the starting pointreferences/preact-v10-guide.md for API detailsassets/component-patterns.md for common UI patternsreferences/architecture-patterns.md for advanced scenariosThe skill is designed to enable rapid development of high-quality Preact applications with minimal friction and maximum standards compliance.
Weekly Installs
81
Repository
GitHub Stars
113
First Seen
Jan 25, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
github-copilot75
opencode73
codex73
gemini-cli73
cursor65
kimi-cli63
Vue 3 调试指南:解决响应式、计算属性与监听器常见错误
11,900 周安装
${value} |
| Props | prop={val} | prop=${val} |
| Spread props | {...obj} | ...${obj} |
| Event handler | onClick={fn} | onClick=${fn} |
| Conditional | {show && <X />} | ${show && html\<${X} />} |
| Ternary | {a ? <X /> : <Y />} | ${a ? html\<${X} /> : html<${Y} />} |
| Map | {items.map(i => <Li />)} | ${items.map(i => html\...)} |
| Spread with braces | {...props} | ...${props} |
| Missing html wrapper in conditional | ${show && <${X} />} | ${show && html\<${X} />} |