Day-to-day pattern development best practices. Use when actively developing patterns. Covers incremental development, commits, communication guidelines, and general development workflow.
./scripts/cf WrapperCRITICAL: Always use ./scripts/cf for all cf commands:
# ✅ CORRECT - Use the wrapper from community-patterns
./scripts/cf dev patterns/$GITHUB_USER/pattern.tsx --no-run
# ❌ WRONG - Don't cd to labs and use deno task cf
cd ~/Code/labs
deno task cf dev ../community-patterns/patterns/$GITHUB_USER/pattern.tsx --no-run
Why the wrapper exists:
$INIT_CWD to preserve path resolution from community-patternsBash(./scripts/cf:*) - no prompts!patterns/$GITHUB_USER/foo.tsxFor detailed deployment commands, see the deployment skill.
The labs repo contains all framework documentation. Start with the README for a guided reading order:
../labs/docs/common/README.md
Essential docs to read before writing patterns:
../labs/docs/common/PATTERNS.md - Main tutorial, start here../labs/docs/common/CELLS_AND_REACTIVITY.md - Core reactive model../labs/docs/common/COMPONENTS.md - UI components reference../labs/docs/common/TYPES_AND_SCHEMAS.md - Type systemWhen stuck or debugging:
../labs/docs/common/DEBUGGING.md - Troubleshooting errors../labs/docs/common/PATTERN_DEV_DEPLOY.md - Build/deploy workflowWhen to read docs:
When testing patterns, use the claude- prefix with descriptive names:
Format: claude-<pattern-name>-<MMDD>-<counter>
Examples:
claude-counter-1130-1
claude-prompt-injection-tracker-1130-2
claude-gmail-importer-1130-1
claude-shopping-list-1201-1
Pattern:
claude- prefix identifies AI-created test spaces<pattern-name> - the pattern being tested (use hyphens, keep concise)<MMDD> - today's date (month-day)<counter> - increment when deploying multiple versions same dayImportant:
Don't:
Do:
Commit frequently as you make progress:
Example commit flow:
# After getting basic pattern working
git add patterns/$GITHUB_USER/WIP/my-pattern.tsx
git commit -m "Add basic counter pattern structure"
# After adding features
git commit -m "Add increment/decrement buttons"
# After testing
git commit -m "Test counter pattern in browser"
You can restart both dev servers whenever needed:
# Stop both servers
pkill -f "packages/toolshed.*deno task dev"
pkill -f "packages/shell.*deno task dev-local"
# Start both servers
cd ~/Code/labs/packages/toolshed && deno task dev > /tmp/toolshed-dev.log 2>&1 &
cd ~/Code/labs/packages/shell && deno task dev-local > /tmp/shell-dev.log 2>&1 &
sleep 3
echo "Both servers restarted"
When to restart:
Both servers run in background - session can continue while they start
Check server logs if issues occur:
/tmp/toolshed-dev.log/tmp/shell-dev.log<cf-cell-context><cf-cell-context> is a debugging tool that annotates regions of the page with
cell data. It's better than sprinkling console.log everywhere because
inspection is conditional—users can watch and unwatch values on demand.
When to use (sparingly, typically 1-2 per pattern):
console.logUsage:
<cf-cell-context $cell={result} label="Calculation Result">
<div>{result.value}</div>
</cf-cell-context>;
API:
$cell - The Cell to associate with this regionlabel - Human-readable name shown in the toolbar (optional)inline - Display as inline-block instead of block (optional)How to inspect: Hold Alt and hover over a cell context region to see the debugging toolbar:
globalThis.$cell to the cell
(like Chrome's $0 for elements)When NOT to use:
Note: Every [UI] render is automatically wrapped in cf-cell-context, so
you get top-level piece debugging for free.
❌ NEVER commit or push to labs - it's READ-ONLY ✅ If you accidentally
changed something: git restore . ✅ To update labs: Pull updates and
restart dev server automatically
⚠️ ONLY delete with explicit user confirmation
Location: ~/Code/labs/packages/toolshed/cache/memory/*.sqlite
WARNING: Deleting these files wipes out ALL local spaces permanently
When this might be needed:
Command:
rm -rf ~/Code/labs/packages/toolshed/cache/memory/*.sqlite
NEVER do this without explicit user permission
When one pattern needs to instantiate another (like page-creator launching new
patterns), use the optional defaults idiom with field?: Default<T, V>.
Without defaults, callers must provide ALL Input fields:
// ❌ FRAGILE - Must list every field, breaks when Input changes
navigateTo(Person({
displayName: "",
givenName: "",
familyName: "",
// ... 10 more fields that must be kept in sync
}));
Add ? to Input fields that have Default<T, V>:
// In person.tsx
type Input = {
displayName?: Default<string, "">; // Optional for callers
givenName?: Default<string, "">; // Optional for callers
birthday?: Default<string, "">; // Optional for callers
emails?: Default<EmailEntry[], []>; // Optional for callers
};
export default pattern<Input, Output>(({ displayName, givenName, ... }) => {
// Inside the pattern body, ALL fields are guaranteed present
// Required<Input> removes the `?`, Default<> provides values
return { ... };
});
Type Flow:
Input has field?: Default<T, V> - optional for callersPatternFunction<Input, Output> wraps internal type with Required<Input>?)StripCell<Input> which preserves the ?Result:
Pattern({}) - all defaults appliedPattern({ title: "Custom" })// In page-creator.tsx
import Person from "./person.tsx";
const createPersonHandler = handler<void, void>(() => {
return navigateTo(Person({})); // Clean! All defaults applied
});
// Or with overrides:
navigateTo(Person({ givenName: "Alice" }));
? to EVERY field with Default<> - this makes it optional for
callers?){}IMPORTANT: When creating or significantly modifying patterns, update
patterns/$GITHUB_USER/README.md.
The README serves as an index of all patterns with descriptions of what they do and what's interesting about them.
When to update:
What to include:
Example entry:
#### `my-pattern.tsx`
Brief description of what it does.
**Interesting features:**
- Notable technique or framework feature demonstrated
- Unique functionality worth highlighting
For specific workflows, use these skills:
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer