@clipform/mcp-server 1.38.0 → 1.40.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.
@@ -2,217 +2,6 @@ import {
2
2
  getMcpAuth
3
3
  } from "./chunk-HCZI2UJ5.js";
4
4
 
5
- // ../config/form-types.js
6
- var FORM_TYPES = {
7
- quiz: {
8
- label: "Quiz",
9
- description: "Scored knowledge quiz with narrated video questions",
10
- is_active: true,
11
- sort_order: 1,
12
- category: "assessment",
13
- aliases: ["trivia", "test", "exam"],
14
- variants: ["personality", "comprehension", "composition"],
15
- required_features: [],
16
- required_node_types: ["choice", "end_screen"],
17
- default_media_style: "video",
18
- guide_uri: "clipform://guides/quiz",
19
- guide_description: "Craft knowledge for writing engaging quizzes - difficulty curves, question psychology, narration style, scoring",
20
- discovery: [
21
- { key: "topic", question: "What topic or subject area?", fallback: "General trivia", mode: "all" },
22
- { key: "question_count", question: "How many questions?", fallback: "8", mode: "all" },
23
- { key: "media_style", question: "Video with narration (recommended), images, or text only?", fallback: "Video with narration", mode: "full" }
24
- ],
25
- variant_discovery: {
26
- personality: [
27
- { key: "topic", question: "What's the theme? (Which X are you?)", fallback: "General personality", mode: "all" },
28
- { key: "categories", question: "What outcome categories? (3-5 results)", fallback: "Infer 4 categories from the theme", mode: "full" },
29
- { key: "question_count", question: "How many questions?", fallback: "8", mode: "all" }
30
- ],
31
- comprehension: [
32
- { key: "youtube_url", question: "What's the YouTube URL?", fallback: "REQUIRED - cannot proceed without it", mode: "all" },
33
- { key: "question_count", question: "How many questions?", fallback: "8", mode: "all" },
34
- { key: "audience", question: "Who's the audience? (kids, teens, adults)", fallback: "General adults", mode: "full" }
35
- ],
36
- composition: [
37
- { key: "topic", question: "What topic? (flags, movies, geography, music...)", fallback: "General trivia", mode: "all" },
38
- { key: "question_count", question: "How many questions? (composition quizzes use ~2 nodes per question - 5-6 is the sweet spot)", fallback: "5", mode: "all" }
39
- ]
40
- },
41
- variant_guide_uris: {
42
- personality: "clipform://guides/quiz/personality",
43
- comprehension: "clipform://guides/quiz/comprehension",
44
- composition: "clipform://guides/quiz/composition"
45
- },
46
- variant_descriptions: {
47
- personality: "Addendum for personality quizzes - category design, option weighting, outcome writing, no right/wrong answers",
48
- comprehension: "Addendum for YouTube comprehension quizzes - extracting questions from transcripts, distractor design, audience adaptation",
49
- composition: "Addendum for composition quizzes - guess-and-reveal formats built from rendered compositions: mechanic selection, the clue/reveal node pair, difficulty design"
50
- },
51
- prompt: { name: "create-quiz", title: "Create a Quiz", description: "Build a scored knowledge quiz with narrated video questions" }
52
- },
53
- survey: {
54
- label: "Survey",
55
- description: "Feedback survey, NPS form, or research questionnaire",
56
- is_active: true,
57
- sort_order: 2,
58
- category: "feedback",
59
- aliases: ["feedback", "poll", "nps", "questionnaire"],
60
- variants: [],
61
- required_features: [],
62
- required_node_types: ["choice", "open", "end_screen"],
63
- default_media_style: "text",
64
- guide_uri: "clipform://guides/survey",
65
- guide_description: "Craft knowledge for feedback surveys, NPS, and research forms - brevity, rating scales, respondent fatigue",
66
- discovery: [
67
- { key: "topic", question: "What are you measuring? (satisfaction, NPS, feedback on what?)", fallback: "General satisfaction", mode: "all" },
68
- { key: "anonymous", question: "Anonymous or identified responses?", fallback: "Anonymous", mode: "full" }
69
- ],
70
- variant_discovery: {},
71
- variant_guide_uris: {},
72
- variant_descriptions: {},
73
- prompt: { name: "create-survey", title: "Create a Survey", description: "Build a feedback survey, NPS form, or research questionnaire" }
74
- },
75
- interview: {
76
- label: "Interview",
77
- description: "Async video interview, case study, or expert input collection",
78
- is_active: true,
79
- sort_order: 3,
80
- category: "collection",
81
- aliases: ["case-study", "callout"],
82
- variants: [],
83
- required_features: [],
84
- required_node_types: ["open", "contact", "end_screen"],
85
- default_media_style: "video",
86
- guide_uri: "clipform://guides/interview",
87
- guide_description: "Craft knowledge for building interview forms - warm-up pacing, open questions, consent, video responses",
88
- discovery: [
89
- { key: "purpose", question: "What are you collecting? (case studies, feedback, expert input)", fallback: "General responses", mode: "all" },
90
- { key: "response_format", question: "How should people respond? (video, audio, text, all)", fallback: "All formats", mode: "full" },
91
- { key: "needs_consent", question: "Need a consent statement?", fallback: "Yes", mode: "full" }
92
- ],
93
- variant_discovery: {},
94
- variant_guide_uris: {},
95
- variant_descriptions: {},
96
- prompt: { name: "create-interview", title: "Create an Interview", description: "Build an async video interview for collecting case studies, feedback, or expert input" }
97
- },
98
- funnel: {
99
- label: "Funnel",
100
- description: "Lead qualification funnel with conditional routing",
101
- is_active: false,
102
- sort_order: 4,
103
- category: "qualification",
104
- aliases: ["lead-gen", "qualification", "lead-magnet"],
105
- variants: [],
106
- required_features: ["branching"],
107
- required_node_types: ["choice", "contact", "end_screen"],
108
- default_media_style: "text",
109
- guide_uri: "clipform://guides/funnel",
110
- guide_description: "Craft knowledge for lead qualification funnels - planned feature, conditional routing coming soon",
111
- discovery: [],
112
- variant_discovery: {},
113
- variant_guide_uris: {},
114
- variant_descriptions: {},
115
- prompt: { name: "create-funnel", title: "Create a Funnel", description: "Lead qualification funnels with branching logic are planned but not yet available" }
116
- },
117
- testimonial: {
118
- label: "Testimonial",
119
- description: "Video testimonial and story collection form",
120
- is_active: true,
121
- sort_order: 5,
122
- category: "collection",
123
- aliases: ["story", "review"],
124
- variants: [],
125
- required_features: [],
126
- required_node_types: ["open", "contact", "end_screen"],
127
- default_media_style: "video",
128
- guide_uri: "clipform://guides/testimonial",
129
- guide_description: "Craft knowledge for collecting testimonials and customer stories on video - storytelling prompts, comfort techniques, consent",
130
- discovery: [
131
- { key: "use_case", question: "What stories are you collecting? (customer success, employee, partner)", fallback: "Customer success stories", mode: "all" },
132
- { key: "media_style", question: "Video responses (recommended), audio, or text?", fallback: "Video", mode: "full" }
133
- ],
134
- variant_discovery: {},
135
- variant_guide_uris: {},
136
- variant_descriptions: {},
137
- prompt: { name: "create-testimonial", title: "Collect Testimonials", description: "Build a video testimonial collection form - capture authentic customer stories on camera" }
138
- },
139
- application: {
140
- label: "Application",
141
- description: "Structured application form for jobs, programmes, or grants",
142
- is_active: true,
143
- sort_order: 6,
144
- category: "collection",
145
- aliases: ["job-application", "admission", "enrollment", "grant"],
146
- variants: [],
147
- required_features: [],
148
- required_node_types: ["open", "choice", "contact", "end_screen"],
149
- default_media_style: "video",
150
- guide_uri: "clipform://guides/application",
151
- guide_description: "Craft knowledge for application and evaluation forms - multi-section structure, video responses for behavioural questions, screening",
152
- discovery: [
153
- { key: "role", question: "What role or position?", fallback: "General application", mode: "all" }
154
- ],
155
- variant_discovery: {},
156
- variant_guide_uris: {},
157
- variant_descriptions: {},
158
- prompt: { name: "create-application", title: "Create an Application Form", description: "Build a structured application form with video responses for behavioural questions" }
159
- },
160
- booking: {
161
- label: "Booking",
162
- description: "Event registration, course signup, or booking form",
163
- is_active: true,
164
- sort_order: 7,
165
- category: "registration",
166
- aliases: ["registration", "signup", "event", "rsvp", "workshop"],
167
- variants: [],
168
- required_features: [],
169
- required_node_types: ["contact", "choice", "end_screen"],
170
- default_media_style: "text",
171
- guide_uri: "clipform://guides/booking",
172
- guide_description: "Craft knowledge for event registration and booking forms - minimal friction, video welcome, confirmation flow",
173
- discovery: [
174
- { key: "event_name", question: "What's the event name?", fallback: "Event registration", mode: "all" },
175
- { key: "event_type", question: "What type? (workshop, webinar, meetup, conference)", fallback: "Event", mode: "full" }
176
- ],
177
- variant_discovery: {},
178
- variant_guide_uris: {},
179
- variant_descriptions: {},
180
- prompt: { name: "create-booking", title: "Create a Booking Form", description: "Build an event registration or booking form with a personal video welcome" }
181
- }
182
- };
183
- var FORM_TYPES_LIST = Object.entries(FORM_TYPES).map(([key, def]) => ({ key, ...def })).sort((a, b) => a.sort_order - b.sort_order);
184
- var FORM_TYPE_KEYS = Object.keys(FORM_TYPES);
185
- var WORKFLOW_TYPES = FORM_TYPE_KEYS.filter(
186
- (key) => FORM_TYPES[key].is_active
187
- );
188
- var FORM_TYPE_ALIASES = Object.fromEntries(
189
- Object.entries(FORM_TYPES).flatMap(
190
- ([key, def]) => def.aliases.map((alias) => [alias, key])
191
- )
192
- );
193
- var ALL_VARIANTS = Object.entries(FORM_TYPES).flatMap(
194
- ([, def]) => def.variants
195
- );
196
- function resolveFormType(input) {
197
- const normalised = input.toLowerCase().trim();
198
- if (FORM_TYPES[normalised]) return normalised;
199
- return FORM_TYPE_ALIASES[normalised] ?? null;
200
- }
201
- function getDiscoveryParams(formType, variant, mode = "full") {
202
- const def = FORM_TYPES[formType];
203
- if (!def) return [];
204
- let params;
205
- if (variant && def.variant_discovery?.[variant]) {
206
- params = def.variant_discovery[variant];
207
- } else {
208
- params = def.discovery;
209
- }
210
- if (mode === "demo") {
211
- return params.filter((p) => p.mode === "all");
212
- }
213
- return params;
214
- }
215
-
216
5
  // ../config/features.js
