me3-protocol 2.3.0 → 2.5.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/dist/index.d.ts CHANGED
@@ -14,6 +14,18 @@ export interface Me3Page {
14
14
  /** Whether to show in navigation */
15
15
  visible: boolean;
16
16
  }
17
+ export interface Me3Post {
18
+ /** URL-friendly identifier */
19
+ slug: string;
20
+ /** Display name for listing */
21
+ title: string;
22
+ /** Path to markdown file (relative to me.json) */
23
+ file: string;
24
+ /** ISO publish date (optional) */
25
+ publishedAt?: string;
26
+ /** Short excerpt for archive/listing (optional) */
27
+ excerpt?: string;
28
+ }
17
29
  export interface Me3Links {
18
30
  website?: string;
19
31
  github?: string;
@@ -79,6 +91,22 @@ export interface Me3BookingAvailability {
79
91
  sunday?: string[];
80
92
  };
81
93
  }
94
+ /**
95
+ * Booking pricing configuration.
96
+ * Allows hosts to charge for meetings with a sliding scale pay-what-you-want model.
97
+ */
98
+ export interface Me3BookingPricing {
99
+ /** Whether paid meetings are enabled */
100
+ enabled: boolean;
101
+ /** Suggested price amount in dollars (e.g., 50 for $50) */
102
+ suggestedAmount: number;
103
+ /** Currency code */
104
+ currency: "USD" | "GBP" | "EUR";
105
+ /** Minimum amount bookers can pay (always $5) */
106
+ minimumAmount: 5;
107
+ /** Whether to allow free meetings alongside paid ones */
108
+ allowFree: boolean;
109
+ }
82
110
  /**
83
111
  * Booking/scheduling intent.
84
112
  * Declares that the person accepts meeting bookings.
@@ -98,6 +126,8 @@ export interface Me3IntentBook {
98
126
  url?: string;
99
127
  /** Availability windows - for native me3 booking */
100
128
  availability?: Me3BookingAvailability;
129
+ /** Pricing configuration for paid meetings (optional) */
130
+ pricing?: Me3BookingPricing;
101
131
  }
102
132
  /**
103
133
  * Intents object - declares what actions visitors/agents can take.
@@ -130,6 +160,8 @@ export interface Me3Profile {
130
160
  buttons?: Me3Button[];
131
161
  /** Custom pages (markdown) */
132
162
  pages?: Me3Page[];
163
+ /** Blog posts (markdown) */
164
+ posts?: Me3Post[];
133
165
  /**
134
166
  * Custom footer configuration.
135
167
  * - `undefined`: default footer behavior (renderer-defined)
package/dist/index.js CHANGED
@@ -277,6 +277,55 @@ function validateProfile(data) {
277
277
  });
278
278
  }
279
279
  }
280
+ // Posts (optional)
281
+ if (profile.posts !== undefined) {
282
+ const posts = profile.posts;
283
+ if (!Array.isArray(posts)) {
284
+ errors.push({ field: "posts", message: "Posts must be an array" });
285
+ }
286
+ else {
287
+ posts.forEach((post, index) => {
288
+ if (!post || typeof post !== "object") {
289
+ errors.push({
290
+ field: `posts[${index}]`,
291
+ message: "Post must be an object",
292
+ });
293
+ return;
294
+ }
295
+ if (!post.slug || typeof post.slug !== "string") {
296
+ errors.push({
297
+ field: `posts[${index}].slug`,
298
+ message: "Post slug is required",
299
+ });
300
+ }
301
+ if (!post.title || typeof post.title !== "string") {
302
+ errors.push({
303
+ field: `posts[${index}].title`,
304
+ message: "Post title is required",
305
+ });
306
+ }
307
+ if (!post.file || typeof post.file !== "string") {
308
+ errors.push({
309
+ field: `posts[${index}].file`,
310
+ message: "Post file is required",
311
+ });
312
+ }
313
+ if (post.publishedAt !== undefined &&
314
+ typeof post.publishedAt !== "string") {
315
+ errors.push({
316
+ field: `posts[${index}].publishedAt`,
317
+ message: "Post publishedAt must be a string",
318
+ });
319
+ }
320
+ if (post.excerpt !== undefined && typeof post.excerpt !== "string") {
321
+ errors.push({
322
+ field: `posts[${index}].excerpt`,
323
+ message: "Post excerpt must be a string",
324
+ });
325
+ }
326
+ });
327
+ }
328
+ }
280
329
  // Intents (optional)
281
330
  if (profile.intents !== undefined) {
282
331
  if (typeof profile.intents !== "object" || profile.intents === null) {
@@ -485,6 +534,58 @@ function validateProfile(data) {
485
534
  message: "Book intent requires either a URL (for external booking) or availability (for native booking)",
486
535
  });
487
536
  }
537
+ // Validate pricing if present
538
+ if (book.pricing !== undefined) {
539
+ if (typeof book.pricing !== "object" || book.pricing === null) {
540
+ errors.push({
541
+ field: "intents.book.pricing",
542
+ message: "Book pricing must be an object",
543
+ });
544
+ }
545
+ else {
546
+ const pricing = book.pricing;
547
+ if (typeof pricing.enabled !== "boolean") {
548
+ errors.push({
549
+ field: "intents.book.pricing.enabled",
550
+ message: "Pricing enabled must be a boolean",
551
+ });
552
+ }
553
+ if (pricing.enabled) {
554
+ if (typeof pricing.suggestedAmount !== "number") {
555
+ errors.push({
556
+ field: "intents.book.pricing.suggestedAmount",
557
+ message: "Suggested amount must be a number",
558
+ });
559
+ }
560
+ else if (pricing.suggestedAmount < 5) {
561
+ errors.push({
562
+ field: "intents.book.pricing.suggestedAmount",
563
+ message: "Suggested amount must be at least $5",
564
+ });
565
+ }
566
+ const validCurrencies = ["USD", "GBP", "EUR"];
567
+ if (typeof pricing.currency !== "string" ||
568
+ !validCurrencies.includes(pricing.currency)) {
569
+ errors.push({
570
+ field: "intents.book.pricing.currency",
571
+ message: `Currency must be one of: ${validCurrencies.join(", ")}`,
572
+ });
573
+ }
574
+ if (pricing.minimumAmount !== 5) {
575
+ errors.push({
576
+ field: "intents.book.pricing.minimumAmount",
577
+ message: "Minimum amount must be 5",
578
+ });
579
+ }
580
+ if (typeof pricing.allowFree !== "boolean") {
581
+ errors.push({
582
+ field: "intents.book.pricing.allowFree",
583
+ message: "Allow free must be a boolean",
584
+ });
585
+ }
586
+ }
587
+ }
588
+ }
488
589
  }
489
590
  }
490
591
  }
@@ -28,6 +28,15 @@
28
28
  "pages": [
29
29
  { "slug": "about", "title": "About", "file": "about.md", "visible": true }
30
30
  ],
31
+ "posts": [
32
+ {
33
+ "slug": "hello-world",
34
+ "title": "Hello World",
35
+ "file": "blog/hello-world.md",
36
+ "publishedAt": "2026-01-29T12:00:00.000Z",
37
+ "excerpt": "A short welcome post for the blog."
38
+ }
39
+ ],
31
40
  "intents": {
32
41
  "subscribe": {
33
42
  "enabled": true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "me3-protocol",
3
- "version": "2.3.0",
3
+ "version": "2.5.0",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
package/schema.json CHANGED
@@ -66,6 +66,46 @@
66
66
  ],
67
67
  "type": "object"
68
68
  },
69
+ "Me3BookingPricing": {
70
+ "additionalProperties": false,
71
+ "description": "Booking pricing configuration. Allows hosts to charge for meetings with a sliding scale pay-what-you-want model.",
72
+ "properties": {
73
+ "allowFree": {
74
+ "description": "Whether to allow free meetings alongside paid ones",
75
+ "type": "boolean"
76
+ },
77
+ "currency": {
78
+ "description": "Currency code",
79
+ "enum": [
80
+ "USD",
81
+ "GBP",
82
+ "EUR"
83
+ ],
84
+ "type": "string"
85
+ },
86
+ "enabled": {
87
+ "description": "Whether paid meetings are enabled",
88
+ "type": "boolean"
89
+ },
90
+ "minimumAmount": {
91
+ "const": 5,
92
+ "description": "Minimum amount bookers can pay (always $5)",
93
+ "type": "number"
94
+ },
95
+ "suggestedAmount": {
96
+ "description": "Suggested price amount in dollars (e.g., 50 for $50)",
97
+ "type": "number"
98
+ }
99
+ },
100
+ "required": [
101
+ "enabled",
102
+ "suggestedAmount",
103
+ "currency",
104
+ "minimumAmount",
105
+ "allowFree"
106
+ ],
107
+ "type": "object"
108
+ },
69
109
  "Me3Button": {
70
110
  "additionalProperties": false,
71
111
  "properties": {
@@ -149,6 +189,10 @@
149
189
  "description": "Whether booking is enabled",
150
190
  "type": "boolean"
151
191
  },
192
+ "pricing": {
193
+ "$ref": "#/definitions/Me3BookingPricing",
194
+ "description": "Pricing configuration for paid meetings (optional)"
195
+ },
152
196
  "provider": {
153
197
  "description": "Booking provider (e.g., \"cal.com\", \"calendly\") - for external providers",
154
198
  "type": "string"
@@ -282,6 +326,37 @@
282
326
  ],
283
327
  "type": "object"
284
328
  },
329
+ "Me3Post": {
330
+ "additionalProperties": false,
331
+ "properties": {
332
+ "excerpt": {
333
+ "description": "Short excerpt for archive/listing (optional)",
334
+ "type": "string"
335
+ },
336
+ "file": {
337
+ "description": "Path to markdown file (relative to me.json)",
338
+ "type": "string"
339
+ },
340
+ "publishedAt": {
341
+ "description": "ISO publish date (optional)",
342
+ "type": "string"
343
+ },
344
+ "slug": {
345
+ "description": "URL-friendly identifier",
346
+ "type": "string"
347
+ },
348
+ "title": {
349
+ "description": "Display name for listing",
350
+ "type": "string"
351
+ }
352
+ },
353
+ "required": [
354
+ "slug",
355
+ "title",
356
+ "file"
357
+ ],
358
+ "type": "object"
359
+ },
285
360
  "Me3Profile": {
286
361
  "additionalProperties": false,
287
362
  "properties": {
@@ -343,6 +418,13 @@
343
418
  },
344
419
  "type": "array"
345
420
  },
421
+ "posts": {
422
+ "description": "Blog posts (markdown)",
423
+ "items": {
424
+ "$ref": "#/definitions/Me3Post"
425
+ },
426
+ "type": "array"
427
+ },
346
428
  "version": {
347
429
  "description": "Protocol version",
348
430
  "type": "string"