@webiny/mcp 6.3.0-beta.2 → 6.3.0-beta.3
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/package.json +7 -4
- package/skills/admin/form-model/SKILL.md +527 -0
- package/skills/admin/website-builder/page-settings/SKILL.md +216 -0
- package/skills/api/v5-to-v6-migration/SKILL.md +367 -18
- package/skills/content-models/SKILL.md +261 -23
- package/skills/generated/admin/SKILL.md +16 -1
- package/skills/generated/admin/cms/SKILL.md +26 -1
- package/skills/generated/admin/form/SKILL.md +58 -1
- package/skills/generated/admin/ui/SKILL.md +26 -1
- package/skills/generated/admin/website-builder/SKILL.md +11 -1
- package/skills/generated/api/mailer/SKILL.md +74 -0
- package/skills/generated/api/tenant-manager/SKILL.md +36 -1
- package/skills/generated/infra/SKILL.md +3 -6
- package/skills/mailer-smtp/SKILL.md +98 -0
- package/skills/project-structure/SKILL.md +0 -1
- package/skills/webiny-sdk/SKILL.md +111 -3
- package/skills/website-builder/SKILL.md +91 -4
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: webiny-api-tenant-manager-catalog
|
|
3
3
|
context: webiny-api
|
|
4
4
|
description: >
|
|
5
|
-
API — Tenant Manager —
|
|
5
|
+
API — Tenant Manager — 9 abstractions.
|
|
6
6
|
Tenant management event handlers and use cases.
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -19,6 +19,36 @@ Tenant management event handlers and use cases.
|
|
|
19
19
|
|
|
20
20
|
## Abstractions
|
|
21
21
|
|
|
22
|
+
---
|
|
23
|
+
**Name:** `CreateAndInstallTenantUseCase`
|
|
24
|
+
**Import:** `import { CreateAndInstallTenantUseCase } from "webiny/api/tenant-manager"`
|
|
25
|
+
**Source:** `@webiny/tenant-manager/api/features/CreateAndInstallTenant/abstractions.ts`
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
**Name:** `CreateTenantUseCase`
|
|
29
|
+
**Import:** `import { CreateTenantUseCase } from "webiny/api/tenant-manager"`
|
|
30
|
+
**Source:** `@webiny/tenant-manager/api/features/CreateTenant/abstractions.ts`
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
**Name:** `DisableTenantUseCase`
|
|
34
|
+
**Import:** `import { DisableTenantUseCase } from "webiny/api/tenant-manager"`
|
|
35
|
+
**Source:** `@webiny/tenant-manager/api/features/DisableTenant/abstractions.ts`
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
**Name:** `EnableTenantUseCase`
|
|
39
|
+
**Import:** `import { EnableTenantUseCase } from "webiny/api/tenant-manager"`
|
|
40
|
+
**Source:** `@webiny/tenant-manager/api/features/EnableTenant/abstractions.ts`
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
**Name:** `GetCurrentTenantUseCase`
|
|
44
|
+
**Import:** `import { GetCurrentTenantUseCase } from "webiny/api/tenant-manager"`
|
|
45
|
+
**Source:** `@webiny/tenant-manager/api/features/GetCurrentTenant/abstractions.ts`
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
**Name:** `GetTenantByIdUseCase`
|
|
49
|
+
**Import:** `import { GetTenantByIdUseCase } from "webiny/api/tenant-manager"`
|
|
50
|
+
**Source:** `@webiny/tenant-manager/api/features/GetTenantById/abstractions.ts`
|
|
51
|
+
|
|
22
52
|
---
|
|
23
53
|
**Name:** `TenantExtensions`
|
|
24
54
|
**Kind:** type
|
|
@@ -32,3 +62,8 @@ Tenant management event handlers and use cases.
|
|
|
32
62
|
**Description:** Extend the tenant content model with custom fields.
|
|
33
63
|
|
|
34
64
|
---
|
|
65
|
+
**Name:** `UpdateTenantUseCase`
|
|
66
|
+
**Import:** `import { UpdateTenantUseCase } from "webiny/api/tenant-manager"`
|
|
67
|
+
**Source:** `@webiny/tenant-manager/api/features/UpdateTenant/abstractions.ts`
|
|
68
|
+
|
|
69
|
+
---
|
|
@@ -46,8 +46,7 @@ Infrastructure extensions.
|
|
|
46
46
|
---
|
|
47
47
|
**Name:** `AdminPulumi`
|
|
48
48
|
**Import:** `import { AdminPulumi } from "webiny/infra/admin"`
|
|
49
|
-
**Source:** `@webiny/project/abstractions/features/pulumi/AdminPulumi.ts`
|
|
50
|
-
**Description:** Implement this abstraction to add custom Pulumi code to Admin.
|
|
49
|
+
**Source:** `@webiny/project-aws/abstractions/features/pulumi/AdminPulumi.ts`
|
|
51
50
|
|
|
52
51
|
---
|
|
53
52
|
**Name:** `AdminStackOutputService`
|
|
@@ -102,8 +101,7 @@ Infrastructure extensions.
|
|
|
102
101
|
---
|
|
103
102
|
**Name:** `ApiPulumi`
|
|
104
103
|
**Import:** `import { ApiPulumi } from "webiny/infra/api"`
|
|
105
|
-
**Source:** `@webiny/project/abstractions/features/pulumi/ApiPulumi.ts`
|
|
106
|
-
**Description:** Implement this abstraction to add custom Pulumi code to API.
|
|
104
|
+
**Source:** `@webiny/project-aws/abstractions/features/pulumi/ApiPulumi.ts`
|
|
107
105
|
|
|
108
106
|
---
|
|
109
107
|
**Name:** `ApiStackOutputService`
|
|
@@ -153,8 +151,7 @@ Infrastructure extensions.
|
|
|
153
151
|
---
|
|
154
152
|
**Name:** `CorePulumi`
|
|
155
153
|
**Import:** `import { CorePulumi } from "webiny/infra/core"`
|
|
156
|
-
**Source:** `@webiny/project/abstractions/features/pulumi/CorePulumi.ts`
|
|
157
|
-
**Description:** Implement this abstraction to add custom Pulumi code to Core.
|
|
154
|
+
**Source:** `@webiny/project-aws/abstractions/features/pulumi/CorePulumi.ts`
|
|
158
155
|
|
|
159
156
|
---
|
|
160
157
|
**Name:** `CoreStackOutputService`
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: webiny-mailer-smtp
|
|
3
|
+
description: >
|
|
4
|
+
Use when configuring SMTP email/mailer settings in a Webiny project.
|
|
5
|
+
Triggers on: "configure email", "set up SMTP", "mailer config", "sending emails",
|
|
6
|
+
"email not working", "configure mailer", "SMTP password", "Api.Mailer.Smtp".
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Mailer SMTP Configuration
|
|
10
|
+
|
|
11
|
+
## TL;DR
|
|
12
|
+
|
|
13
|
+
Add `<Api.Mailer.Smtp ... />` to your `webiny.config.tsx` to configure SMTP email delivery at build time. The component serializes the settings into the build artifact — always pass the password via an environment variable, never hard-code it. Deploy the API after making changes.
|
|
14
|
+
|
|
15
|
+
## Core Pattern
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { Api } from "@webiny/project-aws/api";
|
|
19
|
+
|
|
20
|
+
<Api.Mailer.Smtp
|
|
21
|
+
host={"smtp.example.com"}
|
|
22
|
+
port={587}
|
|
23
|
+
user={"smtp-user"}
|
|
24
|
+
password={process.env.SMTP_PASSWORD!}
|
|
25
|
+
from={"noreply@example.com"}
|
|
26
|
+
replyTo={"support@example.com"} {/* optional */}
|
|
27
|
+
/>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Place this inside the JSX returned by your config component in `webiny.config.tsx`, alongside other `<Api.*>` extensions.
|
|
31
|
+
|
|
32
|
+
## Props Reference
|
|
33
|
+
|
|
34
|
+
| Prop | Type | Required | Description |
|
|
35
|
+
| ---------- | -------- | -------- | ---------------------------------------------- |
|
|
36
|
+
| `host` | `string` | Yes | SMTP server hostname |
|
|
37
|
+
| `port` | `number` | Yes | SMTP server port (positive integer) |
|
|
38
|
+
| `user` | `string` | Yes | SMTP authentication username |
|
|
39
|
+
| `password` | `string` | Yes | SMTP authentication password — **use env var** |
|
|
40
|
+
| `from` | `string` | Yes | Default sender address |
|
|
41
|
+
| `replyTo` | `string` | No | Default reply-to address |
|
|
42
|
+
|
|
43
|
+
`from` and `replyTo` are validated by the [`email-addresses`](https://www.npmjs.com/package/email-addresses) package against RFC 5322.
|
|
44
|
+
|
|
45
|
+
## Full Example (`webiny.config.tsx`)
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
import React from "react";
|
|
49
|
+
import { Api, Admin, Core } from "@webiny/project-aws/api";
|
|
50
|
+
|
|
51
|
+
const MyConfig = () => {
|
|
52
|
+
return (
|
|
53
|
+
<>
|
|
54
|
+
{/* ... other extensions ... */}
|
|
55
|
+
|
|
56
|
+
{/* Mailer: configure SMTP transport via code */}
|
|
57
|
+
<Api.Mailer.Smtp
|
|
58
|
+
host={"smtp.sendgrid.net"}
|
|
59
|
+
port={587}
|
|
60
|
+
user={"apikey"}
|
|
61
|
+
password={process.env.SENDGRID_API_KEY!}
|
|
62
|
+
from={"noreply@acme.com"}
|
|
63
|
+
replyTo={"support@acme.com"}
|
|
64
|
+
/>
|
|
65
|
+
</>
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Add `SENDGRID_API_KEY=your-secret` to your `.env` file (never commit it).
|
|
71
|
+
|
|
72
|
+
## Common Mistakes
|
|
73
|
+
|
|
74
|
+
| Mistake | Fix |
|
|
75
|
+
| ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
|
|
76
|
+
| Hard-coding the password | Use `process.env.SMTP_PASSWORD!` |
|
|
77
|
+
| `process.env.SMTP_PASSWORD` undefined at build time → "expected string, received object" error | Ensure the env var is set before deploying |
|
|
78
|
+
| `from`/`replyTo` value fails validation | Must be a valid RFC 5322 mailbox address |
|
|
79
|
+
| Settings not taking effect | Run `yarn webiny build api` after editing `webiny.config.tsx` |
|
|
80
|
+
|
|
81
|
+
## Quick Reference
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# After editing webiny.config.tsx, build the API
|
|
85
|
+
yarn webiny build api
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
> **Note:** This command only works in a `dev` environment. For other environments, run `yarn webiny build api --env=YOUR_ENV` instead.
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
// Environment variable in .env
|
|
92
|
+
SMTP_PASSWORD = your - smtp - password - here;
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Related Skills
|
|
96
|
+
|
|
97
|
+
- `webiny-project-structure` — Where `webiny.config.tsx` lives and how extensions are structured
|
|
98
|
+
- `webiny-local-development` — Running and deploying locally
|
|
@@ -26,7 +26,6 @@ my-webiny-project/
|
|
|
26
26
|
│ ├── global.css
|
|
27
27
|
│ ├── index.html
|
|
28
28
|
│ └── robots.txt
|
|
29
|
-
├── eslint.config.js # ESLint configuration
|
|
30
29
|
├── package.json # Single package.json for the whole project
|
|
31
30
|
├── tsconfig.json # Single TypeScript config
|
|
32
31
|
├── webiny.config.tsx # Main configuration -- all extensions registered here
|
|
@@ -6,10 +6,14 @@ description: >
|
|
|
6
6
|
Use this skill when the developer is building a Next.js, Vue, Node.js, or any external app
|
|
7
7
|
that needs to fetch or write content to Webiny, set up the SDK, use the Result pattern,
|
|
8
8
|
list/get/create/update/publish entries, filter and sort queries, use TypeScript generics
|
|
9
|
-
for type safety, work with the File Manager, list languages, trigger or monitor background tasks,
|
|
10
|
-
or create API keys programmatically.
|
|
9
|
+
for type safety, work with the File Manager, list languages, trigger or monitor background tasks, or create API keys programmatically.
|
|
11
10
|
Covers read vs preview mode, the `values` wrapper requirement, correct method names,
|
|
12
|
-
the `fields` required parameter, and background task management via `sdk.tasks`.
|
|
11
|
+
and the `fields` required parameter, and background task management via `sdk.tasks`. Also covers common SDK errors and troubleshooting
|
|
12
|
+
— especially "Content model '<modelName>' not found" (which usually means the API key
|
|
13
|
+
lacks permission, not that the model is missing) and the Website Builder starter
|
|
14
|
+
pitfall of reusing NEXT_PUBLIC_WEBSITE_BUILDER_API_KEY for Headless CMS reads (that key
|
|
15
|
+
has no CMS permissions by default and needs either extension or replacement with a
|
|
16
|
+
CMS-scoped key).
|
|
13
17
|
---
|
|
14
18
|
|
|
15
19
|
# Webiny SDK
|
|
@@ -499,6 +503,110 @@ Abort task: webiny.tasks.abortTask({ id, message? })
|
|
|
499
503
|
Filter logs by task: webiny.tasks.listLogs({ where: { task: "id" } })
|
|
500
504
|
```
|
|
501
505
|
|
|
506
|
+
## Troubleshooting
|
|
507
|
+
|
|
508
|
+
The SDK's error messages describe the _server's_ view of the world, which sometimes hides
|
|
509
|
+
the real cause. The patterns below have all bitten real projects — when you hit one of
|
|
510
|
+
these errors, walk through the checklist before assuming the schema or framework is at
|
|
511
|
+
fault.
|
|
512
|
+
|
|
513
|
+
### `"Content model '<modelName>' not found."`
|
|
514
|
+
|
|
515
|
+
This error literally means the **currently authenticated principal cannot see** a model
|
|
516
|
+
with that ID — not necessarily that the model is missing. There are three things to
|
|
517
|
+
check, in order:
|
|
518
|
+
|
|
519
|
+
1. **Does the model actually exist?** Open Webiny Admin → Headless CMS → Models and
|
|
520
|
+
confirm the `modelId` matches exactly (case-sensitive — `productCategory`, not
|
|
521
|
+
`ProductCategory` or `product-category`).
|
|
522
|
+
2. **Is the model published / not private?** A model that's only created in code but not
|
|
523
|
+
yet deployed (or that's defined as `.private(...)` instead of `.public(...)`) will not
|
|
524
|
+
be visible via the public Read API.
|
|
525
|
+
3. **Does the API key have permission to read this model?** This is by far the most
|
|
526
|
+
common cause when the model clearly exists. The CMS returns "not found" rather than
|
|
527
|
+
"forbidden" on purpose, so an attacker can't probe the schema with an unauthorized
|
|
528
|
+
key. Open Settings → API Keys → _your key_ and verify it has at least:
|
|
529
|
+
- **Headless CMS** access (`cms.contentEntry`, `cms.contentModel`, etc.)
|
|
530
|
+
- The relevant model group selected (or "All groups")
|
|
531
|
+
- For private models: the matching `read` permission scope
|
|
532
|
+
|
|
533
|
+
Fix: grant the missing permission to the key, save, and retry. No code change needed.
|
|
534
|
+
|
|
535
|
+
### Using the wrong API key (Website Builder key for Headless CMS reads)
|
|
536
|
+
|
|
537
|
+
The Website Builder starter ships with `NEXT_PUBLIC_WEBSITE_BUILDER_API_KEY`. That key
|
|
538
|
+
exists for the WB editor itself and, **by default, only has Website Builder permissions
|
|
539
|
+
— it has no access to any Headless CMS models.** Reusing it to power
|
|
540
|
+
`webiny.cms.listEntries(...)` from a Server Component is the most common cause of
|
|
541
|
+
"Content model not found" in WB projects, because to the CMS the request looks just like
|
|
542
|
+
an unauthorized one.
|
|
543
|
+
|
|
544
|
+
You have two ways to fix this:
|
|
545
|
+
|
|
546
|
+
1. **Recommended — use a separate, CMS-scoped API key.** Generate a new key in Webiny
|
|
547
|
+
Admin (Settings → API Keys) granting only the CMS permissions the public site needs
|
|
548
|
+
(typically read on the relevant model groups), expose it as a different env var, and
|
|
549
|
+
pass it into the SDK:
|
|
550
|
+
|
|
551
|
+
```dotenv
|
|
552
|
+
# .env
|
|
553
|
+
NEXT_PUBLIC_WEBSITE_BUILDER_API_KEY=... # for the WB editor only
|
|
554
|
+
WEBINY_CMS_READ_TOKEN=... # for SDK calls from Server Components
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
```typescript
|
|
558
|
+
// lib/webiny.ts
|
|
559
|
+
import { Webiny } from "@webiny/sdk";
|
|
560
|
+
|
|
561
|
+
export const webiny = new Webiny({
|
|
562
|
+
token: process.env.WEBINY_CMS_READ_TOKEN!, // ← NOT the WB key
|
|
563
|
+
endpoint: process.env.NEXT_PUBLIC_WEBSITE_BUILDER_API_HOST!,
|
|
564
|
+
tenant: process.env.NEXT_PUBLIC_WEBSITE_BUILDER_API_TENANT || "root"
|
|
565
|
+
});
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
Keeping read and editor permissions on separate keys is also better for revocation
|
|
569
|
+
and the principle of least privilege.
|
|
570
|
+
|
|
571
|
+
2. **Less recommended — extend the existing WB key with CMS permissions.** Open the WB
|
|
572
|
+
API key in Settings → API Keys and add the required Headless CMS permissions to it.
|
|
573
|
+
This works, but the same token now controls both the editor and public reads, which
|
|
574
|
+
makes scoping and rotation harder later.
|
|
575
|
+
|
|
576
|
+
> **Heads-up:** `NEXT_PUBLIC_*` env vars are inlined into the client bundle by Next.js.
|
|
577
|
+
> Anything you put behind that prefix is publicly visible. A read-only CMS token that's
|
|
578
|
+
> scoped to public content is fine to expose; an editor or write-capable token is not —
|
|
579
|
+
> for those, use a non-`NEXT_PUBLIC_` env var and only read it from Server Components or
|
|
580
|
+
> Route Handlers.
|
|
581
|
+
|
|
582
|
+
### Other quick-hit checks
|
|
583
|
+
|
|
584
|
+
- **`endpoint` has a trailing slash.** The SDK appends `/graphql` itself, so a trailing
|
|
585
|
+
slash produces a malformed URL and every call fails. Strip it.
|
|
586
|
+
- **`tenant` is wrong.** In multi-tenant setups, the default `"root"` tenant won't see
|
|
587
|
+
models defined under another tenant. Confirm the tenant ID matches the one that owns
|
|
588
|
+
the model.
|
|
589
|
+
- **Wrong endpoint host.** WB projects sometimes have separate Admin and Read API
|
|
590
|
+
hostnames. The SDK should always point at the **Read** API (the public CloudFront
|
|
591
|
+
URL), not the Admin host.
|
|
592
|
+
- **`fields` parameter omitted.** This throws at request time with a different message,
|
|
593
|
+
but if you see schema-level errors before any data comes back, double-check that every
|
|
594
|
+
call passes a non-empty `fields: [...]`.
|
|
595
|
+
|
|
596
|
+
## Quick Reference
|
|
597
|
+
|
|
598
|
+
```
|
|
599
|
+
Install: npm install @webiny/sdk
|
|
600
|
+
Import: import { Webiny } from "@webiny/sdk";
|
|
601
|
+
Type import: import type { CmsEntryData } from "@webiny/sdk";
|
|
602
|
+
Initialize: new Webiny({ token, endpoint, tenant })
|
|
603
|
+
Result check: result.isOk() -> result.value.data / result.error.message
|
|
604
|
+
API endpoint: yarn webiny info (in your Webiny project) -- NO trailing slash
|
|
605
|
+
Preview mode: pass preview: true to listEntries / getEntry
|
|
606
|
+
fields required: every method needs a fields: string[] array
|
|
607
|
+
values wrapper: createEntry/updateEntryRevision data must use { values: { ... } }
|
|
608
|
+
```
|
|
609
|
+
|
|
502
610
|
## Related Skills
|
|
503
611
|
|
|
504
612
|
- `webiny-api-cms-content-models` -- Define the models you query with the SDK
|
|
@@ -5,10 +5,13 @@ description: >
|
|
|
5
5
|
Building Website Builder editor components, theming, and CMS integration using
|
|
6
6
|
@webiny/website-builder-nextjs. Use this skill when the developer wants to create editor
|
|
7
7
|
components for the Website Builder, register components with createComponent, define
|
|
8
|
-
configurable inputs (text, number, boolean, color, select, file, slot, lexical
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
configurable inputs (text, number, boolean, color, select, file/image, slot, lexical, object,
|
|
9
|
+
tags), type the component's props correctly (especially file/image inputs, which are objects
|
|
10
|
+
with { src, width, height, ... } and NOT plain strings, and lexical inputs which are
|
|
11
|
+
{ html, state } objects), set up component groups, customize the theme (CSS variables,
|
|
12
|
+
createTheme, Tailwind bridge, fonts), build Server Components that fetch CMS data, or
|
|
13
|
+
understand the WB architecture (Admin iframe + Next.js). Also use for anything related to
|
|
14
|
+
the Website Builder starter kit.
|
|
12
15
|
---
|
|
13
16
|
|
|
14
17
|
# Website Builder
|
|
@@ -167,6 +170,90 @@ Use a namespaced string: `"YourNamespace/ComponentName"`. Component names are st
|
|
|
167
170
|
|
|
168
171
|
Each factory accepts: `name`, `label`, `description`, `defaultValue`, and type-specific options.
|
|
169
172
|
|
|
173
|
+
### TypeScript prop types for each input
|
|
174
|
+
|
|
175
|
+
The input factories above define what the editor sidebar shows. Separately, each input
|
|
176
|
+
produces a value at runtime that's passed into your React component via `props.inputs`.
|
|
177
|
+
**The runtime shape is not always a primitive** — the most important case is `file` /
|
|
178
|
+
image inputs, which are objects, not strings. Typing them as `string` compiles but
|
|
179
|
+
breaks as soon as you try to read `.src`, `.width`, etc.
|
|
180
|
+
|
|
181
|
+
Use this table as the source of truth when you write the `ComponentProps<T>` generic for
|
|
182
|
+
a component. These shapes come from the actual SDK usage (see e.g.
|
|
183
|
+
`@webiny/website-builder-nextjs/editorComponents/Image.d.ts` in the project's
|
|
184
|
+
`node_modules` for the canonical file-input shape).
|
|
185
|
+
|
|
186
|
+
| Input factory | Type of `inputs.<name>` in the component |
|
|
187
|
+
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
188
|
+
| `createTextInput` | `string` |
|
|
189
|
+
| `createLongTextInput` | `string` |
|
|
190
|
+
| `createNumberInput` | `number` |
|
|
191
|
+
| `createBooleanInput` | `boolean` |
|
|
192
|
+
| `createColorInput` | `string` (CSS color value, e.g. `"#4632f5"` or `"var(--wb-theme-color-primary)"`) |
|
|
193
|
+
| `createDateInput` | `string` (ISO-8601, e.g. `"2026-04-16T14:06:00.000Z"`) |
|
|
194
|
+
| `createSelectInput` | `string` (the `value` of the chosen option) |
|
|
195
|
+
| `createRadioInput` | `string` (the `value` of the chosen option) |
|
|
196
|
+
| `createTagsInput` | `string[]` |
|
|
197
|
+
| `createFileInput` | `{ id: string; name: string; size: number; mimeType: string; src: string; width: number; height: number }` — **object, NOT a string.** Use `.src` for the URL. |
|
|
198
|
+
| `createLexicalInput` | `{ html?: string; state?: string }` — render with `<div dangerouslySetInnerHTML={{ __html: inputs.<name>.html ?? "" }} />` |
|
|
199
|
+
| `createObjectInput` | An object literal matching the shape of its nested `fields` (e.g. `{ street: string; city: string; zip: string }`) |
|
|
200
|
+
| `createSlotInput` | `React.ReactNode` (rendered children). With `list: true`, the factory wraps inside the field value — see Grid pattern below. |
|
|
201
|
+
|
|
202
|
+
#### List inputs (`list: true`)
|
|
203
|
+
|
|
204
|
+
When an input is declared with `list: true` (either directly, or via a factory like
|
|
205
|
+
`createTagsInput` which does it internally), the type in the component becomes an array
|
|
206
|
+
of the base type:
|
|
207
|
+
|
|
208
|
+
- `createFileInput({ list: true })` → `Array<{ id; name; src; … }>`
|
|
209
|
+
- `createObjectInput({ name: "rows", list: true, fields: [...] })` → an array of objects
|
|
210
|
+
matching the `fields` shape.
|
|
211
|
+
- `createSlotInput({ name: "columns", list: true, ... })` → an array of `{ children: React.ReactNode }` (see the Grid component in `@webiny/website-builder-react` for the reference pattern).
|
|
212
|
+
|
|
213
|
+
#### Worked example: image + rich-text component
|
|
214
|
+
|
|
215
|
+
```tsx
|
|
216
|
+
import React from "react";
|
|
217
|
+
import type { ComponentProps } from "@webiny/website-builder-nextjs";
|
|
218
|
+
|
|
219
|
+
interface FeatureCardInputs {
|
|
220
|
+
headline: string;
|
|
221
|
+
body: { html?: string };
|
|
222
|
+
image: {
|
|
223
|
+
id: string;
|
|
224
|
+
name: string;
|
|
225
|
+
size: number;
|
|
226
|
+
mimeType: string;
|
|
227
|
+
src: string;
|
|
228
|
+
width: number;
|
|
229
|
+
height: number;
|
|
230
|
+
};
|
|
231
|
+
tags: string[];
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export function FeatureCard({
|
|
235
|
+
inputs: { headline, body, image, tags }
|
|
236
|
+
}: ComponentProps<FeatureCardInputs>) {
|
|
237
|
+
return (
|
|
238
|
+
<article>
|
|
239
|
+
<h3>{headline}</h3>
|
|
240
|
+
{image?.src && (
|
|
241
|
+
<img src={image.src} width={image.width} height={image.height} alt={headline} />
|
|
242
|
+
)}
|
|
243
|
+
{body?.html && <div dangerouslySetInnerHTML={{ __html: body.html }} />}
|
|
244
|
+
<ul>
|
|
245
|
+
{tags.map(tag => (
|
|
246
|
+
<li key={tag}>{tag}</li>
|
|
247
|
+
))}
|
|
248
|
+
</ul>
|
|
249
|
+
</article>
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Note how `image` is typed as the full object, not a plain `string` — otherwise the
|
|
255
|
+
component would compile but blow up at runtime when it tried to read `image.src`.
|
|
256
|
+
|
|
170
257
|
## Component Groups
|
|
171
258
|
|
|
172
259
|
Groups organize the editor's component palette:
|