217
6
  var FEATURES = {
218
7
  // -- Builder --
@@ -364,6 +153,34 @@ var FEATURES = {
364
153
  status: "planned",
365
154
  category: "node-types"
366
155
  },
156
+ node_binary: {
157
+ name: "Binary choice",
158
+ description: "Two-option choice node (yes/no, this/that)",
159
+ enabled: false,
160
+ status: "planned",
161
+ category: "node-types"
162
+ },
163
+ node_link_list: {
164
+ name: "Link list",
165
+ description: "Terminal node showing a list of links to choose from",
166
+ enabled: false,
167
+ status: "planned",
168
+ category: "node-types"
169
+ },
170
+ node_file_download: {
171
+ name: "File download",
172
+ description: "Provide files for respondents to download",
173
+ enabled: false,
174
+ status: "planned",
175
+ category: "node-types"
176
+ },
177
+ node_shopping: {
178
+ name: "Shopping",
179
+ description: "Product recommendations with direct checkout",
180
+ enabled: false,
181
+ status: "planned",
182
+ category: "node-types"
183
+ },
367
184
  // -- Response formats --
368
185
  text_responses: {
369
186
  name: "Text responses",
@@ -517,9 +334,89 @@ var FEATURES = {
517
334
  status: "planned",
518
335
  category: "integrations"
519
336
  },
520
- integrations: {
521
- name: "Third-party integrations",
522
- description: "Connect forms to external services (Zapier, HubSpot, Slack, etc.)",
337
+ // Per-integration lifecycle (split from the old coarse `integrations` flag so
338
+ // each can ship independently). integration-catalog.js carries the metadata
339
+ // and derives is_active from these. None are live yet.
340
+ integration_stripe: {
341
+ name: "Stripe",
342
+ description: "Accept payments directly in your forms",
343
+ enabled: false,
344
+ status: "planned",
345
+ category: "integrations"
346
+ },
347
+ integration_paddle: {
348
+ name: "Paddle",
349
+ description: "Accept payments with Paddle",
350
+ enabled: false,
351
+ status: "planned",
352
+ category: "integrations"
353
+ },
354
+ integration_square: {
355
+ name: "Square",
356
+ description: "Accept payments with Square",
357
+ enabled: false,
358
+ status: "planned",
359
+ category: "integrations"
360
+ },
361
+ integration_calendly: {
362
+ name: "Calendly",
363
+ description: "Schedule meetings directly in your forms",
364
+ enabled: false,
365
+ status: "planned",
366
+ category: "integrations"
367
+ },
368
+ integration_calcom: {
369
+ name: "Cal.com",
370
+ description: "Open-source scheduling platform for booking meetings",
371
+ enabled: false,
372
+ status: "planned",
373
+ category: "integrations"
374
+ },
375
+ integration_docusign: {
376
+ name: "DocuSign",
377
+ description: "Collect signatures in your forms",
378
+ enabled: false,
379
+ status: "planned",
380
+ category: "integrations"
381
+ },
382
+ integration_zapier: {
383
+ name: "Zapier",
384
+ description: "Connect to 5,000+ apps and automate workflows",
385
+ enabled: false,
386
+ status: "planned",
387
+ category: "integrations"
388
+ },
389
+ integration_make: {
390
+ name: "Make",
391
+ description: "Advanced automation and integrations",
392
+ enabled: false,
393
+ status: "planned",
394
+ category: "integrations"
395
+ },
396
+ integration_hubspot: {
397
+ name: "HubSpot",
398
+ description: "Sync responses to HubSpot CRM",
399
+ enabled: false,
400
+ status: "planned",
401
+ category: "integrations"
402
+ },
403
+ integration_salesforce: {
404
+ name: "Salesforce",
405
+ description: "Sync responses to Salesforce CRM",
406
+ enabled: false,
407
+ status: "planned",
408
+ category: "integrations"
409
+ },
410
+ integration_slack: {
411
+ name: "Slack",
412
+ description: "Send notifications to Slack channels",
413
+ enabled: false,
414
+ status: "planned",
415
+ category: "integrations"
416
+ },
417
+ integration_shopify: {
418
+ name: "Shopify",
419
+ description: "Product recommendations from quiz results with direct checkout",
523
420
  enabled: false,
524
421
  status: "planned",
525
422
  category: "integrations"
@@ -547,23 +444,9 @@ var FEATURES = {
547
444
  }
548
445
  };
549
446
 
550
- // ../config/help-links.js
551
- var HELP_TOPICS = {
552
- goLive: { path: "/guides/sharing", anchor: "go-live" },
553
- cantGoLive: { path: "/guides/sharing", anchor: "cant-go-live" },
554
- liveAndDraft: { path: "/guides/managing-forms", anchor: "live-and-draft" },
555
- publishingChanges: { path: "/guides/managing-forms", anchor: "publishing-changes" },
556
- embedding: { path: "/guides/embed", anchor: null }
557
- };
558
- function buildHelpLinks(docsBaseUrl) {
559
- const links = {};
560
- for (const [key, { path, anchor }] of Object.entries(HELP_TOPICS)) {
561
- links[key] = `${docsBaseUrl}${path}${anchor ? `#${anchor}` : ""}`;
562
- }
563
- return links;
564
- }
565
-
566
447
  // ../config/node-types.js
448
+ var RESPONSE_FORMATS = ["text", "audio", "video"];
449
+ var CONSENT_TYPES = ["consent", "opt_in"];
567
450
  var NODE_TYPES = {
568
451
  start: {
569
452
  label: "Start",
@@ -580,7 +463,6 @@ var NODE_TYPES = {
580
463
  supports_prompt: false,
581
464
  supports_media: false,
582
465
  is_system: true,
583
- is_active: true,
584
466
  show_in_results: false,
585
467
  default_config: null,
586
468
  config_schema: null,
@@ -605,7 +487,6 @@ var NODE_TYPES = {
605
487
  supports_prompt: true,
606
488
  supports_media: true,
607
489
  is_system: false,
608
- is_active: true,
609
490
  show_in_results: true,
610
491
  default_config: {
611
492
  selection_mode: "single",
@@ -705,7 +586,6 @@ var NODE_TYPES = {
705
586
  supports_prompt: true,
706
587
  supports_media: true,
707
588
  is_system: false,
708
- is_active: true,
709
589
  show_in_results: true,
710
590
  default_config: {
711
591
  formats: [
@@ -722,7 +602,7 @@ var NODE_TYPES = {
722
602
  items: {
723
603
  type: "object",
724
604
  properties: {
725
- format: { enum: ["text", "audio", "video"], type: "string" },
605
+ format: { enum: RESPONSE_FORMATS, type: "string" },
726
606
  order: { type: "number" }
727
607
  }
728
608
  },
@@ -764,7 +644,7 @@ var NODE_TYPES = {
764
644
  description: "Media response (when response_type is audio or video)"
765
645
  },
766
646
  response_type: {
767
- enum: ["text", "audio", "video"],
647
+ enum: RESPONSE_FORMATS,
768
648
  type: "string"
769
649
  },
770
650
  transcription: {
@@ -827,7 +707,6 @@ var NODE_TYPES = {
827
707
  supports_prompt: true,
828
708
  supports_media: true,
829
709
  is_system: false,
830
- is_active: false,
831
710
  show_in_results: true,
832
711
  default_config: null,
833
712
  config_schema: {
@@ -862,7 +741,6 @@ var NODE_TYPES = {
862
741
  supports_prompt: false,
863
742
  supports_media: false,
864
743
  is_system: false,
865
- is_active: false,
866
744
  show_in_results: true,
867
745
  default_config: null,
868
746
  config_schema: {
@@ -937,7 +815,6 @@ var NODE_TYPES = {
937
815
  supports_prompt: false,
938
816
  supports_media: false,
939
817
  is_system: false,
940
- is_active: true,
941
818
  show_in_results: false,
942
819
  default_config: {
943
820
  fields: [
@@ -979,7 +856,7 @@ var NODE_TYPES = {
979
856
  name: { type: "string" },
980
857
  label: { type: "string" },
981
858
  order: { type: "number" },
982
- type: { type: "string", enum: ["consent", "opt_in"] }
859
+ type: { type: "string", enum: CONSENT_TYPES }
983
860
  }
984
861
  }
985
862
  }
@@ -1013,7 +890,7 @@ var NODE_TYPES = {
1013
890
  name: { type: "string" },
1014
891
  label: { type: "string" },
1015
892
  accepted: { type: "boolean" },
1016
- type: { type: "string", enum: ["consent", "opt_in"] }
893
+ type: { type: "string", enum: CONSENT_TYPES }
1017
894
  }
1018
895
  },
1019
896
  description: "Consent checkbox entries"
@@ -1054,7 +931,6 @@ var NODE_TYPES = {
1054
931
  supports_prompt: false,
1055
932
  supports_media: false,
1056
933
  is_system: false,
1057
- is_active: false,
1058
934
  show_in_results: true,
1059
935
  default_config: null,
1060
936
  config_schema: {
@@ -1118,7 +994,6 @@ var NODE_TYPES = {
1118
994
  supports_prompt: false,
1119
995
  supports_media: false,
1120
996
  is_system: false,
1121
- is_active: false,
1122
997
  show_in_results: true,
1123
998
  default_config: { amount: null, currency: "usd", provider: "stripe" },
1124
999
  config_schema: {
@@ -1203,7 +1078,6 @@ var NODE_TYPES = {
1203
1078
  supports_prompt: true,
1204
1079
  supports_media: true,
1205
1080
  is_system: false,
1206
- is_active: false,
1207
1081
  show_in_results: true,
1208
1082
  default_config: {
1209
1083
  choice: { enable_branching: true },
@@ -1266,7 +1140,6 @@ var NODE_TYPES = {
1266
1140
  supports_prompt: true,
1267
1141
  supports_media: true,
1268
1142
  is_system: false,
1269
- is_active: true,
1270
1143
  show_in_results: false,
1271
1144
  default_config: { options: [{ content: "Continue" }] },
1272
1145
  config_schema: {
@@ -1305,7 +1178,6 @@ var NODE_TYPES = {
1305
1178
  supports_prompt: false,
1306
1179
  supports_media: false,
1307
1180
  is_system: false,
1308
- is_active: true,
1309
1181
  show_in_results: false,
1310
1182
  default_config: { url: "", auto_redirect: true },
1311
1183
  config_schema: {
@@ -1336,7 +1208,6 @@ var NODE_TYPES = {
1336
1208
  supports_prompt: false,
1337
1209
  supports_media: false,
1338
1210
  is_system: false,
1339
- is_active: false,
1340
1211
  show_in_results: false,
1341
1212
  default_config: { links: [{ id: "default", url: "", title: "", description: "", order: 0 }], auto_redirect: false },
1342
1213
  config_schema: {
@@ -1382,7 +1253,6 @@ var NODE_TYPES = {
1382
1253
  supports_prompt: false,
1383
1254
  supports_media: false,
1384
1255
  is_system: false,
1385
- is_active: false,
1386
1256
  show_in_results: true,
1387
1257
  default_config: null,
1388
1258
  config_schema: {
@@ -1441,7 +1311,6 @@ var NODE_TYPES = {
1441
1311
  supports_prompt: false,
1442
1312
  supports_media: false,
1443
1313
  is_system: false,
1444
- is_active: false,
1445
1314
  show_in_results: false,
1446
1315
  default_config: { provider: "shopify", cta_mode: "checkout", source_mode: "manual" },
1447
1316
  config_schema: {
@@ -1510,7 +1379,6 @@ var NODE_TYPES = {
1510
1379
  supports_prompt: false,
1511
1380
  supports_media: false,
1512
1381
  is_system: false,
1513
- is_active: true,
1514
1382
  show_in_results: false,
1515
1383
  default_config: null,
1516
1384
  config_schema: {
@@ -1561,6 +1429,13 @@ var NODE_TYPES = {
1561
1429
  output_schema: null
1562
1430
  }
1563
1431
  };
1432
+ for (const [type, def] of Object.entries(NODE_TYPES)) {
1433
+ const feature = FEATURES[`node_${type}`];
1434
+ if (!feature) {
1435
+ throw new Error(`NODE_TYPES.${type}: no matching FEATURES["node_${type}"] entry`);
1436
+ }
1437
+ def.is_active = feature.enabled;
1438
+ }
1564
1439
  var NODE_TYPES_LIST = Object.entries(NODE_TYPES).map(([type, def]) => ({ type, ...def })).sort((a, b) => a.sort_order - b.sort_order);
1565
1440
  var NODE_TYPE_KEYS = Object.keys(NODE_TYPES);
1566
1441
  var RESPONSE_SCHEMAS = Object.fromEntries(
@@ -1587,167 +1462,230 @@ var NON_COUNTABLE_TYPES = Object.entries(NODE_TYPES).filter(([, v]) => v.is_syst
1587
1462
  var NON_COUNTABLE_FILTER = `(${NON_COUNTABLE_TYPES.map((t) => `"${t}"`).join(",")})`;
1588
1463
  var RESULTS_EXCLUDED_TYPES = Object.entries(NODE_TYPES).filter(([, v]) => !v.show_in_results).map(([k]) => k);
1589
1464
 
1590
- // ../config/integration-catalog.js
1591
- var INTEGRATION_CATALOG = {
1592
- stripe: {
1593
- name: "Stripe",
1594
- category: "form_action",
1595
- description: "Accept payments directly in your forms",
1596
- logo_url: "https://cdn.brandfetch.io/stripe.com/w/400/h/400",
1597
- color: "#635BFF",
1465
+ // ../config/form-types.js
1466
+ var FORM_TYPES = {
1467
+ quiz: {
1468
+ label: "Quiz",
1469
+ description: "Scored knowledge quiz with narrated video questions",
1598
1470
  sort_order: 1,
1599
- tags: ["payment"],
1600
- external_account_id_field: "account_id",
1601
- display_name_field: "account_name",
1602
- is_active: true
1471
+ category: "assessment",
1472
+ aliases: ["trivia", "test", "exam"],
1473
+ variants: ["personality", "comprehension", "composition"],
1474
+ required_features: [],
1475
+ required_node_types: ["choice", "end_screen"],
1476
+ default_media_style: "video",
1477
+ guide_uri: "clipform://guides/quiz",
1478
+ guide_description: "Craft knowledge for writing engaging quizzes - difficulty curves, question psychology, narration style, scoring",
1479
+ discovery: [
1480
+ { key: "topic", question: "What topic or subject area?", fallback: "General trivia", mode: "all" },
1481
+ { key: "question_count", question: "How many questions?", fallback: "8", mode: "all" },
1482
+ { key: "media_style", question: "Video with narration (recommended), images, or text only?", fallback: "Video with narration", mode: "full" }
1483
+ ],
1484
+ variant_discovery: {
1485
+ personality: [
1486
+ { key: "topic", question: "What's the theme? (Which X are you?)", fallback: "General personality", mode: "all" },
1487
+ { key: "categories", question: "What outcome categories? (3-5 results)", fallback: "Infer 4 categories from the theme", mode: "full" },
1488
+ { key: "question_count", question: "How many questions?", fallback: "8", mode: "all" }
1489
+ ],
1490
+ comprehension: [
1491
+ { key: "youtube_url", question: "What's the YouTube URL?", fallback: "REQUIRED - cannot proceed without it", mode: "all" },
1492
+ { key: "question_count", question: "How many questions?", fallback: "8", mode: "all" },
1493
+ { key: "audience", question: "Who's the audience? (kids, teens, adults)", fallback: "General adults", mode: "full" }
1494
+ ],
1495
+ composition: [
1496
+ { key: "topic", question: "What topic? (flags, movies, geography, music...)", fallback: "General trivia", mode: "all" },
1497
+ { key: "question_count", question: "How many questions? (composition quizzes use ~2 nodes per question - 5-6 is the sweet spot)", fallback: "5", mode: "all" }
1498
+ ]
1499
+ },
1500
+ variant_guide_uris: {
1501
+ personality: "clipform://guides/quiz/personality",
1502
+ comprehension: "clipform://guides/quiz/comprehension",
1503
+ composition: "clipform://guides/quiz/composition"
1504
+ },
1505
+ variant_descriptions: {
1506
+ personality: "Addendum for personality quizzes - category design, option weighting, outcome writing, no right/wrong answers",
1507
+ comprehension: "Addendum for YouTube comprehension quizzes - extracting questions from transcripts, distractor design, audience adaptation",
1508
+ composition: "Addendum for composition quizzes - guess-and-reveal formats built from rendered compositions: mechanic selection, the clue/reveal node pair, difficulty design"
1509
+ },
1510
+ prompt: { name: "create-quiz", title: "Create a Quiz", description: "Build a scored knowledge quiz with narrated video questions" }
1603
1511
  },
1604
- paddle: {
1605
- name: "Paddle",
1606
- category: "form_action",
1607
- description: "Accept payments with Paddle",
1608
- logo_url: "https://cdn.brandfetch.io/paddle.com/w/400/h/400",
1609
- color: "#6837FC",
1512
+ survey: {
1513
+ label: "Survey",
1514
+ description: "Feedback survey, NPS form, or research questionnaire",
1610
1515
  sort_order: 2,
1611
- tags: ["payment"],
1612
- external_account_id_field: null,
1613
- display_name_field: null,
1614
- is_active: true
1516
+ category: "feedback",
1517
+ aliases: ["feedback", "poll", "nps", "questionnaire"],
1518
+ variants: [],
1519
+ required_features: [],
1520
+ required_node_types: ["choice", "open", "end_screen"],
1521
+ default_media_style: "text",
1522
+ guide_uri: "clipform://guides/survey",
1523
+ guide_description: "Craft knowledge for feedback surveys, NPS, and research forms - brevity, rating scales, respondent fatigue",
1524
+ discovery: [
1525
+ { key: "topic", question: "What are you measuring? (satisfaction, NPS, feedback on what?)", fallback: "General satisfaction", mode: "all" },
1526
+ { key: "anonymous", question: "Anonymous or identified responses?", fallback: "Anonymous", mode: "full" }
1527
+ ],
1528
+ variant_discovery: {},
1529
+ variant_guide_uris: {},
1530
+ variant_descriptions: {},
1531
+ prompt: { name: "create-survey", title: "Create a Survey", description: "Build a feedback survey, NPS form, or research questionnaire" }
1615
1532
  },
1616
- square: {
1617
- name: "Square",
1618
- category: "form_action",
1619
- description: "Accept payments with Square",
1620
- logo_url: "https://cdn.brandfetch.io/square.com/w/400/h/400",
1621
- color: "#000000",
1533
+ interview: {
1534
+ label: "Interview",
1535
+ description: "Async video interview, case study, or expert input collection",
1622
1536
  sort_order: 3,
1623
- tags: ["payment"],
1624
- external_account_id_field: null,
1625
- display_name_field: null,
1626
- is_active: true
1627
- },
1628
- calendly: {
1629
- name: "Calendly",
1630
- category: "form_action",
1631
- description: "Schedule meetings directly in your forms",
1632
- logo_url: "https://cdn.brandfetch.io/calendly.com/w/400/h/400",
1633
- color: "#006BFF",
1634
- sort_order: 4,
1635
- tags: ["booking"],
1636
- external_account_id_field: "user_uri",
1637
- display_name_field: "user_name",
1638
- is_active: true
1537
+ category: "collection",
1538
+ aliases: ["case-study", "callout"],
1539
+ variants: [],
1540
+ required_features: [],
1541
+ required_node_types: ["open", "contact", "end_screen"],
1542
+ default_media_style: "video",
1543
+ guide_uri: "clipform://guides/interview",
1544
+ guide_description: "Craft knowledge for building interview forms - warm-up pacing, open questions, consent, video responses",
1545
+ discovery: [
1546
+ { key: "purpose", question: "What are you collecting? (case studies, feedback, expert input)", fallback: "General responses", mode: "all" },
1547
+ { key: "response_format", question: "How should people respond? (video, audio, text, all)", fallback: "All formats", mode: "full" },
1548
+ { key: "needs_consent", question: "Need a consent statement?", fallback: "Yes", mode: "full" }
1549
+ ],
1550
+ variant_discovery: {},
1551
+ variant_guide_uris: {},
1552
+ variant_descriptions: {},
1553
+ prompt: { name: "create-interview", title: "Create an Interview", description: "Build an async video interview for collecting case studies, feedback, or expert input" }
1639
1554
  },
1640
- calcom: {
1641
- name: "Cal.com",
1642
- category: "form_action",
1643
- description: "Open-source scheduling platform for booking meetings",
1644
- logo_url: null,
1645
- color: "#292929",
1555
+ funnel: {
1556
+ label: "Funnel",
1557
+ description: "Lead qualification funnel with conditional routing",
1646
1558
  sort_order: 4,
1647
- tags: ["booking"],
1648
- external_account_id_field: "id",
1649
- display_name_field: "name",
1650
- is_active: true
1559
+ category: "qualification",
1560
+ aliases: ["lead-gen", "qualification", "lead-magnet"],
1561
+ variants: [],
1562
+ required_features: ["branching"],
1563
+ required_node_types: ["choice", "contact", "end_screen"],
1564
+ default_media_style: "text",
1565
+ guide_uri: "clipform://guides/funnel",
1566
+ guide_description: "Craft knowledge for lead qualification funnels - planned feature, conditional routing coming soon",
1567
+ discovery: [],
1568
+ variant_discovery: {},
1569
+ variant_guide_uris: {},
1570
+ variant_descriptions: {},
1571
+ prompt: { name: "create-funnel", title: "Create a Funnel", description: "Lead qualification funnels with branching logic are planned but not yet available" }
1651
1572
  },
1652
- docusign: {
1653
- name: "DocuSign",
1654
- category: "form_action",
1655
- description: "Collect signatures in your forms",
1656
- logo_url: "https://cdn.brandfetch.io/docusign.com/w/400/h/400",
1657
- color: "#FF0037",
1573
+ testimonial: {
1574
+ label: "Testimonial",
1575
+ description: "Video testimonial and story collection form",
1658
1576
  sort_order: 5,
1659
- tags: ["document", "e-signature", "contract"],
1660
- external_account_id_field: null,
1661
- display_name_field: null,
1662
- is_active: true
1663
- },
1664
- webhook: {
1665
- name: "Webhook",
1666
- category: "automation",
1667
- description: "Send responses to custom webhooks",
1668
- logo_url: null,
1669
- color: "#6B7280",
1670
- sort_order: 100,
1671
- tags: ["webhook", "automation", "developer"],
1672
- external_account_id_field: null,
1673
- display_name_field: null,
1674
- is_active: true
1675
- },
1676
- zapier: {
1677
- name: "Zapier",
1678
- category: "automation",
1679
- description: "Connect to 5,000+ apps and automate workflows",
1680
- logo_url: "https://cdn.brandfetch.io/zapier.com/w/400/h/400",
1681
- color: "#FF4A00",
1682
- sort_order: 101,
1683
- tags: ["automation", "workflow", "no-code"],
1684
- external_account_id_field: null,
1685
- display_name_field: null,
1686
- is_active: true
1687
- },
1688
- make: {
1689
- name: "Make",
1690
- category: "automation",
1691
- description: "Advanced automation and integrations",
1692
- logo_url: "https://cdn.brandfetch.io/make.com/w/400/h/400",
1693
- color: "#6B4AFF",
1694
- sort_order: 102,
1695
- tags: ["automation", "workflow", "integration"],
1696
- external_account_id_field: null,
1697
- display_name_field: null,
1698
- is_active: true
1577
+ category: "collection",
1578
+ aliases: ["story", "review"],
1579
+ variants: [],
1580
+ required_features: [],
1581
+ required_node_types: ["open", "contact", "end_screen"],
1582
+ default_media_style: "video",
1583
+ guide_uri: "clipform://guides/testimonial",
1584
+ guide_description: "Craft knowledge for collecting testimonials and customer stories on video - storytelling prompts, comfort techniques, consent",
1585
+ discovery: [
1586
+ { key: "use_case", question: "What stories are you collecting? (customer success, employee, partner)", fallback: "Customer success stories", mode: "all" },
1587
+ { key: "media_style", question: "Video responses (recommended), audio, or text?", fallback: "Video", mode: "full" }
1588
+ ],
1589
+ variant_discovery: {},
1590
+ variant_guide_uris: {},
1591
+ variant_descriptions: {},
1592
+ prompt: { name: "create-testimonial", title: "Collect Testimonials", description: "Build a video testimonial collection form - capture authentic customer stories on camera" }
1699
1593
  },
1700
- hubspot: {
1701
- name: "HubSpot",
1702
- category: "automation",
1703
- description: "Sync responses to HubSpot CRM",
1704
- logo_url: "https://cdn.brandfetch.io/hubspot.com/w/400/h/400",
1705
- color: "#FF7A59",
1706
- sort_order: 103,
1707
- tags: ["automation", "crm", "marketing"],
1708
- external_account_id_field: "portal_id",
1709
- display_name_field: "portal_name",
1710
- is_active: true
1594
+ application: {
1595
+ label: "Application",
1596
+ description: "Structured application form for jobs, programmes, or grants",
1597
+ sort_order: 6,
1598
+ category: "collection",
1599
+ aliases: ["job-application", "admission", "enrollment", "grant"],
1600
+ variants: [],
1601
+ required_features: [],
1602
+ required_node_types: ["open", "choice", "contact", "end_screen"],
1603
+ default_media_style: "video",
1604
+ guide_uri: "clipform://guides/application",
1605
+ guide_description: "Craft knowledge for application and evaluation forms - multi-section structure, video responses for behavioural questions, screening",
1606
+ discovery: [
1607
+ { key: "role", question: "What role or position?", fallback: "General application", mode: "all" }
1608
+ ],
1609
+ variant_discovery: {},
1610
+ variant_guide_uris: {},
1611
+ variant_descriptions: {},
1612
+ prompt: { name: "create-application", title: "Create an Application Form", description: "Build a structured application form with video responses for behavioural questions" }
1711
1613
  },
1712
- salesforce: {
1713
- name: "Salesforce",
1714
- category: "automation",
1715
- description: "Sync responses to Salesforce CRM",
1716
- logo_url: "https://cdn.brandfetch.io/salesforce.com/w/400/h/400",
1717
- color: "#00A1E0",
1718
- sort_order: 104,
1719
- tags: ["automation", "crm", "sales"],
1720
- external_account_id_field: null,
1721
- display_name_field: null,
1722
- is_active: true
1723
- },
1724
- slack: {
1725
- name: "Slack",
1726
- category: "automation",
1727
- description: "Send notifications to Slack channels",
1728
- logo_url: "https://cdn.brandfetch.io/slack.com/w/400/h/400",
1729
- color: "#4A154B",
1730
- sort_order: 105,
1731
- tags: ["automation", "communication", "notifications"],
1732
- external_account_id_field: null,
1733
- display_name_field: null,
1734
- is_active: true
1735
- },
1736
- shopify: {
1737
- name: "Shopify",
1738
- category: "ecommerce",
1739
- description: "Product recommendations from quiz results with direct checkout",
1740
- logo_url: "https://cdn.brandfetch.io/shopify.com/w/400/h/400",
1741
- color: "#95BF47",
1742
- sort_order: 200,
1743
- tags: ["ecommerce", "product", "checkout", "quiz"],
1744
- external_account_id_field: "shop_domain",
1745
- display_name_field: "shop_name",
1746
- is_active: true
1614
+ booking: {
1615
+ label: "Booking",
1616
+ description: "Event registration, course signup, or booking form",
1617
+ sort_order: 7,
1618
+ category: "registration",
1619
+ aliases: ["registration", "signup", "event", "rsvp", "workshop"],
1620
+ variants: [],
1621
+ required_features: [],
1622
+ required_node_types: ["contact", "choice", "end_screen"],
1623
+ default_media_style: "text",
1624
+ guide_uri: "clipform://guides/booking",
1625
+ guide_description: "Craft knowledge for event registration and booking forms - minimal friction, video welcome, confirmation flow",
1626
+ discovery: [
1627
+ { key: "event_name", question: "What's the event name?", fallback: "Event registration", mode: "all" },
1628
+ { key: "event_type", question: "What type? (workshop, webinar, meetup, conference)", fallback: "Event", mode: "full" }
1629
+ ],
1630
+ variant_discovery: {},
1631
+ variant_guide_uris: {},
1632
+ variant_descriptions: {},
1633
+ prompt: { name: "create-booking", title: "Create a Booking Form", description: "Build an event registration or booking form with a personal video welcome" }
1634
+ }
1635
+ };
1636
+ for (const def of Object.values(FORM_TYPES)) {
1637
+ const featuresLive = def.required_features.every((k) => FEATURES[k]?.enabled === true);
1638
+ const nodesLive = def.required_node_types.every((t) => NODE_TYPES[t]?.is_active === true);
1639
+ def.is_active = featuresLive && nodesLive;
1640
+ }
1641
+ var FORM_TYPES_LIST = Object.entries(FORM_TYPES).map(([key, def]) => ({ key, ...def })).sort((a, b) => a.sort_order - b.sort_order);
1642
+ var FORM_TYPE_KEYS = Object.keys(FORM_TYPES);
1643
+ var WORKFLOW_TYPES = FORM_TYPE_KEYS.filter(
1644
+ (key) => FORM_TYPES[key].is_active
1645
+ );
1646
+ var FORM_TYPE_ALIASES = Object.fromEntries(
1647
+ Object.entries(FORM_TYPES).flatMap(
1648
+ ([key, def]) => def.aliases.map((alias) => [alias, key])
1649
+ )
1650
+ );
1651
+ var ALL_VARIANTS = Object.entries(FORM_TYPES).flatMap(
1652
+ ([, def]) => def.variants
1653
+ );
1654
+ function resolveFormType(input) {
1655
+ const normalised = input.toLowerCase().trim();
1656
+ if (FORM_TYPES[normalised]) return normalised;
1657
+ return FORM_TYPE_ALIASES[normalised] ?? null;
1658
+ }
1659
+ function getDiscoveryParams(formType, variant, mode = "full") {
1660
+ const def = FORM_TYPES[formType];
1661
+ if (!def) return [];
1662
+ let params;
1663
+ if (variant && def.variant_discovery?.[variant]) {
1664
+ params = def.variant_discovery[variant];
1665
+ } else {
1666
+ params = def.discovery;
1667
+ }
1668
+ if (mode === "demo") {
1669
+ return params.filter((p) => p.mode === "all");
1747
1670
  }
1671
+ return params;
1672
+ }
1673
+
1674
+ // ../config/help-links.js
1675
+ var HELP_TOPICS = {
1676
+ goLive: { path: "/guides/sharing", anchor: "go-live" },
1677
+ cantGoLive: { path: "/guides/sharing", anchor: "cant-go-live" },
1678
+ liveAndDraft: { path: "/guides/managing-forms", anchor: "live-and-draft" },
1679
+ publishingChanges: { path: "/guides/managing-forms", anchor: "publishing-changes" },
1680
+ embedding: { path: "/guides/embed", anchor: null }
1748
1681
  };
1749
- var INTEGRATION_CATALOG_LIST = Object.entries(INTEGRATION_CATALOG).map(([slug, def]) => ({ slug, ...def })).sort((a, b) => a.sort_order - b.sort_order);
1750
- var INTEGRATION_SLUGS = Object.keys(INTEGRATION_CATALOG);
1682
+ function buildHelpLinks(docsBaseUrl) {
1683
+ const links = {};
1684
+ for (const [key, { path, anchor }] of Object.entries(HELP_TOPICS)) {
1685
+ links[key] = `${docsBaseUrl}${path}${anchor ? `#${anchor}` : ""}`;
1686
+ }
1687
+ return links;
1688
+ }
1751
1689
 
1752
1690
  // ../config/index.js
1753
1691
  var isServer = typeof window === "undefined";
@@ -1862,6 +1800,44 @@ var SLIDESHOW_TRANSITIONS = [
1862
1800
  "diagbr",
1863
1801
  "hblur"
1864
1802
  ];
1803
+ var COMPOSITION_REGISTRY = [
1804
+ // Beds (full-bleed backgrounds)
1805
+ { id: "MediaSlideshow", tier: "public", kind: "bed" },
1806
+ { id: "Map", tier: "public", kind: "bed" },
1807
+ { id: "Grid", tier: "public", kind: "bed" },
1808
+ { id: "GridList", tier: "public", kind: "bed" },
1809
+ { id: "ObscuredReveal", tier: "public", kind: "bed" },
1810
+ { id: "Timeline", tier: "public", kind: "bed" },
1811
+ { id: "NumberLine", tier: "public", kind: "bed" },
1812
+ { id: "CountdownRing", tier: "public", kind: "bed" },
1813
+ { id: "CountrySilhouetteClip", tier: "public", kind: "bed" },
1814
+ // TODO(consolidation): collapse to one FlagReveal { country } - these three
1815
+ // are the same component with hardcoded flag paths (a recipe, not a tool).
1816
+ { id: "FlagRevealGB", tier: "public", kind: "bed" },
1817
+ { id: "FlagRevealJP", tier: "public", kind: "bed" },
1818
+ { id: "FlagRevealBR", tier: "public", kind: "bed" },
1819
+ { id: "ColorCards", tier: "public", kind: "bed" },
1820
+ { id: "TitleCard", tier: "public", kind: "bed" },
1821
+ { id: "ParallaxImage", tier: "public", kind: "bed" },
1822
+ { id: "Spin3D", tier: "labs", kind: "bed" },
1823
+ // Overlays (assets layered on a bed)
1824
+ { id: "TextReveal", tier: "public", kind: "overlay" },
1825
+ { id: "EmojiPuzzle", tier: "public", kind: "overlay" },
1826
+ { id: "BeforeAfter", tier: "public", kind: "overlay" },
1827
+ { id: "StatCounter", tier: "labs", kind: "overlay" },
1828
+ { id: "ListReveal", tier: "labs", kind: "overlay" },
1829
+ // Container
1830
+ { id: "Scene", tier: "labs", kind: "container" },
1831
+ // Social marketing templates (gated)
1832
+ { id: "ShortFormQuiz", tier: "social", kind: "template" },
1833
+ { id: "ScorecardQuiz", tier: "social", kind: "template" },
1834
+ { id: "ScorecardGK", tier: "social", kind: "template" },
1835
+ { id: "CountrySilhouetteQuiz", tier: "social", kind: "template" }
1836
+ ];
1837
+ var compositionIdsByTier = (tier) => COMPOSITION_REGISTRY.filter((c) => c.tier === tier).map((c) => c.id);
1838
+ var PUBLIC_COMPOSITION_IDS = compositionIdsByTier("public");
1839
+ var LABS_COMPOSITION_IDS = compositionIdsByTier("labs");
1840
+ var SOCIAL_COMPOSITION_IDS = compositionIdsByTier("social");
1865
1841
  var MCP_TOOL_TIERS = {};
1866
1842
 
1867
1843
  // src/lib/telemetry.ts
@@ -2064,6 +2040,9 @@ export {
2064
2040
  KEN_BURNS_PRESETS,
2065
2041
  KEN_BURNS_FIT_MODES,
2066
2042
  SLIDESHOW_TRANSITIONS,
2043
+ PUBLIC_COMPOSITION_IDS,
2044
+ LABS_COMPOSITION_IDS,
2045
+ SOCIAL_COMPOSITION_IDS,
2067
2046
  MCP_TOOL_TIERS,
2068
2047
  setMcpVersion,
2069
2048
  callApi,
@@ -2072,4 +2051,4 @@ export {
2072
2051
  getSessionContextWithAuth,
2073
2052
  getSessionContext
2074
2053
  };
2075
- //# sourceMappingURL=chunk-KBWMI24E.js.map
2054
+ //# sourceMappingURL=chunk-WCC65GB5.js.map