@curenorway/kode-cli 1.5.1 → 1.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.
@@ -446,6 +446,10 @@ The \`.mcp.json\` file enables AI tools:
446
446
  - Modify site structure, CMS collections, pages, and more
447
447
  - Requires the Webflow MCP Bridge App running in Designer (press E \u2192 Apps)
448
448
 
449
+ **playwright MCP**: Testing and runtime HTML inspection
450
+ - \`browser_navigate\`, \`browser_snapshot\`, \`browser_click\`, \`browser_console_messages\`
451
+ - Use to verify scripts work correctly AFTER deploying to staging
452
+
449
453
  Restart Claude Code after \`kode init\` to load MCP servers.
450
454
 
451
455
  `;
@@ -676,6 +680,14 @@ Use both MCPs together for powerful workflows:
676
680
 
677
681
  **IMPORTANT**: Before writing ANY JavaScript, always gather context first. Follow this decision tree:
678
682
 
683
+ ### The Three MCPs
684
+
685
+ | MCP | Purpose | When to Use |
686
+ |-----|---------|-------------|
687
+ | **Cure Kode** | Script management, static HTML, deployment | Writing & deploying scripts |
688
+ | **Webflow** | Site structure, CMS, pages, assets | Understanding data & structure |
689
+ | **Playwright** | Runtime HTML, testing, screenshots | Verifying scripts work correctly |
690
+
679
691
  ### Step 1: Understand the Task
680
692
 
681
693
  | Task Type | First Action |
@@ -685,8 +697,9 @@ Use both MCPs together for powerful workflows:
685
697
  | JS for forms | Use Webflow MCP \u2192 get form structure, then Cure Kode for custom validation |
686
698
  | JS for navigation/menus | Use Webflow MCP \u2192 \`pages_list\` to get site structure |
687
699
  | JS for dynamic content | Check BOTH - Webflow for data structure, Cure Kode for existing scripts |
700
+ | Debugging existing JS | Use Playwright MCP \u2192 \`browser_navigate\` + \`browser_console_messages\` |
688
701
 
689
- ### Step 2: Discovery Workflow
702
+ ### Step 2: The Complete Workflow
690
703
 
691
704
  \`\`\`
692
705
  1. DISCOVER: What elements/data am I working with?
@@ -702,8 +715,19 @@ Use both MCPs together for powerful workflows:
702
715
  4. IMPLEMENT: Write the JavaScript
703
716
  - Use kode_create_script or kode_update_script
704
717
 
705
- 5. DEPLOY: Test on staging first
706
- - kode_deploy (staging), verify, then kode_promote (production)
718
+ 5. DEPLOY: Push to staging
719
+ - kode_deploy (staging)
720
+
721
+ 6. VERIFY: Test that it works! \u2B05\uFE0F CRITICAL STEP
722
+ - Playwright MCP: browser_navigate to staging URL
723
+ - Playwright MCP: browser_snapshot to see runtime DOM
724
+ - Playwright MCP: browser_console_messages to check for errors
725
+ - Playwright MCP: browser_click / browser_fill to test interactions
726
+ - If issues found \u2192 fix and redeploy
727
+
728
+ 7. PROMOTE: Go live
729
+ - kode_promote (production)
730
+ - Optionally verify production with Playwright
707
731
  \`\`\`
708
732
 
709
733
  ### Step 3: Common Patterns
@@ -758,6 +782,400 @@ If you can't find the right selectors or understand the structure:
758
782
  3. Check if there's cached context in \`kode_list_pages_context\`
759
783
  4. Ask the user to refresh context: \`kode html <url> --save --force\`
760
784
 
785
+ ## \u{1F3AD} Playwright MCP (Testing & Verification)
786
+
787
+ Playwright MCP is **always included** because testing is essential. Use it to:
788
+ - Get **runtime HTML** (after JavaScript has executed)
789
+ - **Test interactions** (clicks, form fills, hovers)
790
+ - **Debug issues** (console logs, network errors)
791
+ - **Take screenshots** for visual verification
792
+
793
+ ### Playwright MCP Tools
794
+
795
+ | Tool | Purpose | Example Use |
796
+ |------|---------|-------------|
797
+ | \`browser_navigate\` | Go to a URL | Navigate to staging site |
798
+ | \`browser_snapshot\` | Get accessibility tree (runtime DOM) | See what elements exist after JS runs |
799
+ | \`browser_click\` | Click an element | Test button clicks, menu opens |
800
+ | \`browser_fill\` | Type into input | Test form interactions |
801
+ | \`browser_select\` | Select dropdown option | Test select inputs |
802
+ | \`browser_hover\` | Hover over element | Test hover states |
803
+ | \`browser_screenshot\` | Take screenshot | Visual verification |
804
+ | \`browser_console_messages\` | Get console output | Check for JS errors |
805
+ | \`browser_network_requests\` | See network activity | Debug API calls |
806
+
807
+ ### Static vs Runtime HTML
808
+
809
+ | Method | What You Get | When to Use |
810
+ |--------|--------------|-------------|
811
+ | \`kode_fetch_html_smart\` | Static HTML (before JS) | Understanding page structure |
812
+ | \`browser_snapshot\` | Runtime DOM (after JS) | Verifying JS worked correctly |
813
+
814
+ **Example**: If your script adds a class \`.is-active\` to elements, \`kode_fetch_html_smart\` won't show it, but \`browser_snapshot\` will!
815
+
816
+ ### Testing Patterns
817
+
818
+ **Pattern: Verify Script Deployed Correctly**
819
+ \`\`\`
820
+ 1. browser_navigate \u2192 staging URL
821
+ 2. browser_snapshot \u2192 check if expected elements/classes exist
822
+ 3. browser_console_messages \u2192 ensure no JS errors
823
+ \`\`\`
824
+
825
+ **Pattern: Test Click Interaction**
826
+ \`\`\`
827
+ 1. browser_navigate \u2192 page URL
828
+ 2. browser_click \u2192 target element (e.g., ".accordion-trigger")
829
+ 3. browser_snapshot \u2192 verify state changed (e.g., ".accordion-content" visible)
830
+ \`\`\`
831
+
832
+ **Pattern: Test Form Validation**
833
+ \`\`\`
834
+ 1. browser_navigate \u2192 form page
835
+ 2. browser_fill \u2192 input invalid data
836
+ 3. browser_click \u2192 submit button
837
+ 4. browser_snapshot \u2192 verify error message appears
838
+ \`\`\`
839
+
840
+ **Pattern: Debug Why Script Isn't Working**
841
+ \`\`\`
842
+ 1. browser_navigate \u2192 problem page
843
+ 2. browser_console_messages \u2192 look for errors
844
+ 3. browser_snapshot \u2192 check if elements exist
845
+ 4. Compare with kode_fetch_html_smart \u2192 is JS even loading?
846
+ \`\`\`
847
+
848
+ ### Testing Checklist
849
+
850
+ Before promoting to production, verify:
851
+ - [ ] No console errors (\`browser_console_messages\`)
852
+ - [ ] Expected DOM changes visible (\`browser_snapshot\`)
853
+ - [ ] Interactions work (\`browser_click\`, \`browser_fill\`)
854
+ - [ ] Works on key pages (test multiple URLs)
855
+
856
+ ### Staging vs Production URLs
857
+
858
+ The staging URL for testing is typically:
859
+ - \`https://[site-slug].webflow.io\` (Webflow staging)
860
+ - Or check \`kode_site_info\` for configured staging domain
861
+
862
+ Always test on staging before promoting to production!
863
+
864
+ ## \u{1F4F1} Mobile Testing
865
+
866
+ **50%+ of web traffic is mobile!** Always test on mobile viewports.
867
+
868
+ ### Playwright Viewport Testing
869
+
870
+ \`\`\`
871
+ 1. browser_navigate \u2192 page URL
872
+ 2. browser_resize \u2192 { width: 375, height: 812 } (iPhone)
873
+ 3. browser_snapshot \u2192 check mobile layout
874
+ 4. browser_click \u2192 test touch interactions
875
+ \`\`\`
876
+
877
+ ### Common Mobile Viewports
878
+
879
+ | Device | Width | Height |
880
+ |--------|-------|--------|
881
+ | iPhone SE | 375 | 667 |
882
+ | iPhone 14 | 390 | 844 |
883
+ | iPhone 14 Pro Max | 430 | 932 |
884
+ | iPad | 768 | 1024 |
885
+ | Android (common) | 360 | 800 |
886
+
887
+ ### Mobile-Specific Issues to Check
888
+
889
+ - [ ] Touch targets large enough (44x44px minimum)
890
+ - [ ] No horizontal scroll
891
+ - [ ] Text readable without zooming
892
+ - [ ] Modals/dropdowns work on touch
893
+ - [ ] Hover states have touch alternatives
894
+
895
+ ### Testing Pattern
896
+
897
+ \`\`\`
898
+ // Test on desktop first
899
+ browser_navigate(url)
900
+ browser_snapshot \u2192 verify desktop
901
+
902
+ // Then test mobile
903
+ browser_resize({ width: 375, height: 812 })
904
+ browser_snapshot \u2192 verify mobile layout
905
+ browser_click(".mobile-menu-btn") \u2192 test mobile nav
906
+ \`\`\`
907
+
908
+ ## \u{1F4DA} External Libraries
909
+
910
+ Need GSAP, Swiper, Lodash, or other libraries? Here's how to manage them.
911
+
912
+ ### Pattern 1: CDN Script Loader (Recommended)
913
+
914
+ Create a global "libraries" script that loads dependencies:
915
+
916
+ \`\`\`javascript
917
+ // Script: libraries.js (Global, autoLoad: true)
918
+ // This loads FIRST and makes libraries available to other scripts
919
+
920
+ window.CureLibs = window.CureLibs || {};
921
+
922
+ // Load a library from CDN
923
+ function loadLib(name, url, globalVar) {
924
+ return new Promise((resolve, reject) => {
925
+ if (window[globalVar]) {
926
+ resolve(window[globalVar]);
927
+ return;
928
+ }
929
+ const script = document.createElement('script');
930
+ script.src = url;
931
+ script.onload = () => {
932
+ window.CureLibs[name] = window[globalVar];
933
+ resolve(window[globalVar]);
934
+ };
935
+ script.onerror = reject;
936
+ document.head.appendChild(script);
937
+ });
938
+ }
939
+
940
+ // Pre-load common libraries (add what you need)
941
+ window.CureLibs.load = {
942
+ gsap: () => loadLib('gsap', 'https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js', 'gsap'),
943
+ scrollTrigger: () => loadLib('ScrollTrigger', 'https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js', 'ScrollTrigger'),
944
+ swiper: () => loadLib('Swiper', 'https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js', 'Swiper'),
945
+ lottie: () => loadLib('lottie', 'https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.12.2/lottie.min.js', 'lottie'),
946
+ anime: () => loadLib('anime', 'https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js', 'anime'),
947
+ lodash: () => loadLib('_', 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js', '_'),
948
+ };
949
+
950
+ // Also load CSS for libraries that need it
951
+ function loadCSS(url) {
952
+ const link = document.createElement('link');
953
+ link.rel = 'stylesheet';
954
+ link.href = url;
955
+ document.head.appendChild(link);
956
+ }
957
+
958
+ window.CureLibs.loadCSS = loadCSS;
959
+ \`\`\`
960
+
961
+ ### Pattern 2: Using Libraries in Scripts
962
+
963
+ \`\`\`javascript
964
+ // Script: hero-animations.js (depends on GSAP)
965
+
966
+ (async function() {
967
+ // Wait for library to load
968
+ const gsap = await window.CureLibs.load.gsap();
969
+ await window.CureLibs.load.scrollTrigger();
970
+
971
+ // Register plugin
972
+ gsap.registerPlugin(ScrollTrigger);
973
+
974
+ // Now use GSAP
975
+ gsap.from('.hero-title', {
976
+ y: 100,
977
+ opacity: 0,
978
+ duration: 1,
979
+ scrollTrigger: {
980
+ trigger: '.hero-section',
981
+ start: 'top 80%',
982
+ }
983
+ });
984
+ })();
985
+ \`\`\`
986
+
987
+ ### Pattern 3: Swiper Slider Example
988
+
989
+ \`\`\`javascript
990
+ // Script: testimonial-slider.js
991
+
992
+ (async function() {
993
+ // Load Swiper JS and CSS
994
+ const Swiper = await window.CureLibs.load.swiper();
995
+ window.CureLibs.loadCSS('https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css');
996
+
997
+ // Wait for CSS to load
998
+ await new Promise(resolve => setTimeout(resolve, 100));
999
+
1000
+ // Initialize Swiper
1001
+ new Swiper('.testimonial-slider', {
1002
+ slidesPerView: 1,
1003
+ spaceBetween: 30,
1004
+ pagination: {
1005
+ el: '.swiper-pagination',
1006
+ clickable: true,
1007
+ },
1008
+ breakpoints: {
1009
+ 768: { slidesPerView: 2 },
1010
+ 1024: { slidesPerView: 3 },
1011
+ }
1012
+ });
1013
+ })();
1014
+ \`\`\`
1015
+
1016
+ ### Popular Libraries CDN URLs
1017
+
1018
+ | Library | CDN URL |
1019
+ |---------|---------|
1020
+ | GSAP | \`https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js\` |
1021
+ | ScrollTrigger | \`https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js\` |
1022
+ | Swiper | \`https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js\` |
1023
+ | Lottie | \`https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.12.2/lottie.min.js\` |
1024
+ | Anime.js | \`https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js\` |
1025
+ | Lodash | \`https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js\` |
1026
+ | Alpine.js | \`https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js\` |
1027
+ | Chart.js | \`https://cdn.jsdelivr.net/npm/chart.js\` |
1028
+
1029
+ ### Library Management Best Practices
1030
+
1031
+ 1. **Create a central libraries.js script** - Load ALL external deps from one place
1032
+ 2. **Use async/await pattern** - Ensure libraries load before using them
1033
+ 3. **Don't duplicate loading** - Check if library already exists
1034
+ 4. **Version pin CDN URLs** - Avoid unexpected breaking changes
1035
+ 5. **Load CSS when needed** - Some libraries (Swiper) need CSS too
1036
+
1037
+ ## \u{1F517} Script Dependencies & Load Order
1038
+
1039
+ Scripts sometimes depend on each other. Here's how to manage that.
1040
+
1041
+ ### Understanding Load Order
1042
+
1043
+ | Scope | autoLoad | When it Loads |
1044
+ |-------|----------|---------------|
1045
+ | Global | true | Immediately, inlined in init.js |
1046
+ | Global | false | On-demand via \`CK.loadScript()\` |
1047
+ | Page | true | When URL matches page pattern |
1048
+ | Page | false | On-demand via \`CK.loadScript()\` |
1049
+
1050
+ **Global autoLoad scripts load FIRST**, in the order they appear in the script list.
1051
+
1052
+ ### Dependency Pattern
1053
+
1054
+ \`\`\`javascript
1055
+ // Script: libraries.js (Global, autoLoad: true, position: FIRST)
1056
+ // Loads external libraries
1057
+
1058
+ // Script: utils.js (Global, autoLoad: true, position: SECOND)
1059
+ // Depends on libraries.js, provides shared utilities
1060
+
1061
+ // Script: hero-animations.js (Page-specific for /home)
1062
+ // Depends on both libraries.js and utils.js
1063
+ (async function() {
1064
+ // Libraries are already loaded (global autoLoad runs first)
1065
+ const gsap = await window.CureLibs.load.gsap();
1066
+
1067
+ // Utils are available
1068
+ const elements = window.CureUtils.queryAll('.hero-title');
1069
+
1070
+ // Now animate
1071
+ gsap.from(elements, { opacity: 0 });
1072
+ })();
1073
+ \`\`\`
1074
+
1075
+ ### Manual Loading for Complex Dependencies
1076
+
1077
+ \`\`\`javascript
1078
+ // If you need explicit control, use CK.loadScript()
1079
+ async function initComplexFeature() {
1080
+ // Load dependencies in order
1081
+ await CK.loadScript('libraries');
1082
+ await CK.loadScript('utils');
1083
+ await CK.loadScript('complex-feature');
1084
+ }
1085
+
1086
+ // Trigger when needed
1087
+ document.querySelector('.trigger-btn').addEventListener('click', initComplexFeature);
1088
+ \`\`\`
1089
+
1090
+ ### Avoiding Conflicts with Webflow
1091
+
1092
+ Webflow has its own JS (Webflow.js, IX2 interactions). To avoid conflicts:
1093
+
1094
+ 1. **Wrap in IIFE** - Isolate your code
1095
+ \`\`\`javascript
1096
+ (function() {
1097
+ // Your code here, isolated from global scope
1098
+ })();
1099
+ \`\`\`
1100
+
1101
+ 2. **Use unique prefixes** - \`CureSlider\` not \`Slider\`
1102
+
1103
+ 3. **Check before init** - Don't re-init Webflow components
1104
+ \`\`\`javascript
1105
+ if (!element.hasAttribute('data-cure-initialized')) {
1106
+ // Initialize
1107
+ element.setAttribute('data-cure-initialized', 'true');
1108
+ }
1109
+ \`\`\`
1110
+
1111
+ 4. **Respect Webflow events**
1112
+ \`\`\`javascript
1113
+ // Wait for Webflow to be ready
1114
+ window.Webflow && window.Webflow.push(function() {
1115
+ // Your code runs after Webflow initializes
1116
+ });
1117
+ \`\`\`
1118
+
1119
+ ## \u23EA Rollback & Version Recovery
1120
+
1121
+ Things go wrong. Here's how to recover quickly.
1122
+
1123
+ ### Checking Version History
1124
+
1125
+ Use \`kode_get_script\` to see version info, or check the Cure Kode UI.
1126
+
1127
+ ### Quick Rollback Pattern
1128
+
1129
+ \`\`\`
1130
+ 1. Identify the broken script
1131
+ 2. kode_get_script \u2192 get current (broken) version
1132
+ 3. Check version history in Cure Kode UI
1133
+ 4. Copy the previous working version
1134
+ 5. kode_update_script \u2192 paste the working code
1135
+ 6. kode_deploy \u2192 push fix to staging
1136
+ 7. Verify with Playwright
1137
+ 8. kode_promote \u2192 restore production
1138
+ \`\`\`
1139
+
1140
+ ### Emergency Production Fix
1141
+
1142
+ If production is broken RIGHT NOW:
1143
+
1144
+ \`\`\`
1145
+ Option A: Quick disable
1146
+ - kode_update_script \u2192 set autoLoad: false
1147
+ - kode_deploy + kode_promote
1148
+ - Script stops loading immediately
1149
+
1150
+ Option B: Empty script
1151
+ - kode_update_script \u2192 replace with: // temporarily disabled
1152
+ - kode_deploy + kode_promote
1153
+
1154
+ Option C: Full rollback
1155
+ - Get previous version from history
1156
+ - kode_update_script with old code
1157
+ - kode_deploy + kode_promote
1158
+ \`\`\`
1159
+
1160
+ ### Prevention: Before Major Changes
1161
+
1162
+ 1. **Note the current working state** in context.md
1163
+ 2. **Test thoroughly on staging** with Playwright
1164
+ 3. **Deploy during low-traffic hours** if risky
1165
+ 4. **Have rollback plan ready** before promoting
1166
+
1167
+ ### Debugging Production Issues
1168
+
1169
+ \`\`\`
1170
+ 1. browser_navigate \u2192 production URL
1171
+ 2. browser_console_messages \u2192 look for errors
1172
+ 3. Compare with staging \u2192 same error?
1173
+ 4. If staging works but production doesn't:
1174
+ - Check if promotion completed
1175
+ - Check for caching issues (hard refresh)
1176
+ - Check for environment differences
1177
+ \`\`\`
1178
+
761
1179
  `;
762
1180
  }
763
1181
 
@@ -910,6 +1328,10 @@ config.json
910
1328
  url: "https://mcp.webflow.com/sse"
911
1329
  };
912
1330
  }
1331
+ mcpConfig.mcpServers["playwright"] = {
1332
+ command: "npx",
1333
+ args: ["-y", "@playwright/mcp@latest"]
1334
+ };
913
1335
  spinner.start("Generating AI context files...");
914
1336
  writeFileSync3(mcpConfigPath, JSON.stringify(mcpConfig, null, 2) + "\n");
915
1337
  spinner.text = "Generating AI context files...";
@@ -1059,6 +1481,9 @@ config.json
1059
1481
  console.log(chalk.dim(" webflow: ") + chalk.yellow("Not configured"));
1060
1482
  console.log(chalk.dim(" Run `kode init --force` to set up Webflow MCP later."));
1061
1483
  }
1484
+ console.log();
1485
+ console.log(chalk.dim(" playwright:"));
1486
+ console.log(chalk.dim(" Test scripts, get runtime HTML (after JS runs), take screenshots."));
1062
1487
  if (claudeMdAction === "separate") {
1063
1488
  console.log(chalk.yellow("\n\u{1F4A1} Tip: Add this line to your CLAUDE.md to reference Kode instructions:"));
1064
1489
  console.log(chalk.dim(" See KODE.md for Cure Kode CDN management instructions."));
package/dist/cli.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  readPageContext,
16
16
  statusCommand,
17
17
  watchCommand
18
- } from "./chunk-Z3QNIDBJ.js";
18
+ } from "./chunk-KAYIHS2T.js";
19
19
 
20
20
  // src/cli.ts
21
21
  import { Command } from "commander";
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  updateScriptPurpose,
28
28
  watchCommand,
29
29
  writeContext
30
- } from "./chunk-Z3QNIDBJ.js";
30
+ } from "./chunk-KAYIHS2T.js";
31
31
  export {
32
32
  KodeApiClient,
33
33
  KodeApiError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@curenorway/kode-cli",
3
- "version": "1.5.1",
3
+ "version": "1.7.0",
4
4
  "description": "CLI tool for Cure Kode - manage JS/CSS scripts for Webflow sites",
5
5
  "type": "module",
6
6
  "bin": {