Agent Skills › MrModest/reisenotiz

MrModest/reisenotiz

GitHub

为Reisenotiz旅行笔记PWA生成符合品牌规范的界面和资产。提供设计指南、颜色、字体及UI组件,支持输出静态HTML原型或生产代码,并充当专家设计师协助需求沟通。

2 skills 69

Install All Skills

npx skills add MrModest/reisenotiz --all -g -y
More Options

List skills in collection

npx skills add MrModest/reisenotiz --list

Skills in Collection (2)

为Reisenotiz旅行笔记PWA生成符合品牌规范的界面和资产。提供设计指南、颜色、字体及UI组件,支持输出静态HTML原型或生产代码,并充当专家设计师协助需求沟通。
需要生成Reisenotiz品牌风格的UI界面或视觉资产 创建旅行笔记应用的静态HTML原型或Mockup 进行基于Reisenotiz设计规范的生产级前端开发
.claude/skills/reisenotiz-design/SKILL.md
npx skills add MrModest/reisenotiz --skill reisenotiz-design -g -y
SKILL.md
Frontmatter
{
    "name": "reisenotiz-design",
    "description": "Use this skill to generate well-branded interfaces and assets for Reisenotiz, a self-hosted offline-first travel notes PWA. Contains essential design guidelines, colors, type, fonts, assets, and UI kit components for prototyping.",
    "user-invocable": true
}

Read the README.md file within this skill, and explore the other available files. If creating visual artifacts (slides, mocks, throwaway prototypes, etc), copy assets out and create static HTML files for the user to view. If working on production code, you can copy assets and read the rules here to become an expert in designing with this brand. If the user invokes this skill without any other guidance, ask them what they want to build or design, ask some questions, and act as an expert designer who outputs HTML artifacts or production code, depending on the need.

提供Automerge在React项目中的核心知识,包括useDocument/useRepo钩子、原地变更语义及updateText协作文本用法。适用于编写、调试或审查Automerge代码、同步数据、处理CRDT行为及测试场景。
编写、调试或审查Automerge代码 询问如何使用Automerge同步数据 提及useDocument、useRepo或changeDoc 开发同步引擎或讨论CRDT行为 为Automerge后端存储编写测试
.claude/skills/automerge/SKILL.md
npx skills add MrModest/reisenotiz --skill automerge -g -y
SKILL.md
Frontmatter
{
    "name": "automerge",
    "description": "Fresh Automerge knowledge for this project — React hooks (useDocument, useRepo, RepoContext), mutation semantics, updateText for collaborative text, testing patterns, and common gotchas. Use this skill whenever the user is writing, debugging, or reviewing Automerge code, asks how to sync data with Automerge, mentions useDocument\/useRepo\/changeDoc, is working on the sync engine, asks about CRDT behavior, or is writing tests for Automerge-backed stores. Always load this skill when touching apps\/frontend\/src\/store\/automerge\/ or apps\/frontend\/src\/contexts\/sync*."
}

Automerge Knowledge Reference

Read references/automerge-react.md for full detail. Below is the critical-path summary.


Core React Hooks

useDocument<T>(docUrl, options?)

Primary hook. Returns [doc, changeDoc] — reactive snapshot + mutation function.

const [doc, changeDoc] = useDocument<TaskList>(docUrl, { suspense: true });
  • doc is undefined until loaded. With suspense: true, component suspends instead.
  • changeDoc callback receives a mutable draft — mutations inside it are the ONLY valid way to write.

useRepo()

Returns the Repo instance from context. Use to create/find/delete documents imperatively.

const repo = useRepo();
const handle = repo.create<MyType>({ ...initialData });

RepoContext

Wrap your app tree once. All useDocument/useRepo calls inside read from it.

<RepoContext.Provider value={repo}>
  <App />
</RepoContext.Provider>

Mutation Semantics — the #1 gotcha

Automerge tracks operations, not snapshots. You MUST mutate in-place inside changeDoc. Never spread or replace.

