Start with the shared critique guidance in:
docs/common/ai/pattern-critique-guide.md
Read that guide first. It is the canonical reference.
Then use the detailed references already maintained in the repo for:
docs/development/debugging/README.mddocs/development/debugging/gotchas/docs/common/components/COMPONENTS.mddocs/common/capabilities/llm.md- LLM integration
Quick Patterns
Correct action() Usage (Default Choice)
// action() inside pattern body - closes over pattern variables
export default pattern<MyInput, MyOutput>(({ items, title }) => {
const menuOpen = Writable.of(false);
// Action closes over menuOpen - no binding needed
const toggleMenu = action(() => menuOpen.set(!menuOpen.get()));
// Action closes over items - no binding needed
const addItem = action(() => items.push({ title: title.get() }));
return {
[UI]: (
<>
<ct-button onClick={toggleMenu}>Menu</ct-button>
<ct-button onClick={addItem}>Add</ct-button>
</>
),
items,
};
});Correct handler() Usage (Only for Multi-Binding)
// handler() at module scope - will be bound with different items in .map()
const deleteItem = handler<
void,
{ item: Writable<Item>; items: Writable<Item[]> }
>(
(_, { item, items }) => {
const list = items.get();
items.set(list.filter((i) => i !== item));
},
);
export default pattern<MyInput, MyOutput>(({ items }) => ({
[UI]: (
<ul>
{items.map((item) => (
<li>
{item.name}
{/* Each item gets its own binding */}
<ct-button onClick={deleteItem({ item, items })}>Delete</ct-button>
</li>
))}
</ul>
),
items,
}));Correct Reactive [NAME]
export default pattern<Input>(({ deck }) => ({
[NAME]: computed(() => `Study: ${deck.name}`),
// ...
}));Correct Conditional Rendering
// Both are valid - ternaries auto-transform to ifElse()
return <>{showDetails ? <div>Details content</div> : null}</>;
return <>{ifElse(showDetails, <div>Details content</div>, null)}</>;Correct Style Syntax
<div style={{ display: "flex", gap: "1rem" }}>
<ct-vstack style="flex: 1; padding: 1rem;">
Content
</ct-vstack>
</div>;