@craftware/crafty-sdk 0.5.2 → 0.8.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/README.md +70 -3
- package/dist/client.d.ts +7 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +7 -0
- package/dist/client.js.map +1 -1
- package/dist/crafty-visual-editing.global.js +1 -1
- package/dist/crafty-visual-editing.global.js.map +1 -1
- package/dist/http.d.ts +8 -1
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +50 -11
- package/dist/http.js.map +1 -1
- package/dist/image.d.ts +27 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +110 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/resources/analytics.d.ts +30 -0
- package/dist/resources/analytics.d.ts.map +1 -0
- package/dist/resources/analytics.js +76 -0
- package/dist/resources/analytics.js.map +1 -0
- package/dist/resources/assistant.d.ts +30 -0
- package/dist/resources/assistant.d.ts.map +1 -0
- package/dist/resources/assistant.js +51 -0
- package/dist/resources/assistant.js.map +1 -0
- package/dist/resources/entries.js +2 -2
- package/dist/resources/entries.js.map +1 -1
- package/dist/resources/forms.d.ts.map +1 -1
- package/dist/resources/forms.js +4 -4
- package/dist/resources/forms.js.map +1 -1
- package/dist/resources/pages.js +2 -2
- package/dist/resources/pages.js.map +1 -1
- package/dist/types/public.d.ts +146 -2
- package/dist/types/public.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
- package/skills/crafty-cms/SKILL.md +66 -11
- package/skills/crafty-cms/references/mcp-configuration.md +33 -14
- package/skills/crafty-cms/references/migrate-to-crafty.md +85 -0
- package/skills/crafty-cms/references/sdk-development.md +80 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages.js","sourceRoot":"","sources":["../../src/resources/pages.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAWrD,MAAM,OAAO,aAAa;IACY;IAApC,YAAoC,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;IAAG,CAAC;IAEjD,IAAI,CAAC,KAAsB,EAAE,OAAwB;QAC1D,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QAE/D,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAmB,QAAQ,EAAE,cAAc,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"pages.js","sourceRoot":"","sources":["../../src/resources/pages.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAWrD,MAAM,OAAO,aAAa;IACY;IAApC,YAAoC,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;IAAG,CAAC;IAEjD,IAAI,CAAC,KAAsB,EAAE,OAAwB;QAC1D,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QAE/D,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAmB,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC;IACzF,CAAC;IAEM,KAAK,CAAC,GAAG,CAAC,QAAgB,EAAE,OAAwB;QACzD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAA6B,UAAU,kBAAkB,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;QAE1I,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,IAAI,IAAI,QAAQ,EAAE,IAAI,EAAE,CAAC;YACxD,oBAAoB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACzF,CAAC;QAED,OAAO,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAEO,kBAAkB,CAAC,QAAoC;QAC7D,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/E,MAAM,MAAM,GAAkC,EAAE,CAAC;QACjD,MAAM,WAAW,GAAuC,EAAE,CAAC;QAE3D,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAG,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,SAAS;YACX,CAAC;YAED,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YACpB,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzB,WAAW,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC;QAC9B,CAAC;QAED,OAAO;YACL,GAAG,QAAQ;YACX,MAAM;YACN,MAAM;YACN,WAAW;YACX,KAAK,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,IAAI;YAClD,QAAQ,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE;YAC9C,QAAQ,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC;YAC3D,YAAY,EAAE,CAAC,IAAY,EAAE,EAAE;gBAC7B,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;gBAExC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;oBACnB,MAAM,IAAI,KAAK,CAAC,gCAAgC,IAAI,EAAE,CAAC,CAAC;gBAC1D,CAAC;gBAED,OAAO,KAAK,CAAC;YACf,CAAC;SACF,CAAC;IACJ,CAAC;CACF"}
|
package/dist/types/public.d.ts
CHANGED
|
@@ -1,6 +1,35 @@
|
|
|
1
1
|
import type { CraftyBlock } from "./blocks.js";
|
|
2
2
|
export type { CraftyBlock, CraftyBlockTypeSummary, CraftyReferenceItem } from "./blocks.js";
|
|
3
|
-
|
|
3
|
+
/** Field types a collection (or block type) can declare. */
|
|
4
|
+
export type CraftyFieldType = "string" | "text" | "longText" | "url" | "number" | "decimal" | "boolean" | "datetime" | "select" | "json" | "reference" | "multiReference" | "stringList" | "repeater";
|
|
5
|
+
/** A `select` option: the stored value, optionally with a display label. */
|
|
6
|
+
export type CraftySelectOption = string | {
|
|
7
|
+
value: string;
|
|
8
|
+
label?: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* One field of a collection schema. `number` holds integers and `decimal` any
|
|
12
|
+
* number (both take optional `min`/`max`; `decimal` also `precision`, the
|
|
13
|
+
* maximum decimal places). A `select` value is one of `options` (or, with
|
|
14
|
+
* `multiple: true`, an array of them). A `repeater` holds a list of items with
|
|
15
|
+
* the subfields in `fields`; there `min`/`max` bound the item count.
|
|
16
|
+
*/
|
|
17
|
+
export type CraftyFieldDefinition = {
|
|
18
|
+
type?: CraftyFieldType | (string & {});
|
|
19
|
+
label?: string;
|
|
20
|
+
required?: boolean;
|
|
21
|
+
order?: number;
|
|
22
|
+
model?: string;
|
|
23
|
+
collection?: string;
|
|
24
|
+
repository?: string;
|
|
25
|
+
min?: number;
|
|
26
|
+
max?: number;
|
|
27
|
+
precision?: number;
|
|
28
|
+
options?: CraftySelectOption[];
|
|
29
|
+
multiple?: boolean;
|
|
30
|
+
fields?: Record<string, CraftyFieldDefinition>;
|
|
31
|
+
[key: string]: unknown;
|
|
32
|
+
};
|
|
4
33
|
export type CraftyCollection = {
|
|
5
34
|
id: number;
|
|
6
35
|
name: string;
|
|
@@ -13,8 +42,13 @@ export type CraftyCollection = {
|
|
|
13
42
|
};
|
|
14
43
|
export type CraftyEntry = {
|
|
15
44
|
id: number;
|
|
45
|
+
/** The entry slug (Crafty servers from October 2026; `undefined` on older ones). */
|
|
46
|
+
slug?: string | null;
|
|
16
47
|
created_at: string;
|
|
17
48
|
updated_at: string;
|
|
49
|
+
/** Always "published" outside preview mode: drafts are only returned with a preview token. */
|
|
50
|
+
status: "draft" | "published";
|
|
51
|
+
published_at: string | null;
|
|
18
52
|
display_title: string;
|
|
19
53
|
[key: string]: string | number | boolean | null | Record<string, unknown> | Array<unknown>;
|
|
20
54
|
};
|
|
@@ -57,6 +91,10 @@ export type CraftyMediaCollection = {
|
|
|
57
91
|
export type CraftyMediaFile = {
|
|
58
92
|
id: number;
|
|
59
93
|
file_name: string;
|
|
94
|
+
/** Alt text for `<img alt>`; `null` when none was set. */
|
|
95
|
+
alt: string | null;
|
|
96
|
+
/** `true` when `alt` was suggested by AI and not edited since. */
|
|
97
|
+
alt_generated: boolean;
|
|
60
98
|
file_path: string;
|
|
61
99
|
url: string;
|
|
62
100
|
mime_type: string;
|
|
@@ -65,8 +103,50 @@ export type CraftyMediaFile = {
|
|
|
65
103
|
directory_id: number | null;
|
|
66
104
|
is_public: boolean;
|
|
67
105
|
expires_at: string | null;
|
|
106
|
+
/**
|
|
107
|
+
* Cloudflare zone origin that resizes this image via `/cdn-cgi/image/...`.
|
|
108
|
+
* Set only for public raster images when image transformations are enabled
|
|
109
|
+
* on the Crafty server; use `crafty.image()` instead of reading it directly.
|
|
110
|
+
*/
|
|
111
|
+
image_transform_base?: string | null;
|
|
68
112
|
created_at: string | null;
|
|
69
113
|
};
|
|
114
|
+
/**
|
|
115
|
+
* A media file embedded in page block or entry data: a `reference` /
|
|
116
|
+
* `multiReference` field with `model: "Media"` adds `<field>_media`
|
|
117
|
+
* with this shape (a list for `multiReference`).
|
|
118
|
+
*/
|
|
119
|
+
export type CraftyMediaReference = {
|
|
120
|
+
id: number;
|
|
121
|
+
url: string;
|
|
122
|
+
file_name: string;
|
|
123
|
+
/** Alt text for `<img alt>`; `null` when none was set. */
|
|
124
|
+
alt: string | null;
|
|
125
|
+
mime_type: string | null;
|
|
126
|
+
size: number;
|
|
127
|
+
is_public: boolean;
|
|
128
|
+
/** See `CraftyMediaFile.image_transform_base`. */
|
|
129
|
+
image_transform_base?: string | null;
|
|
130
|
+
};
|
|
131
|
+
/** Anything `crafty.image()` / `crafty.srcset()` can turn into a URL. */
|
|
132
|
+
export type CraftyImageSource = {
|
|
133
|
+
url: string;
|
|
134
|
+
image_transform_base?: string | null;
|
|
135
|
+
} | string | null | undefined;
|
|
136
|
+
/** How the image fits `width` x `height` (Cloudflare `fit`). */
|
|
137
|
+
export type CraftyImageFit = "scale-down" | "contain" | "cover" | "crop" | "pad";
|
|
138
|
+
/** Output format; `auto` serves AVIF or WebP when the browser accepts it. */
|
|
139
|
+
export type CraftyImageFormat = "auto" | "webp" | "avif" | "jpeg" | "png";
|
|
140
|
+
export type CraftyImageOptions = {
|
|
141
|
+
/** Target width in CSS pixels, 1 to 4096. */
|
|
142
|
+
width?: number;
|
|
143
|
+
/** Target height in CSS pixels, 1 to 4096. */
|
|
144
|
+
height?: number;
|
|
145
|
+
fit?: CraftyImageFit;
|
|
146
|
+
/** Compression quality, 1 to 100. */
|
|
147
|
+
quality?: number;
|
|
148
|
+
format?: CraftyImageFormat;
|
|
149
|
+
};
|
|
70
150
|
export type PaginationLinks = {
|
|
71
151
|
first: string | null;
|
|
72
152
|
last: string | null;
|
|
@@ -81,13 +161,26 @@ export type PaginationMeta = {
|
|
|
81
161
|
to: number | null;
|
|
82
162
|
total: number;
|
|
83
163
|
};
|
|
164
|
+
/**
|
|
165
|
+
* Present on entry, page and form responses of a site with locales configured.
|
|
166
|
+
* `translations` (show endpoints only) lists the locales the item has
|
|
167
|
+
* content in, default included: handy for `hreflang` links.
|
|
168
|
+
*/
|
|
169
|
+
export type CraftyLocaleMeta = {
|
|
170
|
+
/** Locale the content was served in (the default when `locale` was omitted or unsupported). */
|
|
171
|
+
locale: string;
|
|
172
|
+
default_locale: string;
|
|
173
|
+
locales: string[];
|
|
174
|
+
translations?: string[];
|
|
175
|
+
};
|
|
84
176
|
export type PaginatedResponse<T> = {
|
|
85
177
|
data: T[];
|
|
86
178
|
links: PaginationLinks;
|
|
87
|
-
meta: PaginationMeta
|
|
179
|
+
meta: PaginationMeta & Partial<CraftyLocaleMeta>;
|
|
88
180
|
};
|
|
89
181
|
export type SingleResponse<T> = {
|
|
90
182
|
data: T;
|
|
183
|
+
meta?: CraftyLocaleMeta;
|
|
91
184
|
};
|
|
92
185
|
export type CollectionListResponse = {
|
|
93
186
|
data: CraftyCollection[];
|
|
@@ -121,7 +214,35 @@ export type MediaFileListResponse = {
|
|
|
121
214
|
ttl_minutes: number;
|
|
122
215
|
};
|
|
123
216
|
};
|
|
217
|
+
export type CraftyAnalytics = {
|
|
218
|
+
gtm_container_id: string | null;
|
|
219
|
+
ga4_measurement_id: string | null;
|
|
220
|
+
meta_pixel_id: string | null;
|
|
221
|
+
tiktok_pixel_id: string | null;
|
|
222
|
+
configured: boolean;
|
|
223
|
+
/** Loaders to render before `</head>`; "" when nothing is configured. */
|
|
224
|
+
head: string;
|
|
225
|
+
/** `<noscript>` fallbacks to render right after `<body>`; "" when there are none. */
|
|
226
|
+
body: string;
|
|
227
|
+
};
|
|
228
|
+
export type CraftyAnalyticsResponse = SingleResponse<CraftyAnalytics>;
|
|
229
|
+
export type CraftyAssistant = {
|
|
230
|
+
/** True when the environment shows the widget (assistant on, or WhatsApp-only). */
|
|
231
|
+
installed: boolean;
|
|
232
|
+
/** "assistant" answers with AI, "whatsapp" shows only the WhatsApp button, "off" shows nothing. */
|
|
233
|
+
mode: "assistant" | "whatsapp" | "off";
|
|
234
|
+
script_url: string;
|
|
235
|
+
site: string;
|
|
236
|
+
environment: string;
|
|
237
|
+
/** Base URL of the public API the widget talks to. */
|
|
238
|
+
api_url: string;
|
|
239
|
+
/** Loader `<script>` to render right before `</body>`; "" when not installed. */
|
|
240
|
+
html: string;
|
|
241
|
+
};
|
|
242
|
+
export type CraftyAssistantResponse = SingleResponse<CraftyAssistant>;
|
|
124
243
|
export type EntriesListQuery = {
|
|
244
|
+
/** Case-insensitive text search over the collection's text fields (2 to 100 characters). */
|
|
245
|
+
q?: string;
|
|
125
246
|
sort_by?: string;
|
|
126
247
|
sort_order?: "asc" | "desc";
|
|
127
248
|
per_page?: number;
|
|
@@ -149,6 +270,8 @@ export type CraftyForm = {
|
|
|
149
270
|
name: string;
|
|
150
271
|
slug: string;
|
|
151
272
|
description: string | null;
|
|
273
|
+
/** Message to show after a successful submission, when the form has one. */
|
|
274
|
+
success_message?: string;
|
|
152
275
|
fields: Record<string, CraftyFormField>;
|
|
153
276
|
status: "draft" | "published";
|
|
154
277
|
hcaptcha_enabled: boolean;
|
|
@@ -159,11 +282,22 @@ export type CraftyFormField = {
|
|
|
159
282
|
label: string;
|
|
160
283
|
type: "text" | "textarea" | "email" | "tel" | "number" | "select" | "checkbox" | "radio" | "date";
|
|
161
284
|
required: boolean;
|
|
285
|
+
placeholder?: string;
|
|
286
|
+
help_text?: string;
|
|
287
|
+
/** Replaces every validation message of the field. */
|
|
288
|
+
error_message?: string;
|
|
289
|
+
/** Options to show, in the requested locale on sites with locales. */
|
|
162
290
|
options?: string[];
|
|
291
|
+
/**
|
|
292
|
+
* Values to submit for `options`, in the same order. Present on sites with
|
|
293
|
+
* locales; submitting the translated option works too.
|
|
294
|
+
*/
|
|
295
|
+
option_values?: string[];
|
|
163
296
|
order: number;
|
|
164
297
|
};
|
|
165
298
|
export type FormListResponse = {
|
|
166
299
|
data: CraftyForm[];
|
|
300
|
+
meta?: CraftyLocaleMeta;
|
|
167
301
|
};
|
|
168
302
|
export type FormShowResponse = SingleResponse<CraftyForm>;
|
|
169
303
|
export type FormSubmitData = Record<string, unknown>;
|
|
@@ -171,6 +305,8 @@ export type FormSubmitResponse = {
|
|
|
171
305
|
id: number;
|
|
172
306
|
form_id: number;
|
|
173
307
|
submitted_at: string;
|
|
308
|
+
/** The form's success message in the submission locale, when it has one. */
|
|
309
|
+
message?: string;
|
|
174
310
|
};
|
|
175
311
|
export type CraftyClientConfig = {
|
|
176
312
|
baseUrl: string;
|
|
@@ -195,11 +331,19 @@ export type CraftyClientConfig = {
|
|
|
195
331
|
preview?: string | false | null;
|
|
196
332
|
/** Called when the API answers `X-Crafty-Preview-Status: invalid` to a request that carried a token. */
|
|
197
333
|
onPreviewInvalid?: () => void;
|
|
334
|
+
/**
|
|
335
|
+
* Default locale for entries, pages and forms, e.g. "en" or "pt-BR". Fields
|
|
336
|
+
* without a translation fall back to the site's default locale. Sites
|
|
337
|
+
* without locales ignore it.
|
|
338
|
+
*/
|
|
339
|
+
locale?: string;
|
|
198
340
|
};
|
|
199
341
|
export type RequestOptions = {
|
|
200
342
|
signal?: AbortSignal;
|
|
201
343
|
headers?: HeadersInit;
|
|
202
344
|
timeoutMs?: number;
|
|
345
|
+
/** Locale for this request (entries, pages and forms), overriding the client's `locale`. */
|
|
346
|
+
locale?: string;
|
|
203
347
|
};
|
|
204
348
|
export type JsonRecord = Record<string, unknown>;
|
|
205
349
|
//# sourceMappingURL=public.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/types/public.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAA+C,MAAM,aAAa,CAAC;AAE5F,YAAY,EACV,WAAW,EACX,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/types/public.ts"],"names":[],"mappings":"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"}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const SDK_VERSION = "0.
|
|
1
|
+
export declare const SDK_VERSION = "0.8.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@craftware/crafty-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"codegen": "node scripts/codegen.mjs",
|
|
37
37
|
"changeset": "npx -y @changesets/cli@2.29.7",
|
|
38
38
|
"changeset:add": "npm run changeset -- add",
|
|
39
|
-
"changeset:version": "npm run changeset -- version"
|
|
39
|
+
"changeset:version": "npm run changeset -- version && node scripts/write-version.mjs"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"esbuild": "^0.28.2",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: crafty-cms
|
|
3
|
-
description: "Build on Crafty CMS — configure sites, pages, blocks, collections, entries, forms, and media through the Crafty MCP server, then develop a frontend with the @craftware/crafty-sdk JavaScript SDK. Use when connecting an agent to a Crafty MCP server; calling Crafty MCP tools like list_sites, create_page, create_block_type, publish_form, upload_media, or request_media_upload; modelling site content with block types (repeater and stringList fields); installing or importing @craftware/crafty-sdk or createCraftyClient; fetching Crafty pages, entries, collections, or media; rendering page blocks; submitting Crafty forms; or preparing a site for the Crafty visual editor (crafty.attrs, enableVisualEditing, preview tokens, configure_visual_editor)."
|
|
3
|
+
description: "Build on Crafty CMS — start a new site from an official starter with `npm create crafty`, configure sites, pages, blocks, collections, entries, forms, and media through the Crafty MCP server, then develop a frontend with the @craftware/crafty-sdk JavaScript SDK. Use when starting a new Crafty site or project (npm create crafty, crafty create, starters); connecting an agent to a Crafty MCP server; calling Crafty MCP tools like list_sites, create_page, create_block_type, publish_form, upload_media, or request_media_upload; modelling site content with block types (repeater and stringList fields); installing or importing @craftware/crafty-sdk or createCraftyClient; fetching Crafty pages, entries, collections, or media; rendering page blocks; submitting Crafty forms; or preparing a site for the Crafty visual editor (crafty.attrs, enableVisualEditing, preview tokens, configure_visual_editor)."
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
6
|
author: craftware
|
|
@@ -15,15 +15,36 @@ Crafty is a headless, multi-tenant CMS. There are two integration surfaces, and
|
|
|
15
15
|
| **MCP server** | Author and configure content | Bearer token (PAT or OAuth), scoped | Create sites, pages, blocks, collections, entries, forms; upload media; publish |
|
|
16
16
|
| **`@craftware/crafty-sdk`** | Read published content into an app | `X-API-Key` environment token | Fetch pages/blocks, entries, collections, media; submit forms from a site |
|
|
17
17
|
|
|
18
|
-
The normal flow is **configure with the MCP server → build a frontend with the SDK**.
|
|
18
|
+
The normal flow is **configure with the MCP server → build a frontend with the SDK**. For a **new site**, `npm create crafty` does both in one step (see [Start a new site](#start-a-new-site)).
|
|
19
19
|
|
|
20
20
|
## When to Use
|
|
21
21
|
|
|
22
|
+
- Starting a new Crafty site or frontend project from scratch (`npm create crafty`, `crafty create`, official starters).
|
|
22
23
|
- Connecting Claude, Cursor, VS Code, Codex, or ChatGPT to a Crafty tenant's MCP server.
|
|
23
24
|
- Driving Crafty MCP tools (`list_sites`, `create_page`, `create_entry`, `create_form`, `publish_page`, `upload_media`, …).
|
|
24
25
|
- Installing or importing `@craftware/crafty-sdk` / `createCraftyClient`.
|
|
25
26
|
- Fetching Crafty pages, entries, collections, or media in app code, or submitting a Crafty form.
|
|
26
27
|
|
|
28
|
+
## Start a new site
|
|
29
|
+
|
|
30
|
+
When the user wants a **new** site (not Crafty added to an existing frontend), don't model content and write the frontend by hand: scaffold it from an official starter.
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm create crafty@latest mi-sitio -- --url=https://<tenant>.crafty.do
|
|
34
|
+
# same flow: npx @craftware/crafty-cli create mi-sitio --url=https://<tenant>.crafty.do
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
It asks for the framework and template (today: Astro, `astro-services` = "sitio de servicios"; Next.js and Nuxt are coming), logs in through the browser (device flow; the user approves, an admin account is needed), creates the site with the starter's block types, collections, form and demo content, configures the visual editor routes, and writes `.env` (`CRAFTY_API_URL`, `CRAFTY_API_KEY`, `CRAFTY_SITE`), `crafty.json` and `src/crafty.types.ts`. Then:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
cd mi-sitio && npm install && npm run dev # npm run deploy → Crafty Hosting
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- Flags (after `--`): `--url`, `--framework=astro`, `--template=astro-services`, `--name`, `--site=<slug>`, `--draft` (keep demo content as drafts; by default it is published so the static build shows it), `--yes` (no prompts). Agents should pass `--url` and `--yes` so nothing blocks on a prompt; the browser approval still needs the user.
|
|
44
|
+
- The command is interactive only for the login: tell the user to open the printed URL and approve the code.
|
|
45
|
+
- After it finishes, **read the project's `AGENTS.md`** and follow its conventions (one renderer per block type in `src/render/blocks/`, routes in `src/lib/routes.ts`, `npm run types` after changing the content model) instead of the generic steps in Phase 2.
|
|
46
|
+
- If the site slug already exists it fails before creating anything; if provisioning fails midway it names the half-created site: delete it in the panel or rerun with another `--site`.
|
|
47
|
+
|
|
27
48
|
## Scope
|
|
28
49
|
|
|
29
50
|
- **In scope:** using a *deployed* Crafty tenant via its MCP server and the published SDK.
|
|
@@ -35,7 +56,7 @@ The normal flow is **configure with the MCP server → build a frontend with the
|
|
|
35
56
|
- **Page** — a web page in a site; `draft` or `published`; composed of ordered **Blocks**.
|
|
36
57
|
- **Block** — a content unit on a page; its **BlockType** defines the data schema. Block types can be created and edited over MCP (`create_block_type`, `update_block_type`).
|
|
37
58
|
- **Collection** — a structured content schema (e.g. "Blog Posts"); defines the fields **Entries** must have.
|
|
38
|
-
- **Entry** — one record in a collection (e.g. a single post). Belongs to a site and a collection.
|
|
59
|
+
- **Entry** — one record in a collection (e.g. a single post). Belongs to a site and a collection; `draft` or `published` (new entries start as drafts; only published entries reach the SDK).
|
|
39
60
|
- **Form** — a contact/feedback form in a site; `draft` or `published`. Published forms accept **public** submissions without auth.
|
|
40
61
|
- **Form Submission** — visitor-submitted data; read-only after creation.
|
|
41
62
|
- **Media** — files attached to a site via the Spatie Media Library.
|
|
@@ -49,15 +70,34 @@ Why: page blocks are validated against their schema on write, show up in the vis
|
|
|
49
70
|
How to model it:
|
|
50
71
|
|
|
51
72
|
- **One block type per section** (`hero`, `stats`, `solutions`, `footer`, …); the block type `slug` is what `page.block("hero")` / `page.blocksOf("solutions")` look up in the SDK.
|
|
52
|
-
- **Lists of items → a `repeater` field**, not a `json` field and not a collection: `items: repeater { icon, title, text, tags: stringList }`. One level only (a repeater cannot contain another repeater), subfield types: `string`, `text`, `longText`, `url`, `number`, `boolean`, `
|
|
73
|
+
- **Lists of items → a `repeater` field**, not a `json` field and not a collection: `items: repeater { icon, title, text, tags: stringList }`. One level only (a repeater cannot contain another repeater), subfield types: `string`, `text`, `longText`, `url`, `number`, `decimal`, `boolean`, `select`, `reference` (incl. `model: "Media"` for an image per item), `stringList`. Optional `min` / `max` item limits.
|
|
53
74
|
- **`url` fields** (top level or in a repeater) accept http(s) URLs, `mailto:`, `tel:`, `#anchors` and site-relative paths starting with `/` (`mailto:` allows one recipient, `tel:` needs at least 3 digits, IDN hosts are converted to punycode when validated); anything else (`javascript:`, `//host`, other schemes) is rejected.
|
|
54
75
|
- **List of plain strings → `stringList`** (`["AI", "Cloud"]`).
|
|
76
|
+
- **Numbers**: `number` holds integers only; prices, ratings and measures are `decimal` (`{ key: "price", type: "decimal", min: 0, precision: 2 }`). Both take optional `min` / `max`; `precision` is the maximum number of decimal places.
|
|
77
|
+
- **Fixed choices → `select`**: `{ key: "condition", type: "select", options: ["new", { value: "used", label: "Used" }] }` stores one option value; add `multiple: true` to store an array of distinct values. Options are strings or `{ value, label }` and must be unique.
|
|
78
|
+
- **Images and files → media references, never `url` or `string` fields.** Upload the file first (see "Media" below), then store its id:
|
|
79
|
+
- one image (logo, hero, avatar, `og:image`): `{ key: "image", type: "reference", model: "Media" }`, value `42`;
|
|
80
|
+
- several images (gallery, slider, logo wall): `{ key: "gallery", type: "multiReference", model: "Media" }`, value `[42, 43, 44]`;
|
|
81
|
+
- an image per repeater item: a `reference` subfield with `model: "Media"` (`multiReference` is top-level only).
|
|
82
|
+
|
|
83
|
+
The public API returns the id under the field key and adds `<key>_media` with the file (`{ id, url, file_name, alt, mime_type, size, is_public, image_transform_base }`, a list for `multiReference`), so the frontend renders `crafty.image(block.data.image_media, { width: 800, format: "auto" })` with `alt={block.data.image_media?.alt ?? ""}`. Editors get a media picker in the panel and the visual editor can swap the image. A `photo_url` string field gives them none of that and breaks when the file moves.
|
|
55
84
|
- **Shared data** (address, phone, social links, footer text used in several places): block types have no global blocks. Put it in a dedicated page (e.g. slug `site-settings`) with one `site-settings` block and read it with `crafty.pages.get("site-settings")`.
|
|
56
|
-
- **Languages**: pages
|
|
85
|
+
- **Languages**: do not duplicate pages per language. Set the site's locales (`configure_locales`, e.g. default `es` plus `en`), write the default-locale content as usual, then add each translation with `upsert_translation` (entries; pages with their blocks by id). The frontend passes `locale` (`createCraftyClient({ locale })` or per call) and untranslated fields fall back to the default. Mark fields that must never change per language (SKU, codes) with `translatable: false`. `meta.translations` on `get()` lists the locales an item has, for `hreflang`. When AI translation is enabled for the workspace (from Crafty central) and for the site (`configure_translation` with `enabled: true`), `translate_content` translates an entry or page (with its blocks) into the site's locales without overwriting what a person wrote, and `configure_translation` also turns on re-translation after every change plus a glossary of untranslated terms.
|
|
57
86
|
- There is no `json` field type in block types. If you catch yourself wanting one, model it as a repeater or `stringList`.
|
|
87
|
+
- **References to records**: `{ type: "reference", collection: "<collection slug>" }` (one entry) or `multiReference` (several); the API expands them into the referenced entries.
|
|
58
88
|
|
|
59
89
|
Use a **collection** only when the content is a large set of independent records that you list, filter, sort or paginate through the API (`entries.list`) — for example blog posts or a product catalogue — or when many different pages reference the same record. A handful of cards, team members or FAQs inside a page is a repeater, not a collection.
|
|
60
90
|
|
|
91
|
+
**Collection fields use the same types as block types, plus `json`**: `string`, `text`, `longText`, `url`, `number` (integer), `decimal`, `boolean`, `datetime`, `select`, `json`, `reference`, `multiReference`, `stringList`, `repeater` (same one-level rules and subfield types as in block types; a Media `reference` subfield gets `<subkey>_media` in the API). Do not fall back to `json` for lists in a collection — a `json` field is a raw JSON textarea in the panel, with no inputs, no validation of its contents and no media picker. Instead:
|
|
92
|
+
|
|
93
|
+
- product photos, gallery → `multiReference` with `model: "Media"` (one cover image → `reference` with `model: "Media"`);
|
|
94
|
+
- tags, categories, related products, authors → `multiReference` (or `reference`) with `collection: "<slug>"` pointing at a small collection of those records; a short fixed list of labels (sizes, colors) → `select` with `multiple: true` or a `stringList`;
|
|
95
|
+
- a short fixed set of attributes (price, sku, color) → one scalar field each (`decimal` for the price, `select` for a fixed set of values);
|
|
96
|
+
- a list of rich items per entry (specs, itinerary days, FAQ of a product) → a `repeater` field on the collection;
|
|
97
|
+
- a list of rich items that only appears inside one page → a block type `repeater`, not a collection.
|
|
98
|
+
|
|
99
|
+
Use `json` only for machine data no editor maintains (e.g. a map's coordinates array imported from elsewhere), and say so to the user when you do.
|
|
100
|
+
|
|
61
101
|
## Phase 1 — Configure content via the MCP server
|
|
62
102
|
|
|
63
103
|
Connect once, then drive the tools. Minimal connect with a Personal Access Token (Claude Code shown):
|
|
@@ -78,16 +118,20 @@ Canonical authoring workflow (exact tool names):
|
|
|
78
118
|
|
|
79
119
|
Block types: `get_block_type` (`site_id` + `block_type_id` or `slug`) → `create_block_type` → `update_block_type` (`fields` replaces ALL fields; removing or retyping a field that blocks already fill needs `force: true`, and existing block data is never rewritten) → `delete_block_type` (`confirm: true`, refused while blocks use it).
|
|
80
120
|
|
|
81
|
-
Collections/entries: `list_collections` → `create_entry` (`collection_slug`, `site_id`, `slug`, `data`) → `update_entry` (snapshots a revision).
|
|
121
|
+
Collections/entries: `list_collections` → `create_entry` (`collection_slug`, `site_id`, `slug`, `data`, optional `status: "draft"` to prepare it unpublished) → `update_entry` (snapshots a revision) → `publish_entry` / `unpublish_entry`. To publish or unpublish a page or entry at a given time, use `schedule_publication` (`publish_at` / `unpublish_at`).
|
|
82
122
|
Forms: `create_form` (`site_id`, `name`, `slug`, `fields`) → `publish_form` → `list_form_submissions`.
|
|
83
|
-
Media: `upload_media` (`url`, `site_id`, optional `collection_name`, `sha256`) takes an http(s) URL or a small base64 data URI (256 KB decoded). For a **local binary file** call `request_media_upload` (`site_id`, `file_name`, `sha256`, optional `collection_name`) and run the returned `curl -T` command from your shell; the bytes never pass through the model and the upload is verified against the sha256. Files land on a public disk only if the `collection_name` repository is public — create or change it with `manage_media_collection` (`site_id`, `key`, `is_public`) BEFORE uploading.
|
|
123
|
+
Media: upload files before you fill content, and put the returned media `id` in `reference` / `multiReference` fields with `model: "Media"` (`list_media` lists existing ids). `upload_media` (`url`, `site_id`, optional `collection_name`, `sha256`) takes an http(s) URL or a small base64 data URI (256 KB decoded). For a **local binary file** call `request_media_upload` (`site_id`, `file_name`, `sha256`, optional `collection_name`) and run the returned `curl -T` command from your shell; the bytes never pass through the model and the upload is verified against the sha256. Files land on a public disk only if the `collection_name` repository is public — create or change it with `manage_media_collection` (`site_id`, `key`, `is_public`) BEFORE uploading. **Always set alt text on content images**: pass `alt` (a concise description of what the image shows, in the site language, max 500 characters) to `upload_media` / `request_media_upload`, or set it later with `update_media` (`site_id`, `media_id`, `alt`); `list_media` shows `alt: null` for files still missing it. Purely decorative images may keep `alt` empty.
|
|
84
124
|
Cache: `set_api_cache_status` (`site_id`, `enabled`) to toggle per-site; `flush_api_cache` (`site_id`, optional `resource`) to invalidate cached responses after bulk edits.
|
|
85
125
|
Visual editor: `configure_visual_editor` (`site_id`, optional `environment`, `frontend_url`, `routes`, `render_mode`, `upload_media_collection`) — see `references/visual-editor.md`.
|
|
86
126
|
|
|
87
127
|
> `update_page` **replaces all blocks** when `blocks` is supplied (send every block again with its `id` to keep it). `update_entry` creates a revision. `create_page` always starts as `draft`.
|
|
88
128
|
|
|
129
|
+
Migrating an existing site (WordPress, Webflow, a static site…)? Don't recreate it by hand: follow `references/migrate-to-crafty.md` — it uses `bulk_upsert_entries` (100 entries per call, drafts, `dry_run`), `import_media_from_urls` (50 URLs per call, deduplicated) and `upsert_redirects` so old URLs keep working.
|
|
130
|
+
|
|
89
131
|
## Phase 2 — Build a frontend with the SDK
|
|
90
132
|
|
|
133
|
+
Starting a new site from scratch? Use `npm create crafty` ([Start a new site](#start-a-new-site)) and follow the starter's `AGENTS.md` instead of the steps below. Adding Crafty to an existing frontend:
|
|
134
|
+
|
|
91
135
|
```bash
|
|
92
136
|
npm install @craftware/crafty-sdk
|
|
93
137
|
```
|
|
@@ -109,10 +153,16 @@ const hero = page.block("hero"); // first block of that type, or null
|
|
|
109
153
|
const posts = await crafty.entries.list("posts", { per_page: 15 });
|
|
110
154
|
```
|
|
111
155
|
|
|
156
|
+
**Generate types before writing code against the content.** Field shapes depend on the site's collections and block types — do not guess them. Run `npx @craftware/crafty-cli types` (reads `CRAFTY_API_URL` + `CRAFTY_API_KEY` from `.env`, or pass `--url` / `--api-key`; `--out` changes the file) to write `crafty.types.ts` with `<Slug>Entry` per collection, `<Slug>BlockData` / `<Slug>Block` per block type and the `CraftyPageBlock` union; cast SDK results to them (`page.blocks as unknown as CraftyPageBlock[]`). Types follow the API key's environment (staging may differ from production); re-run it after `create_block_type` / `update_block_type` / `update_collection`. The raw JSON Schema is `GET /api/v1/schema`. Details: `references/sdk-development.md`.
|
|
157
|
+
|
|
158
|
+
Images: render every Crafty image with `crafty.image(media, { width, format: "auto" })` and `crafty.srcset(media, [400, 800, 1200], { format: "auto" })` instead of the raw `url`; they return resized AVIF/WebP URLs when the server has image transformations enabled and fall back to the original `url` otherwise. Never hand-build `/cdn-cgi/image/` URLs.
|
|
159
|
+
|
|
112
160
|
`pages.get()` returns the page enriched with block helpers (`page.block(type)`, `page.blocksOf(type)`, `page.byType`, …). **Full client config, every resource and return shape, block helpers, errors, and an end-to-end example: read `references/sdk-development.md`.**
|
|
113
161
|
|
|
114
162
|
Serving `llms.txt` / `llms-full.txt` for AI agents and crawlers: `crafty.llms.handler()` as a route (Next/Astro/Nuxt), or `crafty.llms.index()` / `full()` written into `dist/` for a static build. Title, summary, language, and routeless collections are configured on the "llms.txt" admin screen or the `configure_llms` MCP tool. **Full API, per-framework wiring, and error handling: `references/sdk-development.md`.**
|
|
115
163
|
|
|
164
|
+
Analytics and ad pixels (Google Tag Manager, GA4, Meta Pixel, TikTok Pixel): do **not** hard-code their snippets into the site. Set the IDs on the "Analítica" admin screen or with the `configure_analytics` MCP tool; Crafty hosting injects the official loaders into every HTML page on the next deploy. If the site already loads GA4 or pixels through GTM, set only the GTM container. Hosted elsewhere: render `(await crafty.analytics.get()).head` before `</head>` in SSR, or call `crafty.analytics.load()` once in the browser (it skips itself when the deploy already injected them). **Details: `references/sdk-development.md`.**
|
|
165
|
+
|
|
116
166
|
## Phase 3 — Deploy a static site with the CLI
|
|
117
167
|
|
|
118
168
|
```bash
|
|
@@ -163,12 +213,16 @@ These are two different credentials — do not mix them:
|
|
|
163
213
|
- **Wrong tenant host** → the MCP endpoint won't resolve. Use the exact `https://<tenant-domain>/mcp`; each tenant has its own endpoint.
|
|
164
214
|
- **401 from the MCP server** → the Bearer token is missing, invalid, or expired; reconnect or regenerate it.
|
|
165
215
|
- **A tool is missing or fails with "Insufficient OAuth scope"** → the token lacks that tool's scope; re-issue it with `crafty:write` / `crafty:publish` / `crafty:submissions` as needed.
|
|
166
|
-
- **`forms.submit()` throws `BAD_REQUEST`** → `siteSlug` was not set in `createCraftyClient()`. Submissions hit the public endpoint
|
|
216
|
+
- **`forms.submit()` throws `BAD_REQUEST`** → `siteSlug` was not set in `createCraftyClient()`. Submissions hit the public endpoint; the API key, when set, only picks the environment the submission lands in.
|
|
167
217
|
- **`update_entry` / `update_page` wipe fields you don't send** → both MCP tools do a **full replace**, not a merge. If you send only the new fields, all existing fields are deleted in that revision. Always fetch the current entry first (`get_entry`), merge your changes into the full field map, then call `update_entry` with the complete merged object. Entry `data` is validated against the collection schema: invalid values are rejected and undeclared keys are dropped (listed in `warnings`).
|
|
168
|
-
- **`create_page` / `update_page` reject block data** → block data is validated against the block type (`blocks.2.data.items.1.title: …`), `number` fields are integers, `string` fields max 255 characters, and `block_type_id` must belong to the same site. Read the schema with `get_block_type` first.
|
|
218
|
+
- **`create_page` / `update_page` reject block data** → block data is validated against the block type (`blocks.2.data.items.1.title: …`), `number` fields are integers (use `decimal` for prices), `select` values must be one of the declared options, `string` fields max 255 characters, and `block_type_id` must belong to the same site. Read the schema with `get_block_type` first.
|
|
169
219
|
- **Data silently missing from a block** → keys not declared in the block type are dropped; check the `warnings` array in the response.
|
|
170
|
-
- **Modelled a list as a collection or a `json` field** → use a block type with a `repeater` (or `stringList`) instead; see "Model content with block types first".
|
|
171
|
-
- **
|
|
220
|
+
- **Modelled a list as a collection or a `json` field** → use a block type with a `repeater` (or `stringList`) instead; see "Model content with block types first". Inside a collection, use a `repeater`, `stringList`, `select` with `multiple: true` or `multiReference` (to media or to another collection) instead of `json`.
|
|
221
|
+
- **Guessed a field name or shape (`block.data.title` vs `heading`, a select value, `image` vs `image_media.url`)** → generate `crafty.types.ts` with `crafty types` and let the compiler catch it.
|
|
222
|
+
- **Stored an image as a `url` / `string` field (`photo_url`, `image`, `logo`)** → upload it to the media library and use a `reference` (`multiReference` for several) with `model: "Media"`; render `crafty.image(<key>_media, { width, format: "auto" })`. Change an existing field with `update_block_type` / `update_collection` and re-save the content with media ids.
|
|
223
|
+
- **Serving the original image (`<img src={media.url}>`)** → large uploads hurt LCP. Use `crafty.image(media, { width, format: "auto" })` plus `crafty.srcset()`; it falls back to `url` when transforms are unavailable.
|
|
224
|
+
- **Uploaded images without alt text** → set `alt` with `update_media` for every content image (`list_media` shows which have `alt: null`) and render `<key>_media.alt` in the frontend's `<img alt>`.
|
|
225
|
+
- **Content not visible via the SDK** → it isn't published. Pages/forms must be published (`publish_page` / `publish_form`); entries created as drafts need `publish_entry`.
|
|
172
226
|
- **Confusing the two tokens** → the SDK `apiKey` (X-API-Key) is not an MCP Bearer token.
|
|
173
227
|
- **Stale skill copy** → a project copy of this skill (e.g. `.claude/skills/crafty-cms`) does not update with the SDK. After upgrading `@craftware/crafty-sdk`, copy `node_modules/@craftware/crafty-sdk/skills/crafty-cms` over it.
|
|
174
228
|
|
|
@@ -176,4 +230,5 @@ These are two different credentials — do not mix them:
|
|
|
176
230
|
|
|
177
231
|
- `references/mcp-configuration.md` — connecting every client, scopes, and the full MCP tool catalog with workflows.
|
|
178
232
|
- `references/sdk-development.md` — the complete SDK surface, block helpers, error handling, and examples.
|
|
233
|
+
- `references/migrate-to-crafty.md` — migrating an existing site (WordPress or any other) into Crafty: crawl, classify, model, bulk import as drafts, media, redirects, human review, publish.
|
|
179
234
|
- `references/visual-editor.md` — preparing a site for the visual editor: the mandatory question, marking, preview tokens, bridge, headers, `configure_visual_editor`, verification.
|