// CORRECT — targeted mutation, records the operation
changeDoc((d) => {
  d.tasks[i].done = !d.tasks[i].done;
});

// WRONG — replaces the entire array, destroys merge history
changeDoc((d) => ({
  ...d,
  tasks: d.tasks.map((t, idx) => idx === i ? { ...t, done: !t.done } : t),
}));

Any mutation outside changeDoc is invisible to Automerge and will not sync.


Collaborative Text — updateText

Direct string assignment replaces the whole string (poor merge). Use updateText for any user-editable text:

import { updateText } from "@automerge/react";

changeDoc((d) => {
  updateText(d, ["notes", "body"], e.target.value);
});

updateText diffs the old and new strings and emits minimal splice operations, enabling proper multi-user merge.

Automerge v3+: no Text class — all collaborative strings are plain string. Use updateText or Automerge.splice.


Testing Patterns

See references/automerge-react.md#testing for full patterns.

Key principles:

  • No mocks for Automerge itself — use a real in-memory Repo with new Repo({ network: [] }) (no storage adapter either — IndexedDB unavailable in jsdom).
  • Wrap test components in <RepoContext.Provider value={repo}>.
  • Create documents via repo.create(initialData) before the hook renders, pass the URL to hooks.
  • Multi-peer tests: instantiate two Repo objects, connect via MessageChannelNetworkAdapter.
  • Offline scenarios: disconnect the adapter, mutate, reconnect — verify sync after.
  • Assert on doc snapshots not on internal CRDT state: handle.doc() synchronously after a change.

Critical vitest setup (blockers if missing)

vite-plugin-wasm + vite-plugin-top-level-await — Automerge ships a WASM binary. Without these plugins the module fails to load in jsdom:

// vitest.config.ts
import wasm from 'vite-plugin-wasm'
import topLevelAwait from 'vite-plugin-top-level-await'
export default defineConfig({
  plugins: [wasm(), topLevelAwait(), react()],
  test: { environment: 'jsdom', setupFiles: ['./vitest.setup.ts'] },
})

IS_REACT_ACT_ENVIRONMENT — React 19 requires this so act() flushes effects:

// vitest.setup.ts
globalThis.IS_REACT_ACT_ENVIRONMENT = true

await act() — every mutation must be wrapped; useDocument uses useSyncExternalStore so changes schedule async re-renders:

await act(async () => {
  result.current.addItem({ title: 'foo' })
})
// now result.current reflects updated state

Reading raw doc state — access the document directly from the repo's handle map to assert on CRDT structure independent of hook state:

import { interpretAsDocumentId } from '@automerge/react'
const handle = repo.handles[interpretAsDocumentId(url)]
const doc = handle.doc() // synchronous after change applied

Key Gotchas (quick-reference)

# Gotcha Fix
1 Immutability semantics inverted Always mutate inside changeDoc
2 useDocument returns undefined until loaded Guard with if (!doc) return null or use suspense: true
3 Schema init on two devices = incompatible docs Sync or share initial state before independent writes
4 Text class removed in v3 Use plain string + updateText/Automerge.splice
5 Array spread kills merge Use push, unshift, or indexed assignment
6 Root doc stored in localStorage Losing the key = losing access (docs still in IndexedDB)
7 Full history retained, no GC yet Monitor memory on high-edit-count docs
8 Multiple adapters are independent No prioritization — both receive all changes
9 Fine-grained docs = overhead Consolidate if sync overhead grows
10 Merge is automatic, no conflicts Trust the CRDT; no manual conflict resolution needed
11 Automerge WASM breaks vitest without plugins Add vite-plugin-wasm + vite-plugin-top-level-await to vitest config
12 React 19 act() doesn't flush without flag Set globalThis.IS_REACT_ACT_ENVIRONMENT = true in vitest.setup.ts

Read references/automerge-react.md for extended examples, network adapters, and persistence setup.

ホーム - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-07-19 23:41
浙ICP备14020137号-1 $お客様$