Skip to content

Commit e041759

Browse files
github-actions[bot]webiny-botadrians5jPavel910
authored
feat: release 6.4.0 (#789)
Co-authored-by: webiny-bot <webiny-bot@webiny.com> Co-authored-by: adrians5j <adrian@webiny.com> Co-authored-by: Pavel Denisjuk <pavel@webiny.com>
1 parent 9fbe974 commit e041759

25 files changed

Lines changed: 728 additions & 0 deletions

AGENTS.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ When editing a generated `changelog.mdx` file, always keep the sibling `changelo
1515
- **Removed entry** → add the PR number(s) to the `## Skipped PRs` section with a short reason
1616
- **Rewritten entry** → add a note to the `## Manual Rewrites` section
1717

18+
**Writing style for changelog entries:**
19+
20+
- Keep entries user-facing — describe the impact for the user, not internal implementation details (e.g. "X wasn't cached, slowing down the API" rather than "X was fetched outside the cache boundary")
21+
- Entry descriptions should be 1-2 sentences. Bullet lists for key changes only when there are multiple distinct sub-items.
22+
1823
The `generate-changelog.ts` script reads `## Skipped PRs` to avoid re-adding manually removed entries on the next run. If `changelog.ai.txt` is not updated, removed PRs will reappear.
1924

2025
### Validation and Quality
@@ -130,6 +135,17 @@ Alert types:
130135

131136
- use <Image/> (src/components/Image.js) component when adding images
132137

138+
#### Video
139+
140+
- use `<Video>` (global MDX component, no import needed) for embedded videos
141+
- Video files must be **imported** as ESM imports, not referenced by string path:
142+
143+
```mdx
144+
import myVideo from "./assets/my-video.mp4";
145+
146+
<Video src={myVideo} controls={true} />
147+
```
148+
133149
### Code Blocks
134150

135151
- Language tag is always specified: ` ```typescript ` or ` ```graphql `
108 KB
Loading
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
---
2+
id: a3f8kd92
3+
title: File URL Formatter
4+
description: Learn how to customize file and image URLs in the Webiny admin app using the FileUrlFormatter extension point.
5+
---
6+
7+
import { Alert } from "@/components/Alert";
8+
import fileUrlFormatter from "./assets/file-url-formatter.png";
9+
10+
<Alert type="success" title="WHAT YOU'LL LEARN">
11+
12+
- what the FileUrlFormatter extension point is and where it applies
13+
- how to implement and register a custom file URL formatter
14+
- how to remap query parameters for your own CDN or image service
15+
16+
</Alert>
17+
18+
## Overview
19+
20+
<Alert type="info">
21+
22+
This extension point is most relevant if you are replacing Webiny's built-in File Manager with your own Digital Asset Manager (DAM). If you are using the default File Manager, no configuration is needed.
23+
24+
</Alert>
25+
26+
File URLs for images displayed in the Admin app pass through the `FileUrlFormatter` extension point before being rendered.
27+
28+
You can customize how those URLs are constructed: remap parameters to your CDN's own syntax, add authentication tokens, rewrite the host, or apply any other transformation your image delivery pipeline requires. For example, `FilePicker` calls `format(url, { width: 128 })` when rendering thumbnails — a custom formatter can intercept that and swap the standard `?width=N` for whatever your CDN expects.
29+
30+
<Alert type="info">
31+
32+
Only one `FileUrlFormatter` is active at a time. When you register your own implementation it replaces the File Manager default — the last implementation registered wins.
33+
34+
</Alert>
35+
36+
## Implement the Formatter
37+
38+
Create an implementation of `FileUrlFormatter`. The `url` object is mutable — modify it in place. `params.width` is the only supported parameter.
39+
40+
```typescript extensions/fileUrlFormatter/MyFileUrlFormatter.ts
41+
import { FileUrlFormatter } from "webiny/admin/file-manager";
42+
43+
class MyFileUrlFormatter implements FileUrlFormatter.Interface {
44+
format(url: URL, params?: FileUrlFormatter.Params): void {
45+
if (params?.width !== undefined) {
46+
url.searchParams.set("my_width", String(params.width));
47+
}
48+
}
49+
}
50+
51+
export const MyFileUrlFormatterImpl = FileUrlFormatter.createImplementation({
52+
implementation: MyFileUrlFormatter,
53+
dependencies: []
54+
});
55+
```
56+
57+
## Register the Formatter
58+
59+
Wrap the implementation in a feature and mount it with `RegisterFeature`:
60+
61+
```tsx extensions/fileUrlFormatter/index.tsx
62+
import React from "react";
63+
import { createFeature, RegisterFeature } from "webiny/admin";
64+
import { MyFileUrlFormatterImpl } from "./MyFileUrlFormatter.js";
65+
66+
const FileUrlFormatterFeature = createFeature({
67+
name: "MyApp/FileUrlFormatter",
68+
register(container) {
69+
container.register(MyFileUrlFormatterImpl).inSingletonScope();
70+
}
71+
});
72+
73+
export default () => <RegisterFeature feature={FileUrlFormatterFeature} />;
74+
```
75+
76+
Then add the extension to your `webiny.config.tsx`:
77+
78+
```tsx webiny.config.tsx
79+
<Admin.Extension src={"@/extensions/fileUrlFormatter/index.tsx"} />
80+
```
81+
82+
With the extension registered, file thumbnails in the Admin app will use your formatter. Here is the result:
83+
84+
<Image src={fileUrlFormatter} alt="File URL Formatter result" />

docs/developer-docs/6.x/navigation.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export const Navigation = ({ children }: { children: React.ReactNode }) => {
4848
<Page link={"admin/whitelabeling"} />
4949
<Page link={"admin/connect-custom-domain"} />
5050
<Page link={"admin/build-params"} />
51+
<Page link={"admin/file-url-formatter"} />
5152
</Group>
5253
<Group
5354
title={"API"}
@@ -125,6 +126,7 @@ export const Navigation = ({ children }: { children: React.ReactNode }) => {
125126
title={"Customize Page List Columns"}
126127
/>
127128
<Page link={"website-builder/event-handlers"} title={"Event Handlers"} />
129+
<Page link={"website-builder/preview-url-modifier"} title={"Preview URL Modifier"} />
128130
</Group>
129131
<Group
130132
title={"Tenant Manager"}

docs/developer-docs/6.x/reference/extensions/infra.mdx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,19 @@ Adds a fully custom Lambda function to the API application, with both an applica
274274
| `functionSrc` | `string` | Yes | Path to the Lambda handler source file |
275275
| `pulumiSrc` | `string` | Yes | Path to the Pulumi infrastructure file (must follow `ApiPulumi` abstraction) |
276276

277+
### Infra.Api.MaxBundleSize
278+
279+
Sets the maximum allowed size of the backend (AWS Lambda) function code. If the built output exceeds this limit, the build fails immediately. The default is **4.5 MB**.
280+
281+
| Prop | Type | Required | Description |
282+
| ------ | -------- | -------- | ----------------------------- |
283+
| `size` | `number` | Yes | Maximum bundle size in bytes. |
284+
285+
```tsx
286+
{/* Raise the API bundle size limit to 6 MB */}
287+
<Infra.Api.MaxBundleSize size={6 * 1024 * 1024} />
288+
```
289+
277290
### Infra.Api.StackOutputValue
278291

279292
Adds a custom key-value entry to the API Pulumi stack outputs. Can be used multiple times.
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
---
2+
id: m4x7pq2n
3+
title: Preview URL Modifier
4+
description: Learn how to inject custom query parameters into Website Builder's live preview URLs.
5+
---
6+
7+
import { Alert } from "@/components/Alert";
8+
9+
<Alert type="success" title="WHAT YOU'LL LEARN">
10+
11+
- what the PreviewUrlModifier extension point is and where it applies
12+
- how to implement and register a custom preview URL modifier
13+
- how to use async operations (e.g. fetching a signed token) inside a modifier
14+
15+
</Alert>
16+
17+
## Overview
18+
19+
Every live preview URL that Website Builder generates — in the page editor iframe, the address bar's copy link button, and the pages list — can be customized via the `PreviewUrlModifier` extension point.
20+
21+
When registered, the modifier receives the fully-constructed `URL` object just before it is used. You can add, remove, or change any query parameter, including ones fetched asynchronously from a remote API.
22+
23+
<Alert type="info">
24+
25+
Only one `PreviewUrlModifier` can be registered per project. Avoid setting parameters that start with `wb.` — those are reserved for internal Website Builder use.
26+
27+
</Alert>
28+
29+
## Implement the Modifier
30+
31+
Create a class that implements `PreviewUrlModifier.Interface`. The single required method is `modify(url: URL): Promise<void>`. Mutate the `url` object in place — the return value is ignored.
32+
33+
```typescript extensions/previewUrlModifier/MyPreviewUrlModifier.ts
34+
import { PreviewUrlModifier } from "webiny/admin/website-builder";
35+
36+
class MyPreviewUrlModifier implements PreviewUrlModifier.Interface {
37+
async modify(url: URL) {
38+
url.searchParams.set("my-param", "my-value");
39+
}
40+
}
41+
42+
export default PreviewUrlModifier.createImplementation({
43+
implementation: MyPreviewUrlModifier,
44+
dependencies: []
45+
});
46+
```
47+
48+
### Async Example — Fetching a Signed Token
49+
50+
Mark the method `async` to perform any async work before the URL is handed back:
51+
52+
```typescript extensions/previewUrlModifier/MyPreviewUrlModifier.ts
53+
import { PreviewUrlModifier } from "webiny/admin/website-builder";
54+
55+
class MyPreviewUrlModifier implements PreviewUrlModifier.Interface {
56+
async modify(url: URL) {
57+
const token = await fetch("/api/preview-token").then(r => r.text());
58+
url.searchParams.set("token", token);
59+
}
60+
}
61+
62+
export default PreviewUrlModifier.createImplementation({
63+
implementation: MyPreviewUrlModifier,
64+
dependencies: []
65+
});
66+
```
67+
68+
## Register the Feature
69+
70+
Wire the implementation into the DI container using `createFeature` and `RegisterFeature`:
71+
72+
```tsx extensions/previewUrlModifier/index.tsx
73+
import React from "react";
74+
import { createFeature, RegisterFeature } from "webiny/admin";
75+
import MyPreviewUrlModifier from "./MyPreviewUrlModifier.js";
76+
77+
const PreviewUrlModifierFeature = createFeature({
78+
name: "MyApp/PreviewUrlModifier",
79+
register(container) {
80+
container.register(MyPreviewUrlModifier);
81+
}
82+
});
83+
84+
export default () => <RegisterFeature feature={PreviewUrlModifierFeature} />;
85+
```
86+
87+
Then register the extension in `webiny.config.tsx`:
88+
89+
```tsx webiny.config.tsx
90+
import React from "react";
91+
import { Admin } from "webiny/extensions";
92+
93+
export const Extensions = () => {
94+
return (
95+
<>
96+
{/* ... other extensions */}
97+
<Admin.Extension src={"@/extensions/previewUrlModifier/index.tsx"} />
98+
</>
99+
);
100+
};
101+
```
102+
103+
## Where the Modifier Applies
104+
105+
| Surface | Description |
106+
|---|---|
107+
| Editor iframe | The live-editing iframe in the page editor |
108+
| Address bar link | The "copy preview link" button in the editor toolbar |
109+
| Pages list | Preview icon links in the pages list table |
191 KB
Loading
2.27 MB
Binary file not shown.
165 KB
Loading
39.5 KB
Loading

0 commit comments

Comments
 (0)