multisite-cms-mcp 1.7.0 → 1.7.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"get-conversion-guide.d.ts","sourceRoot":"","sources":["../../src/tools/get-conversion-guide.ts"],"names":[],"mappings":"AAAA,KAAK,OAAO,GAAG,MAAM,GAAG,aAAa,GAAG,UAAU,GAAG,WAAW,GAAG,KAAK,GAAG,UAAU,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,GAAG,iBAAiB,CAAC;AAooCtK;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CA+F1E"}
1
+ {"version":3,"file":"get-conversion-guide.d.ts","sourceRoot":"","sources":["../../src/tools/get-conversion-guide.ts"],"names":[],"mappings":"AAAA,KAAK,OAAO,GAAG,MAAM,GAAG,aAAa,GAAG,UAAU,GAAG,WAAW,GAAG,KAAK,GAAG,UAAU,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,GAAG,iBAAiB,CAAC;AAotCtK;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CA+F1E"}
@@ -744,7 +744,7 @@ Forms are automatically captured by the CMS.
744
744
  ## Basic Form Setup
745
745
 
746
746
  \`\`\`html
747
- <form data-form-name="contact">
747
+ <form data-form-name="contact" action="/_forms/contact" method="POST">
748
748
  <input type="text" name="name" required>
749
749
  <input type="email" name="email" required>
750
750
  <textarea name="message" required></textarea>
@@ -755,6 +755,8 @@ Forms are automatically captured by the CMS.
755
755
  ## Required Attributes
756
756
 
757
757
  - \`data-form-name="xxx"\` on the form element
758
+ - \`action="/_forms/xxx"\` pointing to the form endpoint (MUST match data-form-name)
759
+ - \`method="POST"\` for form submission
758
760
  - \`name="fieldName"\` on each input
759
761
 
760
762
  ## Form Handler Script
@@ -787,6 +789,60 @@ document.querySelectorAll('form[data-form-name]').forEach(form => {
787
789
 
788
790
  **CRITICAL:** The form endpoint is \`/_forms/{formName}\` - NOT \`/api/forms/submit\`
789
791
 
792
+ ---
793
+
794
+ ## CRITICAL: Remove Original Form Handlers
795
+
796
+ **If the source site has JavaScript that handles form submissions, you MUST modify or remove it!**
797
+
798
+ The original site's JavaScript often does:
799
+ - \`e.preventDefault()\` - blocks the actual form submission
800
+ - Shows a "fake" success toast/message - but data goes nowhere
801
+ - Never actually submits to a server
802
+
803
+ ### What to Look For in Original JS
804
+
805
+ \`\`\`javascript
806
+ // PROBLEM: This blocks real submissions!
807
+ form.addEventListener('submit', (e) => {
808
+ e.preventDefault();
809
+ // ... validation ...
810
+ showToast('Message sent!'); // FAKE! Data not saved!
811
+ });
812
+ \`\`\`
813
+
814
+ ### What You Must Do
815
+
816
+ **Option A: Use Native Form Submission (Simplest)**
817
+ \`\`\`html
818
+ <form data-form-name="contact" action="/_forms/contact" method="POST">
819
+ <input type="text" name="name" required>
820
+ <input type="email" name="email" required>
821
+ <button type="submit">Send</button>
822
+ </form>
823
+ \`\`\`
824
+ Then **remove** the original JavaScript form handler entirely.
825
+
826
+ **Option B: Keep JS but POST to Fast Mode**
827
+ Replace the original handler with one that actually submits:
828
+ \`\`\`javascript
829
+ form.addEventListener('submit', async (e) => {
830
+ e.preventDefault();
831
+ const formName = form.dataset.formName;
832
+ const response = await fetch('/_forms/' + formName, {
833
+ method: 'POST',
834
+ headers: { 'Content-Type': 'application/json' },
835
+ body: JSON.stringify(Object.fromEntries(new FormData(form)))
836
+ });
837
+ if (response.ok) {
838
+ showToast('Message sent!'); // NOW it's real!
839
+ form.reset();
840
+ }
841
+ });
842
+ \`\`\`
843
+
844
+ ---
845
+
790
846
  ## Naming Conventions
791
847
 
792
848
  - Contact form → \`contact\`
@@ -1016,13 +1072,13 @@ assets/
1016
1072
  **CORRECT:**
1017
1073
  \`\`\`
1018
1074
  public/
1019
- ├── css/style.css ← Served at /css/style.css
1020
- └── js/main.js ← Served at /js/main.js
1075
+ ├── css/style.css ← Reference as /public/css/style.css in HTML
1076
+ └── js/main.js ← Reference as /public/js/main.js in HTML
1021
1077
  \`\`\`
1022
1078
 
1023
1079
  If CSS/JS isn't loading, check that:
1024
- - Files are in \`public/\` folder
1025
- - HTML references use paths like \`/css/style.css\` (not \`/public/css/style.css\`)
1080
+ - Files are in \`public/\` folder (NOT \`assets/\`)
1081
+ - HTML references use \`/public/css/style.css\` (WITH the /public/ prefix)
1026
1082
 
1027
1083
  ---
1028
1084
 
@@ -1132,6 +1188,30 @@ If external CSS/JS absolutely won't load, you can inline them in manifest.json:
1132
1188
 
1133
1189
  ---
1134
1190
 
1191
+ ## 8. Keeping Original Form Handlers
1192
+
1193
+ The source site often has JavaScript that "handles" form submissions with fake success messages.
1194
+
1195
+ **WRONG (original site's JS):**
1196
+ \`\`\`javascript
1197
+ form.addEventListener('submit', (e) => {
1198
+ e.preventDefault();
1199
+ showToast('Message sent!'); // FAKE! Data goes nowhere!
1200
+ });
1201
+ \`\`\`
1202
+
1203
+ **CORRECT (submit to Fast Mode):**
1204
+ \`\`\`html
1205
+ <form data-form-name="contact" action="/_forms/contact" method="POST">
1206
+ <!-- inputs -->
1207
+ </form>
1208
+ \`\`\`
1209
+ Then REMOVE the original JavaScript handler, or replace it with one that actually POSTs to \`/_forms/{formName}\`.
1210
+
1211
+ **See \`get_conversion_guide(section: "forms")\` for detailed form handling instructions.**
1212
+
1213
+ ---
1214
+
1135
1215
  ## Validation Workflow
1136
1216
 
1137
1217
  Before deploying, ALWAYS run:
@@ -1 +1 @@
1
- {"version":3,"file":"get-field-types.d.ts","sourceRoot":"","sources":["../../src/tools/get-field-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,SAAS,EAqE5C,CAAC;AAEF;;;GAGG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,CAqDrD"}
1
+ {"version":3,"file":"get-field-types.d.ts","sourceRoot":"","sources":["../../src/tools/get-field-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,SAAS,EA0E5C,CAAC;AAEF;;;GAGG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,CAqDrD"}
@@ -51,6 +51,11 @@ exports.AVAILABLE_FIELD_TYPES = [
51
51
  label: 'Image',
52
52
  description: 'Image file or URL. Supports direct file uploads to storage. Use for photos, thumbnails, hero images.'
53
53
  },
54
+ {
55
+ value: 'file',
56
+ label: 'File',
57
+ description: 'Downloadable file (PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, ZIP, MP3, MP4, etc.). Max 10MB. Use in templates as a download link: <a href="{{field}}" download>Download</a>'
58
+ },
54
59
  {
55
60
  value: 'url',
56
61
  label: 'URL',
@@ -1 +1 @@
1
- {"version":3,"file":"get-started.d.ts","sourceRoot":"","sources":["../../src/tools/get-started.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,MAAM,MAAM,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,eAAe,GAAG,SAAS,GAAG,QAAQ,CAAC;AAExF,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAsiBD;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CA4FxE"}
1
+ {"version":3,"file":"get-started.d.ts","sourceRoot":"","sources":["../../src/tools/get-started.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,MAAM,MAAM,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,eAAe,GAAG,SAAS,GAAG,QAAQ,CAAC;AAExF,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAmjBD;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CA4FxE"}
@@ -376,20 +376,33 @@ create_site(name: "New Website Name")
376
376
 
377
377
  ---
378
378
 
379
- ## Website Conversion Workflow
379
+ ## ⚠️ REQUIRED: Read Before Building
380
380
 
381
- ### Step 1: Get the conversion guide
381
+ **DO NOT SKIP THIS STEP.** The conversion guide contains CRITICAL information that prevents common failures:
382
+
383
+ ### Step 1: Read common mistakes FIRST
384
+ \`\`\`
385
+ get_conversion_guide(section: "common_mistakes")
386
+ \`\`\`
387
+
388
+ This section covers:
389
+ - **Asset paths** - Why CSS/JS might 404 (MUST use /public/ prefix!)
390
+ - **Form handling** - Why forms might not work (MUST remove original handlers!)
391
+ - **data-edit-key** - Why text won't be editable (REQUIRED for static pages!)
392
+
393
+ ### Step 2: Read the full guide
382
394
  \`\`\`
383
395
  get_conversion_guide(section: "full")
384
396
  \`\`\`
385
397
 
386
- Or get specific sections:
398
+ All sections:
387
399
  - \`first_steps\` - Required initial setup
388
400
  - \`structure\` - Package folder structure
389
401
  - \`manifest\` - manifest.json configuration
390
402
  - \`templates\` - Template creation patterns
391
403
  - \`tokens\` - CMS token reference
392
- - \`common_mistakes\` - Avoid these errors!
404
+ - \`forms\` - Form submission setup
405
+ - \`common_mistakes\` - Critical errors to avoid
393
406
 
394
407
  ### Step 2: Build and validate as you go
395
408
  \`\`\`
@@ -1 +1 @@
1
- {"version":3,"file":"validate-package.d.ts","sourceRoot":"","sources":["../../src/tools/validate-package.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAAE,EAClB,eAAe,EAAE,MAAM,EACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACxC,OAAO,CAAC,MAAM,CAAC,CA8TjB"}
1
+ {"version":3,"file":"validate-package.d.ts","sourceRoot":"","sources":["../../src/tools/validate-package.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAAE,EAClB,eAAe,EAAE,MAAM,EACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACxC,OAAO,CAAC,MAAM,CAAC,CA4VjB"}
@@ -257,6 +257,34 @@ Reference in HTML as: /images/${fileName}
257
257
  Files outside public/ will not be served and will cause 404 errors.`);
