claude-toolkit 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/LICENSE +21 -0
  3. package/README.md +126 -0
  4. package/bin/cli.ts +112 -0
  5. package/core/agents/ct-code-reviewer.md +123 -0
  6. package/core/agents/ct-github-workflow.md +137 -0
  7. package/core/commands/ct/code-quality.md +59 -0
  8. package/core/commands/ct/onboard.md +84 -0
  9. package/core/commands/ct/pr-review.md +104 -0
  10. package/core/commands/ct/pr-summary.md +59 -0
  11. package/core/commands/ct/proto-check.md +74 -0
  12. package/core/commands/ct/ticket.md +71 -0
  13. package/core/hooks/skill-eval.js +381 -0
  14. package/core/hooks/skill-eval.sh +35 -0
  15. package/core/hooks/skill-rules.schema.json +112 -0
  16. package/core/skills/systematic-debugging/SKILL.md +44 -0
  17. package/core/skills/testing-patterns/SKILL.md +52 -0
  18. package/core/skills/typescript-conventions/SKILL.md +57 -0
  19. package/core/skills/verification-before-completion/SKILL.md +42 -0
  20. package/docs/README.md +49 -0
  21. package/docs/agents/code-reviewer.md +76 -0
  22. package/docs/agents/github-workflow.md +98 -0
  23. package/docs/best-practices/solidjs/README.md +43 -0
  24. package/docs/best-practices/solidjs/anti-patterns.md +166 -0
  25. package/docs/best-practices/solidjs/component-patterns.md +131 -0
  26. package/docs/best-practices/solidjs/context-and-global-state.md +131 -0
  27. package/docs/best-practices/solidjs/control-flow.md +124 -0
  28. package/docs/best-practices/solidjs/data-fetching.md +205 -0
  29. package/docs/best-practices/solidjs/effects-and-lifecycle.md +113 -0
  30. package/docs/best-practices/solidjs/performance.md +100 -0
  31. package/docs/best-practices/solidjs/props-patterns.md +100 -0
  32. package/docs/best-practices/solidjs/reactivity-model.md +104 -0
  33. package/docs/best-practices/solidjs/signals-and-state.md +78 -0
  34. package/docs/best-practices/solidjs/stores-and-nested-state.md +111 -0
  35. package/docs/best-practices/solidjs/typescript-integration.md +186 -0
  36. package/docs/best-practices/typescript/README.md +45 -0
  37. package/docs/best-practices/typescript/any-and-unknown.md +73 -0
  38. package/docs/best-practices/typescript/deriving-vs-decoupling.md +83 -0
  39. package/docs/best-practices/typescript/discriminated-unions.md +75 -0
  40. package/docs/best-practices/typescript/enums-alternatives.md +72 -0
  41. package/docs/best-practices/typescript/essential-patterns.md +119 -0
  42. package/docs/best-practices/typescript/generics-patterns.md +105 -0
  43. package/docs/best-practices/typescript/micro-opinions.md +87 -0
  44. package/docs/best-practices/typescript/runtime-validation.md +62 -0
  45. package/docs/best-practices/typescript/satisfies-operator.md +100 -0
  46. package/docs/best-practices/typescript/tsconfig-cheat-sheet.md +129 -0
  47. package/docs/best-practices/typescript/type-organization.md +64 -0
  48. package/docs/best-practices/typescript/type-vs-interface.md +80 -0
  49. package/docs/commands/code-quality.md +42 -0
  50. package/docs/commands/onboard.md +72 -0
  51. package/docs/commands/pr-review.md +102 -0
  52. package/docs/commands/pr-summary.md +50 -0
  53. package/docs/commands/proto-check.md +59 -0
  54. package/docs/commands/ticket.md +56 -0
  55. package/docs/skills/systematic-debugging.md +70 -0
  56. package/docs/skills/testing-patterns.md +89 -0
  57. package/docs/skills/typescript-conventions.md +137 -0
  58. package/docs/skills/verification-before-completion.md +91 -0
  59. package/docs/stacks/cloudflare-d1-kv.md +110 -0
  60. package/docs/stacks/i18n-typesafe.md +141 -0
  61. package/docs/stacks/protobuf-contracts.md +85 -0
  62. package/docs/stacks/rust-wasm-patterns.md +106 -0
  63. package/docs/stacks/solidjs-patterns.md +110 -0
  64. package/docs/stacks/vanilla-extract-patterns.md +115 -0
  65. package/package.json +58 -0
  66. package/src/generator.ts +317 -0
  67. package/src/index.ts +30 -0
  68. package/src/types.ts +85 -0
  69. package/src/utils.ts +53 -0
  70. package/stacks/cloudflare/skills/cloudflare-d1-kv/SKILL.md +84 -0
  71. package/stacks/cloudflare/stack.json +26 -0
  72. package/stacks/i18n-typesafe/skills/i18n-typesafe/SKILL.md +64 -0
  73. package/stacks/i18n-typesafe/stack.json +25 -0
  74. package/stacks/protobuf/skills/protobuf-contracts/SKILL.md +78 -0
  75. package/stacks/protobuf/stack.json +25 -0
  76. package/stacks/rust-wasm/skills/rust-wasm-patterns/SKILL.md +76 -0
  77. package/stacks/rust-wasm/stack.json +26 -0
  78. package/stacks/solidjs/skills/solidjs-patterns/SKILL.md +66 -0
  79. package/stacks/solidjs/stack.json +52 -0
  80. package/stacks/vanilla-extract/skills/vanilla-extract-patterns/SKILL.md +76 -0
  81. package/stacks/vanilla-extract/stack.json +40 -0
  82. package/templates/claude-toolkit.config.ts +34 -0
  83. package/templates/configs/biome.base.json +35 -0
  84. package/templates/configs/tsconfig.base.json +16 -0
  85. package/templates/skill-rules.base.json +98 -0
