create-what 0.6.0 → 0.7.0
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.
- package/index.js +219 -3
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -128,6 +128,7 @@ function generatePackageJson(projectName, { reactCompat, cssApproach }) {
|
|
|
128
128
|
const devDeps = {
|
|
129
129
|
vite: '^6.0.0',
|
|
130
130
|
'what-compiler': '^0.6.0',
|
|
131
|
+
'what-devtools-mcp': '^0.6.0',
|
|
131
132
|
'@babel/core': '^7.23.0',
|
|
132
133
|
};
|
|
133
134
|
|
|
@@ -181,6 +182,10 @@ function generateViteConfig({ reactCompat, cssApproach }) {
|
|
|
181
182
|
plugins.push('what()');
|
|
182
183
|
}
|
|
183
184
|
|
|
185
|
+
// MCP DevTools — auto-injects devtools client in dev mode for AI agent debugging
|
|
186
|
+
imports.push(`import whatDevTools from 'what-devtools-mcp/vite-plugin';`);
|
|
187
|
+
plugins.push('whatDevTools()');
|
|
188
|
+
|
|
184
189
|
if (cssApproach === 'tailwind') {
|
|
185
190
|
imports.push(`import tailwindcss from '@tailwindcss/vite';`);
|
|
186
191
|
plugins.push('tailwindcss()');
|
|
@@ -841,9 +846,220 @@ async function main() {
|
|
|
841
846
|
|
|
842
847
|
mkdirSync(join(root, 'src'), { recursive: true });
|
|
843
848
|
mkdirSync(join(root, 'public'), { recursive: true });
|
|
844
|
-
// MCP config
|
|
845
|
-
|
|
846
|
-
|
|
849
|
+
// MCP DevTools config — lets AI agents (Claude Code, Cursor, etc.) connect to the running app
|
|
850
|
+
writeFileSync(join(root, '.mcp.json'), JSON.stringify({
|
|
851
|
+
mcpServers: {
|
|
852
|
+
'what-devtools-mcp': {
|
|
853
|
+
command: 'npx',
|
|
854
|
+
args: ['what-devtools-mcp'],
|
|
855
|
+
},
|
|
856
|
+
},
|
|
857
|
+
}, null, 2) + '\n');
|
|
858
|
+
|
|
859
|
+
// CLAUDE.md — agent instructions for Claude Code (also useful for other AI tools)
|
|
860
|
+
writeFileSync(join(root, 'CLAUDE.md'), `# ${projectName}
|
|
861
|
+
|
|
862
|
+
Built with What Framework — signal-based reactivity, components run once.
|
|
863
|
+
|
|
864
|
+
## Writing Code
|
|
865
|
+
|
|
866
|
+
\`\`\`js
|
|
867
|
+
import { signal, effect, computed, batch, onMount, h, mount } from 'what-framework';
|
|
868
|
+
|
|
869
|
+
const count = signal(0, 'count'); // state
|
|
870
|
+
count() // read
|
|
871
|
+
count(5) // write
|
|
872
|
+
count(c => c + 1) // update
|
|
873
|
+
|
|
874
|
+
const doubled = computed(() => count() * 2); // derived
|
|
875
|
+
effect(() => console.log(count())); // side effect
|
|
876
|
+
\`\`\`
|
|
877
|
+
|
|
878
|
+
Components run ONCE. Use \`signal()\` for state, \`() =>\` in JSX for reactive text.
|
|
879
|
+
|
|
880
|
+
**Signal scope:** \`signal()\` works anywhere — module scope (shared state), component scope (local state). Components run once, so signal declarations execute exactly once.
|
|
881
|
+
|
|
882
|
+
## MCP DevTools
|
|
883
|
+
|
|
884
|
+
This project includes MCP devtools that connect to the running app in the browser.
|
|
885
|
+
|
|
886
|
+
### Quick Start (First 5 Minutes)
|
|
887
|
+
|
|
888
|
+
1. \`what_connection_status\` — am I connected? how big is the app?
|
|
889
|
+
2. \`what_diagnose\` — any errors or issues?
|
|
890
|
+
3. \`what_page_map\` — what's on the page?
|
|
891
|
+
4. \`what_components\` -> \`what_explain\` on a leaf component — deep dive
|
|
892
|
+
5. \`what_signals({filter: "name", named_only: true})\` — check key state
|
|
893
|
+
|
|
894
|
+
### Decision Tree
|
|
895
|
+
|
|
896
|
+
| I want to... | Use this |
|
|
897
|
+
|---|---|
|
|
898
|
+
| Get oriented / check connection | \`what_connection_status\` |
|
|
899
|
+
| Health check (errors + perf + reactivity) | \`what_diagnose\` |
|
|
900
|
+
| Find a component by name | \`what_components {filter}\` |
|
|
901
|
+
| Understand one component deeply | \`what_explain {componentId}\` |
|
|
902
|
+
| See the component hierarchy | \`what_component_tree\` |
|
|
903
|
+
| Check a signal's current value | \`what_signals {filter, named_only: true}\` |
|
|
904
|
+
| See all effects and their run counts | \`what_effects {minRunCount}\` |
|
|
905
|
+
| Understand why a signal changed | \`what_signal_trace {signalId}\` |
|
|
906
|
+
| See what depends on a signal | \`what_dependency_graph {signalId, direction: "downstream"}\` |
|
|
907
|
+
| See what an effect depends on | \`what_dependency_graph {effectId, direction: "upstream"}\` |
|
|
908
|
+
| Find runtime errors | \`what_errors\` |
|
|
909
|
+
| Get component layout/styles (no image) | \`what_look {componentId}\` |
|
|
910
|
+
| Get full page structure | \`what_page_map\` |
|
|
911
|
+
| Get a visual screenshot | \`what_screenshot {componentId}\` (use after what_look) |
|
|
912
|
+
| Inspect raw DOM | \`what_dom_inspect {componentId, depth}\` |
|
|
913
|
+
| Find performance issues | \`what_perf {threshold}\` |
|
|
914
|
+
| Compare before/after state | \`what_diff_snapshot {action: "save"}\` then \`{action: "diff"}\` |
|
|
915
|
+
| Change a signal live | \`what_set_signal {signalId, value}\` |
|
|
916
|
+
| Validate code before saving | \`what_lint {code}\` |
|
|
917
|
+
| Generate boilerplate | \`what_scaffold {type, name}\` |
|
|
918
|
+
| Diagnose an error code | \`what_fix {errorCode}\` |
|
|
919
|
+
|
|
920
|
+
### Workflows
|
|
921
|
+
|
|
922
|
+
**Find and inspect a component:**
|
|
923
|
+
\`what_components({filter:"Stats"})\` -> get ID -> \`what_explain({componentId: 4})\`
|
|
924
|
+
|
|
925
|
+
**Debug a signal's reactive graph:**
|
|
926
|
+
\`what_signals({filter:"count"})\` -> get ID -> \`what_dependency_graph({signalId: 1, direction: "downstream"})\`
|
|
927
|
+
|
|
928
|
+
**Before/after comparison:**
|
|
929
|
+
\`what_diff_snapshot({action:"save"})\` -> make change -> \`what_diff_snapshot({action:"diff"})\`
|
|
930
|
+
|
|
931
|
+
**Performance audit:**
|
|
932
|
+
\`what_perf({threshold: 3})\` -> \`what_effects({minRunCount: 2})\` -> \`what_dependency_graph({effectId: N})\`
|
|
933
|
+
|
|
934
|
+
**Visual/layout audit:**
|
|
935
|
+
\`what_page_map\` -> \`what_look({componentId: N})\` on key components -> \`what_screenshot\` only if needed
|
|
936
|
+
|
|
937
|
+
**Disconnected reactivity (UI parts that should update together but don't):**
|
|
938
|
+
\`what_dependency_graph({signalId: N, direction: "downstream"})\` -> check ALL expected effects appear. Missing edges = component won't react to that signal.
|
|
939
|
+
|
|
940
|
+
**Multi-signal interaction (order-of-operations bugs):**
|
|
941
|
+
\`what_diff_snapshot(save)\` -> set signal A -> \`diff\` -> save -> set signal B -> \`diff\`. Compare cascades.
|
|
942
|
+
|
|
943
|
+
**Build & test new features:**
|
|
944
|
+
\`what_look\` to match styling -> \`what_scaffold\` for structure -> write code -> \`what_lint\` -> \`what_diff_snapshot(save)\` -> \`what_set_signal\` to simulate trigger -> \`what_diff_snapshot(diff)\` to verify cascade.
|
|
945
|
+
|
|
946
|
+
**Stale subscription (effect should fire but doesn't):**
|
|
947
|
+
If dep graph shows an edge but diff shows 0 re-runs, the effect lost its subscription during a remount. Fix: move effect to module scope or use \`computed()\`.
|
|
948
|
+
|
|
949
|
+
### Understanding Diagnostics
|
|
950
|
+
|
|
951
|
+
- **"N signals with no subscribers"** — Normal. Signals in \`() => ...\` reactive text bindings (\`<!--fn-->\` in DOM) update the DOM directly, bypassing tracked effects. Only investigate if a signal should trigger an effect but isn't.
|
|
952
|
+
- **"N effects with no signal dependencies"** — Normal. One-shot setup effects that run once during component creation (DOM init, event listeners). Expected in "components run once" model.
|
|
953
|
+
- **Components with signalCount=0** — Module-scope signals (shared stores) don't appear on any component. Use \`what_signals\` directly.
|
|
954
|
+
- **\`<!--fn-->\` in DOM** — Reactive text binding markers. The primary reactivity mechanism in templates.
|
|
955
|
+
|
|
956
|
+
### Key Parameters
|
|
957
|
+
|
|
958
|
+
| Param | Type | Notes |
|
|
959
|
+
|---|---|---|
|
|
960
|
+
| \`what_signals\` \`named_only\` | boolean | \`true\`/\`false\`, not a string |
|
|
961
|
+
| \`what_effects\` \`minRunCount\` | number | Filter effects that ran >= N times |
|
|
962
|
+
| \`what_dependency_graph\` \`direction\` | \`"upstream"\` \`"downstream"\` \`"both"\` | Default: both |
|
|
963
|
+
| \`what_dom_inspect\` \`depth\` | number | DOM traversal depth (default: 3) |
|
|
964
|
+
| \`what_perf\` \`threshold\` | number | Flag effects with >= N subscribers |
|
|
965
|
+
|
|
966
|
+
### Efficiency
|
|
967
|
+
|
|
968
|
+
**Parallel-safe (batch these):** \`what_perf\`, \`what_effects\`, \`what_signals\`, \`what_components\`, \`what_dependency_graph\`, \`what_explain\`, \`what_look\`, \`what_page_map\`, \`what_diagnose\`, \`what_lint\`, \`what_scaffold\`. NOT safe to parallelize: \`what_set_signal\` calls on signals that share effects.
|
|
969
|
+
|
|
970
|
+
**Diff output:** \`effectsTriggered\` = re-ran. \`effectsAdded\` = new mounts. \`effectsRemoved\` = unmounts. \`what_perf\` includes \`largestSubscribers\` — skip \`what_signals\` if you only need hot signals.
|
|
971
|
+
|
|
972
|
+
### Principles
|
|
973
|
+
1. \`what_connection_status\` first — always orient before diving in
|
|
974
|
+
2. \`what_explain\` over individual calls — replaces separate signals + effects + DOM lookups
|
|
975
|
+
3. \`what_look\` before \`what_screenshot\` — 10x cheaper, usually sufficient
|
|
976
|
+
4. \`what_signals\` with \`filter\` and \`named_only: true\` — never dump unfiltered
|
|
977
|
+
5. \`what_lint\` before saving generated code
|
|
978
|
+
6. Text tools before visual tools — orient with data, then confirm visually
|
|
979
|
+
7. Re-fetch component IDs after state changes — IDs are ephemeral after mount/unmount cycles
|
|
980
|
+
8. \`what_set_signal\` can cascade — use \`what_diff_snapshot\` to see full impact
|
|
981
|
+
|
|
982
|
+
### Troubleshooting
|
|
983
|
+
- **Not connected:** Open the app in a browser, wait 2-3s, retry. \`what_lint\`/\`what_scaffold\`/\`what_fix\` work offline.
|
|
984
|
+
- **"Component N not found":** Re-fetch IDs with \`what_components\` after signal changes that alter the component tree.
|
|
985
|
+
- **Screenshot fails:** Use \`what_look\` instead (usually sufficient without an image).
|
|
986
|
+
- **\`what_lint\` false positive on \`signal-write-in-render\`:** Both named handlers and inline \`onClick={() => sig(val)}\` trigger this. Safe to ignore if signal write is inside an event handler. Re-run with \`rules\` excluding that rule to confirm.
|
|
987
|
+
`);
|
|
988
|
+
|
|
989
|
+
// AGENTS.md — model-agnostic instructions for OpenCode, Codex, Gemini, Cursor, etc.
|
|
990
|
+
writeFileSync(join(root, 'AGENTS.md'), `# ${projectName} — Agent Instructions
|
|
991
|
+
|
|
992
|
+
> Model-agnostic guide for AI agents using MCP DevTools with What Framework.
|
|
993
|
+
|
|
994
|
+
## Framework Basics
|
|
995
|
+
|
|
996
|
+
Signal-based reactivity. Components run **once**. \`signal()\` for state, \`() =>\` in JSX for reactive text.
|
|
997
|
+
|
|
998
|
+
\`\`\`js
|
|
999
|
+
import { signal, effect, computed, h, mount } from 'what-framework';
|
|
1000
|
+
const count = signal(0, 'count');
|
|
1001
|
+
count() // read
|
|
1002
|
+
count(5) // write
|
|
1003
|
+
count(c => c + 1) // update
|
|
1004
|
+
\`\`\`
|
|
1005
|
+
|
|
1006
|
+
## MCP DevTools
|
|
1007
|
+
|
|
1008
|
+
**Always start:** \`what_connection_status\` — returns app info, tool list, next steps.
|
|
1009
|
+
|
|
1010
|
+
### Pick the Right Tool
|
|
1011
|
+
|
|
1012
|
+
| Goal | Tool | Key params |
|
|
1013
|
+
|------|------|------------|
|
|
1014
|
+
| Orient / check connection | \`what_connection_status\` | none |
|
|
1015
|
+
| Health check | \`what_diagnose\` | none |
|
|
1016
|
+
| Find a component | \`what_components\` | \`filter\` (regex string) |
|
|
1017
|
+
| Deep-dive one component | \`what_explain\` | \`componentId\` (number) |
|
|
1018
|
+
| Check signal values | \`what_signals\` | \`filter\` (string), \`named_only\` (boolean) |
|
|
1019
|
+
| See effect run counts | \`what_effects\` | \`minRunCount\` (number) |
|
|
1020
|
+
| Signal dependency graph | \`what_dependency_graph\` | \`signalId\`/\`effectId\` (number), \`direction\` |
|
|
1021
|
+
| Page layout | \`what_page_map\` | none |
|
|
1022
|
+
| Component styling | \`what_look\` | \`componentId\` (number) |
|
|
1023
|
+
| Performance issues | \`what_perf\` | \`threshold\` (number) |
|
|
1024
|
+
| Before/after state | \`what_diff_snapshot\` | \`action\`: \`"save"\` then \`"diff"\` |
|
|
1025
|
+
| Change a signal | \`what_set_signal\` | \`signalId\` (number), \`value\` (any) |
|
|
1026
|
+
| Validate code | \`what_lint\` | \`code\` (string) |
|
|
1027
|
+
| Generate boilerplate | \`what_scaffold\` | \`type\`, \`name\` (strings) |
|
|
1028
|
+
|
|
1029
|
+
### Recipes
|
|
1030
|
+
|
|
1031
|
+
**Find component:** \`what_components({filter:"Name"})\` -> \`what_explain({componentId: N})\`
|
|
1032
|
+
**Debug signal:** \`what_signals({filter:"name"})\` -> \`what_dependency_graph({signalId: N, direction: "downstream"})\`
|
|
1033
|
+
**Before/after:** \`what_diff_snapshot({action:"save"})\` -> change -> \`what_diff_snapshot({action:"diff"})\`
|
|
1034
|
+
**Build feature:** \`what_look\` (match styling) -> \`what_scaffold\` -> write code -> \`what_lint\` -> \`what_diff_snapshot\` (save/set/diff)
|
|
1035
|
+
|
|
1036
|
+
### Parameter Types (common mistakes)
|
|
1037
|
+
|
|
1038
|
+
| Param | Correct | Wrong |
|
|
1039
|
+
|-------|---------|-------|
|
|
1040
|
+
| \`named_only\` | \`true\` (boolean) | \`"true"\` (string) |
|
|
1041
|
+
| \`componentId\` | \`4\` (number) | \`"4"\` (string) |
|
|
1042
|
+
| \`direction\` | \`"downstream"\` | \`downstream\` |
|
|
1043
|
+
|
|
1044
|
+
### Pitfalls
|
|
1045
|
+
|
|
1046
|
+
- **Not connected:** Open app in browser, wait 3s, retry
|
|
1047
|
+
- **Component IDs change** after signal mutations — re-fetch with \`what_components\`
|
|
1048
|
+
- **\`what_lint\` FP on \`signal-write-in-render\`:** Handlers in event callbacks are safe
|
|
1049
|
+
- **\`what_set_signal\` cascades:** Use \`what_diff_snapshot\` to see full impact
|
|
1050
|
+
- **"N signals with no subscribers":** Normal — reactive text bindings bypass tracked effects
|
|
1051
|
+
`);
|
|
1052
|
+
|
|
1053
|
+
// Also generate a .cursor/mcp.json for Cursor users
|
|
1054
|
+
mkdirSync(join(root, '.cursor'), { recursive: true });
|
|
1055
|
+
writeFileSync(join(root, '.cursor', 'mcp.json'), JSON.stringify({
|
|
1056
|
+
mcpServers: {
|
|
1057
|
+
'what-devtools-mcp': {
|
|
1058
|
+
command: 'npx',
|
|
1059
|
+
args: ['what-devtools-mcp'],
|
|
1060
|
+
},
|
|
1061
|
+
},
|
|
1062
|
+
}, null, 2) + '\n');
|
|
847
1063
|
|
|
848
1064
|
// .gitignore
|
|
849
1065
|
writeFileSync(join(root, '.gitignore'), `node_modules\ndist\n.DS_Store\n`);
|