258
258
  }
259
259
  }
260
+ // 9. Check JS files for potential form handler conflicts
261
+ if (templateContents) {
262
+ for (const [path, content] of Object.entries(templateContents)) {
263
+ if (path.endsWith('.js')) {
264
+ // Check for form submit handlers that might block CMS form submission
265
+ const hasSubmitListener = content.includes('addEventListener') && content.includes('submit');
266
+ const hasPreventDefault = content.includes('preventDefault');
267
+ const hasFormsEndpoint = content.includes('/_forms/');
268
+ if (hasSubmitListener && hasPreventDefault && !hasFormsEndpoint) {
269
+ warnings.push(`POTENTIAL FORM ISSUE: ${path} has form handlers with preventDefault() but no /_forms/ endpoint.
270
+
271
+ This JavaScript may block form submissions from reaching Fast Mode!
272
+
273
+ LOOK FOR patterns like:
274
+ form.addEventListener('submit', (e) => {
275
+ e.preventDefault();
276
+ showToast('Message sent!'); // FAKE - data not saved!
277
+ });
278
+
279
+ FIX BY either:
280
+ 1. Remove the original handler entirely (use native form submission)
281
+ 2. Update handler to POST to /_forms/{formName}
282
+
283
+ See get_conversion_guide(section: "forms") for proper form setup.`);
284
+ }
285
+ }
286
+ }
287
+ }
260
288
  // Build result
261
289
  let output = '';
262
290
  if (errors.length === 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"validate-template.d.ts","sourceRoot":"","sources":["../../src/tools/validate-template.ts"],"names":[],"mappings":"AAMA,KAAK,YAAY,GAAG,cAAc,GAAG,eAAe,GAAG,aAAa,CAAC;AAuTrE;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,YAAY,EAC1B,cAAc,CAAC,EAAE,MAAM,EACvB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CA6kBjB"}
1
+ {"version":3,"file":"validate-template.d.ts","sourceRoot":"","sources":["../../src/tools/validate-template.ts"],"names":[],"mappings":"AAMA,KAAK,YAAY,GAAG,cAAc,GAAG,eAAe,GAAG,aAAa,CAAC;AAmUrE;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,YAAY,EAC1B,cAAc,CAAC,EAAE,MAAM,EACvB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CA8kBjB"}
@@ -121,16 +121,30 @@ function validateForms(html) {
121
121
  const hasLegacyDataFormName = /data-form-name=["'][^"']+["']/i.test(formTag);
122
122
  if (hasDataForm) {
123
123
  formsWithDataForm++;
124
+ // Check if form has proper action attribute pointing to /_forms/
125
+ if (!formTag.includes('action=')) {
126
+ errors.push(`- Form has data-form but no action attribute. Add action="/_forms/formname" for the form to work.`);
127
+ }
128
+ else if (!formTag.includes('/_forms/')) {
129
+ warnings.push(`- Form has action but it doesn't point to /_forms/. Fast Mode forms must submit to /_forms/{formName}.`);
130
+ }
124
131
  }
125
132
  else if (hasLegacyDataFormName) {
126
133
  formsWithLegacyAttr++;
127
134
  warnings.push(`- Form uses deprecated data-form-name attribute. Migrate to data-form="formname" for consistency.`);
135
+ // Also check action for legacy forms
136
+ if (!formTag.includes('action=')) {
137
+ errors.push(`- Form has data-form-name but no action attribute. Add action="/_forms/formname" for the form to work.`);
138
+ }
139
+ else if (!formTag.includes('/_forms/')) {
140
+ warnings.push(`- Form has action but it doesn't point to /_forms/. Fast Mode forms must submit to /_forms/{formName}.`);
141
+ }
128
142
  }
129
143
  else {
130
144
  // Form without any data-form attribute - check if it looks like a CMS form
131
- // Don't error on forms that might be external (like search forms)
145
+ // Don't error on forms that might be external (like search forms, login forms)
132
146
  if (!formTag.includes('action=')) {
133
- errors.push(`- Form is missing data-form attribute. Add data-form="formname" to identify the form for CMS submission.`);
147
+ errors.push(`- Form is missing data-form attribute. Add data-form="formname" and action="/_forms/formname" to identify the form for CMS submission.`);
134
148
  }
135
149
  }
136
150
  }