@@ -0,0 +1,166 @@
1
+ # Anti-Patterns
2
+
3
+ > Common SolidJS mistakes sourced from the [SolidJS documentation](https://docs.solidjs.com/), community guides, and [Ryan Carniato's articles](https://dev.to/ryansolid).
4
+
5
+ ## 1. Destructuring Props
6
+
7
+ The single most common Solid mistake. Props use getters for reactivity — destructuring extracts the value once.
8
+
9
+ ```typescript
10
+ // BROKEN
11
+ const Card = ({ title, count }) => <div>{title}: {count}</div>;
12
+
13
+ // FIXED
14
+ const Card = (props) => <div>{props.title}: {props.count}</div>;
15
+ ```
16
+
17
+ If you need to separate props, use `splitProps`. If you need defaults, use `mergeProps`.
18
+
19
+ ## 2. Forgetting to Call Signals
20
+
21
+ Signals are getter functions. Forgetting `()` passes the function itself, not the value.
22
+
23
+ ```typescript
24
+ // BROKEN — passes the function, not the value
25
+ <span>{count}</span>
26
+
27
+ // FIXED
28
+ <span>{count()}</span>
29
+ ```
30
+
31
+ ## 3. Reading Signals Outside Reactive Context
32
+
33
+ The component body runs once. Reading a signal at the top level captures the initial value — it never updates.
34
+
35
+ ```typescript
36
+ // BROKEN — layout is assigned once, never reactive
37
+ const MyComponent = (props) => {
38
+ const layout = props.wide ? "grid" : "list"; // Evaluated once
39
+ return <div class={layout}>...</div>;
40
+ };
41
+
42
+ // FIXED — read in JSX (reactive context)
43
+ const MyComponent = (props) => {
44
+ return <div class={props.wide ? "grid" : "list"}>...</div>;
45
+ };
46
+
47
+ // Also fixed — wrap in a function
48
+ const MyComponent = (props) => {
49
+ const layout = () => props.wide ? "grid" : "list";
50
+ return <div class={layout()}>...</div>;
51
+ };
52
+ ```
53
+
54
+ ## 4. Using Effects to Sync State
55
+
56
+ Effects that set state from other state create ordering problems and glitchy intermediate renders.
57
+
58
+ ```typescript
59
+ // BROKEN — effect-based synchronization
60
+ const [count, setCount] = createSignal(0);
61
+ const [doubled, setDoubled] = createSignal(0);
62
+ createEffect(() => setDoubled(count() * 2));
63
+
64
+ // FIXED — derivation
65
+ const doubled = createMemo(() => count() * 2);
66
+ // or: const doubled = () => count() * 2;
67
+ ```
68
+
69
+ **Rule:** If a value can be computed from reactive sources, derive it.
70
+
71
+ ## 5. Using Effects for Data Fetching
72
+
73
+ Effects run after render, have no built-in loading/error states, and create race conditions on dependency changes.
74
+
75
+ ```typescript
76
+ // BROKEN
77
+ createEffect(async () => {
78
+ const res = await fetch(`/api/${id()}`);
79
+ setData(await res.json());
80
+ });
81
+
82
+ // FIXED
83
+ const [data] = createResource(id, fetchData);
84
+ ```
85
+
86
+ `createResource` integrates with Suspense, handles loading/error, and manages race conditions.
87
+
88
+ ## 6. Using `.map()` Instead of `<For>`
89
+
90
+ JavaScript `.map()` recreates all DOM nodes whenever the array signal changes. `<For>` tracks items by reference and only updates what changed.
91
+
92
+ ```typescript
93
+ // INEFFICIENT — full DOM rebuild on any array change
94
+ <ul>{items().map(item => <li>{item.name}</li>)}</ul>
95
+
96
+ // CORRECT — granular updates
97
+ <ul><For each={items()}>{(item) => <li>{item.name}</li>}</For></ul>
98
+ ```
99
+
100
+ ## 7. Using `&&` for Conditional Rendering
101
+
102
+ JavaScript short-circuit evaluation doesn't give Solid the boundaries it needs to optimize.
103
+
104
+ ```typescript
105
+ // SUBOPTIMAL — no Solid optimization
106
+ {isVisible() && <Modal />}
107
+
108
+ // CORRECT — Solid can optimize the boundary
109
+ <Show when={isVisible()}><Modal /></Show>
110
+ ```
111
+
112
+ ## 8. Mutating Store State Directly
113
+
114
+ Stores use proxies. Direct mutation bypasses the reactive system.
115
+
116
+ ```typescript
117
+ // BROKEN — Solid doesn't see this change
118
+ state.tasks[0].completed = true;
119
+
120
+ // FIXED — go through setState
121
+ setState("tasks", 0, "completed", true);
122
+ ```
123
+
124
+ ## 9. Creating Unnecessary Reactivity
125
+
126
+ Not everything needs to be a signal. Static configuration, constants, and values that never change don't benefit from reactivity.
127
+
128
+ ```typescript
129
+ // UNNECESSARY
130
+ const [apiUrl] = createSignal("https://api.example.com");
131
+
132
+ // JUST USE A CONSTANT
133
+ const API_URL = "https://api.example.com";
134
+ ```
135
+
136
+ ## 10. Missing `onCleanup`
137
+
138
+ Effects that create subscriptions, timers, or event listeners without cleanup cause memory leaks.
139
+
140
+ ```typescript
141
+ // LEAKS — interval is never cleared
142
+ createEffect(() => {
143
+ setInterval(() => tick(), 1000);
144
+ });
145
+
146
+ // FIXED
147
+ createEffect(() => {
148
+ const id = setInterval(() => tick(), 1000);
149
+ onCleanup(() => clearInterval(id));
150
+ });
151
+ ```
152
+
153
+ ## Quick Reference
154
+
155
+ | Mistake | Fix |
156
+ |---|---|
157
+ | Destructure props | Use `props.x` directly |
158
+ | `count` without `()` | Always call signal getters |
159
+ | Signal read at top level | Read in JSX or wrap in `() =>` |
160
+ | Effect sets state from state | Use `createMemo` |
161
+ | Effect fetches data | Use `createResource` |
162
+ | `.map()` for lists | Use `<For>` |
163
+ | `&&` for conditionals | Use `<Show>` |
164
+ | Direct store mutation | Use `setState()` |
165
+ | Signal for constants | Use a plain variable |
166
+ | No `onCleanup` | Always clean up side effects |
@@ -0,0 +1,131 @@
1
+ # Component Patterns
2
+
3
+ > Sources: [TypeScript](https://docs.solidjs.com/configuration/typescript), [Props](https://docs.solidjs.com/concepts/components/props) — SolidJS Docs
4
+
5
+ ## Component Type Hierarchy
6
+
7
+ SolidJS provides four component types for TypeScript:
8
+
9
+ ```typescript
10
+ import type { Component, ParentComponent, FlowComponent, VoidComponent } from "solid-js";
11
+ ```
12
+
13
+ | Type | Children | Use Case |
14
+ |---|---|---|
15
+ | `Component<P>` | No opinion | Base type, generic components |
16
+ | `ParentComponent<P>` | Optional `JSX.Element` | Components that accept children |
17
+ | `FlowComponent<P, C>` | Required, typed | Control flow (`Show`, `For`-like) |
18
+ | `VoidComponent<P>` | Forbidden | Leaf components (icons, inputs) |
19
+
20
+ ```typescript
21
+ const Card: ParentComponent<{ title: string }> = (props) => {
22
+ return (
23
+ <div class="card">
24
+ <h2>{props.title}</h2>
25
+ {props.children}
26
+ </div>
27
+ );
28
+ };
29
+
30
+ const Icon: VoidComponent<{ name: string }> = (props) => {
31
+ return <svg class={`icon-${props.name}`} />;
32
+ };
33
+ ```
34
+
35
+ ## Generic Components
36
+
37
+ The `Component` types cannot be used for generic components. Use function declarations instead:
38
+
39
+ ```typescript
40
+ function List<T>(props: { items: T[]; render: (item: T) => JSX.Element }): JSX.Element {
41
+ return <For each={props.items}>{props.render}</For>;
42
+ }
43
+
44
+ // Usage — T is inferred
45
+ <List items={users()} render={(user) => <span>{user.name}</span>} />
46
+ ```
47
+
48
+ ## Refs
49
+
50
+ Refs may be `undefined` before mount. Always account for this:
51
+
52
+ ```typescript
53
+ const MyComponent: VoidComponent = () => {
54
+ let inputRef: HTMLInputElement | undefined;
55
+
56
+ onMount(() => {
57
+ inputRef?.focus(); // Safe access after mount
58
+ });
59
+
60
+ return <input ref={inputRef} />;
61
+ };
62
+ ```
63
+
64
+ Alternatively, use the definite assignment assertion in JSX: `ref={inputRef!}`.
65
+
66
+ ## Composition Over Inheritance
67
+
68
+ Solid components are plain functions — compose them by passing components as props or using children:
69
+
70
+ ```typescript
71
+ const Layout: ParentComponent<{ sidebar: JSX.Element }> = (props) => {
72
+ return (
73
+ <div class="layout">
74
+ <aside>{props.sidebar}</aside>
75
+ <main>{props.children}</main>
76
+ </div>
77
+ );
78
+ };
79
+
80
+ <Layout sidebar={<Navigation />}>
81
+ <PageContent />
82
+ </Layout>
83
+ ```
84
+
85
+ ## Event Handling
86
+
87
+ Inline event handlers get automatic type inference. For extracted handlers, use `JSX.EventHandler`:
88
+
89
+ ```typescript
90
+ const onInput: JSX.EventHandler<HTMLInputElement, InputEvent> = (event) => {
91
+ // event.currentTarget is HTMLInputElement
92
+ // event.target may be any element within
93
+ console.log(event.currentTarget.value);
94
+ };
95
+ ```
96
+
97
+ ### Custom Events
98
+
99
+ Extend the JSX namespace:
100
+
101
+ ```typescript
102
+ declare module "solid-js" {
103
+ namespace JSX {
104
+ interface CustomEvents {
105
+ customClick: CustomEvent<{ id: string }>;
106
+ }
107
+ }
108
+ }
109
+ ```
110
+
111
+ ## Custom Directives
112
+
113
+ Register with `use:` prefix. Declare via the JSX namespace:
114
+
115
+ ```typescript
116
+ declare module "solid-js" {
117
+ namespace JSX {
118
+ interface Directives {
119
+ tooltip: string;
120
+ }
121
+ }
122
+ }
123
+
124
+ function tooltip(el: HTMLElement, accessor: () => string) {
125
+ // Set up tooltip on el using accessor()
126
+ onCleanup(() => { /* teardown */ });
127
+ }
128
+
129
+ // Usage
130
+ <div use:tooltip={"Hello!"} />
131
+ ```
@@ -0,0 +1,131 @@
1
+ # Context & Global State
2
+
3
+ > Sources: [Context](https://docs.solidjs.com/concepts/context), [Complex State Management](https://docs.solidjs.com/guides/complex-state-management) — SolidJS Docs
4
+
5
+ ## When to Use Context
6
+
7
+ Context solves **prop drilling** — passing state through many component layers that don't use it themselves. Use it for:
8
+
9
+ - Theme / appearance settings
10
+ - Authentication state
11
+ - Feature flags
12
+ - Any state needed by many descendants
13
+
14
+ **When NOT to use context:**
15
+ - If only a few components need the data, pass props directly
16
+ - If you can restructure the component tree to avoid drilling
17
+ - For truly global singletons, a module-level signal may be simpler
18
+
19
+ ## Basic Context Pattern
20
+
21
+ ```typescript
22
+ import { createContext, useContext } from "solid-js";
23
+ import { createStore } from "solid-js/store";
24
+
25
+ // 1. Create context
26
+ const CounterContext = createContext<{
27
+ count: number;
28
+ increment: () => void;
29
+ }>();
30
+
31
+ // 2. Create provider component
32
+ function CounterProvider(props: ParentProps) {
33
+ const [state, setState] = createStore({ count: 0 });
34
+ const value = {
35
+ get count() { return state.count; },
36
+ increment() { setState("count", c => c + 1); },
37
+ };
38
+
39
+ return (
40
+ <CounterContext.Provider value={value}>
41
+ {props.children}
42
+ </CounterContext.Provider>
43
+ );
44
+ }
45
+
46
+ // 3. Consume with useContext
47
+ function Counter() {
48
+ const ctx = useContext(CounterContext);
49
+ return <button onClick={ctx.increment}>{ctx.count}</button>;
50
+ }
51
+ ```
52
+
53
+ ## Safe useContext with Error Throwing
54
+
55
+ `useContext` returns `undefined` when no provider exists above. Create a custom hook that throws a helpful error:
56
+
57
+ ```typescript
58
+ function useCounter() {
59
+ const ctx = useContext(CounterContext);
60
+ if (!ctx) {
61
+ throw new Error("useCounter must be used within a CounterProvider");
62
+ }
63
+ return ctx;
64
+ }
65
+ ```
66
+
67
+ This also **narrows the TypeScript type** — no more `| undefined`.
68
+
69
+ ## Context + Store Pattern (Recommended)
70
+
71
+ Combine `createStore` with context for scalable state. Stores give you fine-grained reactivity; context distributes it without prop drilling.
72
+
73
+ ```typescript
74
+ function createTaskStore() {
75
+ const [state, setState] = createStore({
76
+ tasks: [] as Task[],
77
+ filter: "all" as "all" | "active" | "completed",
78
+ });
79
+
80
+ return {
81
+ get tasks() { return state.tasks; },
82
+ get filter() { return state.filter; },
83
+ addTask(text: string) {
84
+ setState("tasks", state.tasks.length, {
85
+ id: crypto.randomUUID(),
86
+ text,
87
+ completed: false,
88
+ });
89
+ },
90
+ toggleTask(id: string) {
91
+ setState("tasks", t => t.id === id, "completed", c => !c);
92
+ },
93
+ setFilter(filter: "all" | "active" | "completed") {
94
+ setState("filter", filter);
95
+ },
96
+ };
97
+ }
98
+
99
+ const TaskContext = createContext<ReturnType<typeof createTaskStore>>();
100
+
101
+ function TaskProvider(props: ParentProps) {
102
+ return (
103
+ <TaskContext.Provider value={createTaskStore()}>
104
+ {props.children}
105
+ </TaskContext.Provider>
106
+ );
107
+ }
108
+ ```
109
+
110
+ **Why this works well in Solid:** Updating a signal at the top of the tree does NOT cause children to re-render. Only the specific reactive expressions that read the changed property update. There is no performance penalty for high-level state.
111
+
112
+ ## HMR Consideration
113
+
114
+ To avoid recreating context during Hot Module Replacement, define `createContext` in its **own module** (separate file), not inline in a component file.
115
+
116
+ ## Module-Level Signals vs Context
117
+
118
+ For truly global, app-wide singletons (e.g., a theme toggle), a module-level signal is simpler:
119
+
120
+ ```typescript
121
+ // theme.ts
122
+ export const [theme, setTheme] = createSignal<"light" | "dark">("light");
123
+
124
+ // Any component can import directly
125
+ import { theme, setTheme } from "./theme";
126
+ ```
127
+
128
+ Use context instead when:
129
+ - Different subtrees need different values (e.g., per-user state)
130
+ - You need testability (mock providers in tests)
131
+ - The state has complex dependencies
@@ -0,0 +1,124 @@
1
+ # Control Flow
2
+
3
+ > Sources: [Show](https://docs.solidjs.com/reference/components/show), [For](https://docs.solidjs.com/reference/components/for), [SolidJS Tutorials](https://www.solidjs.com/tutorial) — SolidJS Docs
4
+
5
+ ## Why Control Flow Components?
6
+
7
+ In Solid, **avoid JavaScript-native conditionals and `.map()` in JSX**. Solid's control flow components provide explicit boundaries that the compiler can optimize — they track dependencies and minimize DOM operations.
8
+
9
+ ## `<Show>` — Conditional Rendering
10
+
11
+ Renders children when `when` is truthy. Optionally provides a `fallback`.
12
+
13
+ ```typescript
14
+ <Show when={user()} fallback={<LoginPrompt />}>
15
+ <Dashboard />
16
+ </Show>
17
+ ```
18
+
19
+ ### Callback Form for Type Narrowing
20
+
21
+ The callback form provides a non-null accessor — essential for TypeScript:
22
+
23
+ ```typescript
24
+ <Show when={user()}>
25
+ {(nonNullUser) => <span>{nonNullUser().name}</span>}
26
+ </Show>
27
+ ```
28
+
29
+ TypeScript cannot narrow accessor types through control flow, so the callback form is the idiomatic way to access narrowed values.
30
+
31
+ ## `<For>` — List Rendering
32
+
33
+ Renders a list, keyed by **reference** (not index). Only re-renders items that actually change.
34
+
35
+ ```typescript
36
+ <For each={items()}>
37
+ {(item, index) => (
38
+ <li>{index()}: {item.name}</li>
39
+ )}
40
+ </For>
41
+ ```
42
+
43
+ - `item` is the value (not reactive for primitives)
44
+ - `index()` is a signal — call it as a function
45
+ - Items are tracked by reference — avoid recreating objects
46
+
47
+ ### `<Index>` — Keyed by Index
48
+
49
+ For primitive arrays where values change but positions are stable:
50
+
51
+ ```typescript
52
+ <Index each={names()}>
53
+ {(name, i) => <li>{i}: {name()}</li>}
54
+ </Index>
55
+ ```
56
+
57
+ - `name` is a signal (reactive)
58
+ - `i` is a plain number (not reactive)
59
+
60
+ **Rule of thumb:** Use `<For>` for arrays of objects, `<Index>` for arrays of primitives.
61
+
62
+ ## `<Switch>` / `<Match>` — Multi-Branch Conditional
63
+
64
+ ```typescript
65
+ <Switch fallback={<p>Unknown state</p>}>
66
+ <Match when={state() === "loading"}>
67
+ <Spinner />
68
+ </Match>
69
+ <Match when={state() === "error"}>
70
+ <ErrorDisplay />
71
+ </Match>
72
+ <Match when={state() === "ready"}>
73
+ <Content />
74
+ </Match>
75
+ </Switch>
76
+ ```
77
+
78
+ First matching `<Match>` wins. Use `fallback` on `<Switch>` for the default case.
79
+
80
+ ## `<ErrorBoundary>` — Error Catching
81
+
82
+ Catches errors thrown in child components and renders a fallback:
83
+
84
+ ```typescript
85
+ <ErrorBoundary fallback={(err, reset) => (
86
+ <div>
87
+ <p>Error: {err.message}</p>
88
+ <button onClick={reset}>Retry</button>
89
+ </div>
90
+ )}>
91
+ <RiskyComponent />
92
+ </ErrorBoundary>
93
+ ```
94
+
95
+ The `reset` function re-renders the children, giving the component a fresh chance.
96
+
97
+ ## `<Suspense>` — Async Loading States
98
+
99
+ Displays a fallback while waiting for async resources to resolve:
100
+
101
+ ```typescript
102
+ <Suspense fallback={<Skeleton />}>
103
+ <UserProfile /> {/* Uses createResource internally */}
104
+ </Suspense>
105
+ ```
106
+
107
+ Suspense detects any `createResource` read within its boundary and holds rendering until all resolve. Nested Suspense boundaries allow granular loading states.
108
+
109
+ ## `<Dynamic>` — Dynamic Component
110
+
111
+ Render a component determined at runtime:
112
+
113
+ ```typescript
114
+ <Dynamic component={isAdmin() ? AdminPanel : UserPanel} user={user()} />
115
+ ```
116
+
117
+ ## Don't Use
118
+
119
+ | Instead of | Use |
120
+ |---|---|
121
+ | `{condition && <Component />}` | `<Show when={condition}>` |
122
+ | `{condition ? <A /> : <B />}` | `<Show when={condition} fallback={<B />}>` |
123
+ | `{items.map(i => ...)}` | `<For each={items()}>` |
124
+ | Nested ternaries | `<Switch>` / `<Match>` |