@@ -351,19 +365,20 @@ Without tokens, every item page will show the same static content.`);
351
365
  const hasHeadings = /<h[1-6][^>]*>[^<]+<\/h[1-6]>/gi.test(html);
352
366
  const hasParagraphs = /<p[^>]*>[^<]+<\/p>/gi.test(html);
353
367
  if (editKeys.length === 0 && (hasHeadings || hasParagraphs)) {
354
- warnings.push(`MISSING INLINE EDITING: No data-edit-key attributes found.
368
+ errors.push(`MISSING INLINE EDITING: Static page has no data-edit-key attributes.
355
369
 
356
370
  Without data-edit-key, users CANNOT edit text content in the visual editor!
357
371
 
358
372
  WRONG (no inline editing):
359
- <h1>{{page_title}}</h1>
360
- <p>{{intro_text}}</p>
373
+ <h1>Welcome</h1>
374
+ <p>Introduction text here.</p>
361
375
 
362
376
  CORRECT (enables inline editing):
363
- <h1 data-edit-key="page_title">{{page_title}}</h1>
364
- <p data-edit-key="intro_text">{{intro_text}}</p>
377
+ <h1 data-edit-key="hero-title">Welcome</h1>
378
+ <p data-edit-key="hero-subtitle">Introduction text here.</p>
365
379
 
366
- Add data-edit-key to any text element the user should be able to edit.`);
380
+ REQUIRED: Add data-edit-key="unique-name" to each text element that should be editable.
381
+ Every heading, paragraph, button label, etc. needs its own unique key.`);
367
382
  }
368
383
  else if (editKeys.length > 0) {
369
384
  suggestions.push(`- Found ${editKeys.length} inline editing point(s) with data-edit-key`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "multisite-cms-mcp",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "description": "MCP server for Fast Mode CMS. Convert websites, validate packages, and deploy directly to Fast Mode. Includes authentication, project creation, schema sync, and one-click deployment.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {