Skip to content

Commit 235a72f

Browse files
adrians5jPavel910brunozoricswapnilmmaneSvenAlHamad
authored
feat: create v6 articles (#758)
Co-authored-by: Pavel Denisjuk <pavel@webiny.com> Co-authored-by: Bruno Zorić <bruno.zoric@gmail.com> Co-authored-by: Swapnil M Mane <swapnilmmane@gmail.com> Co-authored-by: SvenAlHamad <sven@webiny.com>
1 parent e165b3d commit 235a72f

567 files changed

Lines changed: 45312 additions & 4883 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,11 @@ build
123123
/src/data/
124124
/src/pages/docs/
125125
/public/algolia/sitemap.xml
126-
126+
/public/docs-static/raw/
127127
# Mac files
128128
.DS_Store
129+
130+
# Bruno
131+
v6
132+
remote
133+
.claude/settings.local.json

.mdx-validation.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"targetDir": "docs/developer-docs/6.0.x",
3+
"exceptions": [
4+
"get-started/welcome.mdx",
5+
"get-started/install-webiny.mdx",
6+
"overview/pricing.mdx",
7+
"overview/features/security.mdx",
8+
"tenant-manager/manage-tenants.mdx",
9+
"tenant-manager/extend-tenant-model.mdx"
10+
]
11+
}

AGENTS.md

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
# Project Instructions
2+
3+
## Critical Project Conventions
4+
5+
### Package Manager
6+
7+
- **ALWAYS use `yarn`, NEVER use `npm`** - This project exclusively uses Yarn
8+
- All script execution: `yarn <script-name>`
9+
- All package operations: `yarn add`, `yarn install`, etc.
10+
11+
### Validation and Quality
12+
13+
- **MDX/.ai.txt Pairing**: Every `.mdx` file must have a corresponding `.ai.txt` companion file
14+
- Run `yarn validate:mdx` to verify pairing before commits/PRs
15+
- Exceptions are defined in `.mdx-validation.json` (supports exact paths and glob patterns)
16+
- The validation script (`scripts/validate-mdx-pairing.ts`) checks bidirectionally
17+
18+
### Project Structure
19+
20+
- Documentation: `docs/developer-docs/6.0.x/`
21+
- Plans/design docs: `plans/` (project root)
22+
- Scripts: `scripts/` (TypeScript scripts executed via `tsx`)
23+
- Validation config: `.mdx-validation.json` (project root)
24+
25+
## Documentation Structure
26+
27+
- Documentation files live in `docs/developer-docs/6.0.x/`
28+
- `.mdx` files are the documentation pages
29+
- `.ai.txt` files are AI companion context files — read them to understand the corresponding `.mdx` file (sources, decisions, patterns, tone guidelines)
30+
31+
### Directory Layout
32+
33+
```
34+
docs/developer-docs/6.0.x/
35+
├── core-concepts/ # Foundational knowledge: architecture, applications, project structure, DI, Result pattern, multi-tenancy, local dev, env vars
36+
├── get-started/ # Welcome, installation, upgrade to Business
37+
├── cli/ # CLI commands reference
38+
├── graphql/ # GraphQL schema building with factory pattern
39+
├── headless-cms/ # Largest section — all CMS extensibility
40+
│ ├── builder/ # ModelBuilder, GroupBuilder, FieldBuilder APIs
41+
│ ├── event-handler/ # Entry/model/group lifecycle events
42+
│ ├── examples/ # Private model, single-entry model
43+
│ ├── ui/ # Field renderers
44+
│ └── use-case/ # Entry/model/group business logic
45+
├── overview/ # Pricing, security features
46+
│ └── features/
47+
├── tasks/ # Background task system (Runner, Context, Controller)
48+
└── website-builder/ # Website Builder extensibility
49+
├── event-handler/ # Page/redirect lifecycle events
50+
└── use-case/ # Page/redirect business logic
51+
```
52+
53+
### Key Patterns
54+
55+
- Each major system follows a consistent taxonomy: **builder** (define structure) / **event-handler** (react to events) / **use-case** (custom business logic)
56+
- `core-concepts/di.mdx` and `core-concepts/result.mdx` are foundational — referenced by all other sections
57+
- `.ai.txt` files contain: source info, key decisions, understanding, code patterns, related docs, and tone guidelines
58+
- Tone is calibrated per doc type: conceptual (about), technical (reference), practical (examples)
59+
60+
### MDX/.ai.txt Pairing Exceptions
61+
62+
Current exceptions (defined in `.mdx-validation.json`):
63+
64+
- `get-started/welcome.mdx` - introductory page
65+
- `get-started/install-webiny.mdx` - installation guide
66+
- `overview/pricing.mdx` - pricing overview
67+
- `overview/features/security.mdx` - security features
68+
69+
## MDX Writing Conventions
70+
71+
### Frontmatter
72+
73+
Every `.mdx` file uses exactly three required fields:
74+
75+
```yaml
76+
---
77+
id: <8-char-alphanumeric> # e.g., "kp9m2xnf" — short, random, lowercase
78+
title: <Title Case>
79+
description: <One-line description>
80+
---
81+
```
82+
83+
Optional fields (rare, only for special pages like welcome): `pageHeader: false`, `fullWidth: true`.
84+
85+
### Page Structure
86+
87+
Every page follows this order:
88+
89+
1. Frontmatter
90+
2. Component imports
91+
3. `<Alert type="success" title="WHAT YOU'LL LEARN">` block with bullet list of questions
92+
4. `## Overview` — always the first H2, 1-3 paragraphs of prose
93+
5. Content sections as H2 (`##`) with H3 (`###`) subsections as needed
94+
6. No H1 headings in the body — the page title comes from frontmatter
95+
96+
### Components
97+
98+
Only one MDX component is used: `<Alert>` from `@/components/Alert`.
99+
100+
```mdx
101+
import { Alert } from "@/components/Alert";
102+
103+
;
104+
```
105+
106+
Alert types:
107+
108+
- `type="success"` — "WHAT YOU'LL LEARN" opener (every page)
109+
- `type="info"` — supplemental links or context (inline, overview pages)
110+
- `type="warning"` — important cautions (inline, overview pages)
111+
112+
No other custom components are used (no `<Tabs>`, `<Steps>`, etc.).
113+
114+
### Code Blocks
115+
116+
- Language tag is always specified: ` ```typescript ` or ` ```graphql `
117+
- **File path annotations** go after the language tag: ` ```typescript extensions/cms/group/eventHandler/create/beforeCreate.ts `
118+
- Use ` ```tsx ` for `webiny.config.tsx` files
119+
- GraphQL SDL in TypeScript uses `/* GraphQL */` tag: `builder.addTypeDefs(/* GraphQL */ \`...\`)`
120+
- Minimal comments in code — only for pedagogical correct/wrong comparisons using `// ✅ Correct` / `// ❌ Wrong`
121+
- No shell/bash code blocks
122+
123+
### Import Paths in Code Examples
124+
125+
```typescript
126+
// Webiny v6 API imports — use "webiny/" prefix, NOT "@webiny/"
127+
import { ModelFactory } from "webiny/api/cms/model";
128+
import { CreateEntryUseCase } from "webiny/api/cms/entry";
129+
import { Logger } from "webiny/api/logger";
130+
import { Api } from "webiny/extensions";
131+
import { Result } from "webiny/api";
132+
133+
// Local file imports use .js extensions (ESM)
134+
import { BookRepository } from "./abstractions/BookRepository.js";
135+
136+
// Type-only imports
137+
import type { CmsEntry } from "webiny/api";
138+
```
139+
140+
### Text Formatting
141+
142+
- Backticks for: code, class names, method names, type names, package names
143+
- **Bold** for key labels: `**Naming Convention:**`, `**Key Point:**`
144+
- Bullet lists use `-`, not numbered lists (even for sequential steps)
145+
- No emojis in prose
146+
- Inline links use standard markdown: `[text](/docs/path)`
147+
- "Webiny" always capitalized
148+
149+
## Tone and Voice
150+
151+
### General Rules
152+
153+
- Concise and technical — no filler, no marketing language in developer docs
154+
- Direct and instructional — "Use `createAbstraction()` to create one"
155+
- Address the reader as "you"
156+
- Explain "why" briefly before showing "how"
157+
- Avoid "we" statements — use "The system provides/offers" instead
158+
- No analogies in published docs (save those for `.ai.txt` context)
159+
- Accessible to junior developers while remaining technically complete
160+
161+
### Per Doc Type
162+
163+
| Doc Type | Tone | Focus |
164+
| --------------------------- | ---------------------------- | ------------------------------------------------- |
165+
| `about.mdx` | Conceptual, accessible | Why and what, link to reference for how |
166+
| `reference.mdx` | Simple, concise, API-focused | Method signatures, minimal examples |
167+
| `example.mdx` | Practical, production-ready | Complete working code, copy-paste friendly |
168+
| `event-handler/*.mdx` | Production-ready examples | When/why to use each event, real-world scenarios |
169+
| `use-case/*.mdx` | Technical and complete | Full abstraction + implementation patterns |
170+
| `builder/*.mdx` | Technical reference | Complete method docs, practical examples per type |
171+
| `management.mdx` | Practical, operation-focused | Complete examples, error handling |
172+
| `get-started/`, `overview/` | Conversational, welcoming | High-level survey, no code |
173+
174+
## TypeScript Code Patterns
175+
176+
### DI Pattern (used in all implementations)
177+
178+
```typescript
179+
import { SomeAbstraction } from "webiny/api/cms/entity";
180+
import { Logger } from "webiny/api/logger";
181+
182+
// Implementation class with Impl suffix
183+
class SomeAbstractionImpl implements SomeAbstraction.Interface {
184+
public constructor(private logger: Logger.Interface) {}
185+
186+
public async handle(event: SomeAbstraction.Event): Promise<void> {
187+
// implementation
188+
}
189+
}
190+
191+
// Factory registration — MUST be default export
192+
const SomeAbstractionConst = SomeAbstraction.createImplementation({
193+
implementation: SomeAbstractionImpl,
194+
dependencies: [Logger]
195+
});
196+
197+
export default SomeAbstractionConst;
198+
```
199+
200+
### Result Pattern (used in all use cases)
201+
202+
```typescript
203+
const result = await someUseCase.execute(params);
204+
if (result.isFail()) {
205+
// handle error — return early (guard clause)
206+
return { error: result.error, data: null };
207+
}
208+
const value = result.value;
209+
```
210+
211+
### Namespace Export Pattern (abstractions)
212+
213+
```typescript
214+
export namespace MyAbstraction {
215+
export type Interface = IMyAbstraction;
216+
export type Params = IMyAbstractionParams;
217+
export type Return = IMyAbstractionReturn;
218+
}
219+
```
220+
221+
### Registration in webiny.config.tsx
222+
223+
```tsx
224+
import React from "react";
225+
import { Api } from "webiny/extensions";
226+
227+
export const Extensions = () => {
228+
return (
229+
<>
230+
{/* ... all your other extensions */}
231+
<Api.Extension src={"/extensions/cms/entity/path/to/file.ts"} />
232+
</>
233+
);
234+
};
235+
```
236+
237+
### Event Handler Naming
238+
239+
- Class names: `On[Resource][Before|After][Operation]Handler` (e.g., `OnPageBeforeCreateHandler`)
240+
- Abstraction tokens: `[Resource][Before|After][Operation]Handler` (without "On" prefix)
241+
- "Before" handlers receive `payload.input`; "After" handlers receive the completed entity (e.g., `payload.page`)
242+
243+
## .ai.txt File Format
244+
245+
Each `.ai.txt` companion file contains these sections:
246+
247+
1. `AI Context: [Page Title] ([filename])` — header
248+
2. `Source of Information:` — numbered list of research sources
249+
3. `Key Documentation Decisions:` — editorial choices made
250+
4. `[Topic-specific understanding]` — detailed domain knowledge
251+
5. `[Code patterns/snippets]` — verified TypeScript templates
252+
6. `Related Documents:` — cross-references to sibling docs
253+
7. `Key Code Locations:` — source code paths in the Webiny repo
254+
8. `Tone Guidelines:` — explicit style instructions for the page
255+
256+
### Maintenance
257+
258+
- When new documentation files (`.mdx` or `.ai.txt`) are added, update the directory layout and notes in this AGENTS.md to reflect the changes.

CLAUDE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## Startup
2+
- Always read `~/.claude/settings.json` at the start of every conversation.
3+
- Read `./AGENTS.md"

docs.config.ts

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,27 +34,78 @@ const linkWhitelist: string[] = [...redirects.map(r => r.source), "/forms/produc
3434
*/
3535
const whitelistedVersions: string[] = [];
3636

37+
/**
38+
* Only build versions at or above this version (e.g., "5.40.x").
39+
* Set via MIN_VERSION environment variable or modify here.
40+
* Set to empty string to build all versions.
41+
*/
42+
const minVersionToBuild = process.env.MIN_VERSION || "";
43+
3744
const filterByEnvironment = (version: Version) => {
3845
// In `preview`, if there are specific versions whitelisted for deployment, those are the only ones we'll output.
3946
if (preview && whitelistedVersions.length > 0) {
4047
return whitelistedVersions.includes(version.getValue());
4148
}
4249

50+
// If minVersionToBuild is set, only build versions >= minVersion or `latest`.
51+
if (minVersionToBuild) {
52+
if (minVersionToBuild === "latest") {
53+
return version.isLatest();
54+
}
55+
const versionNum = parseFloat(version.getValue().replace(/[^\d.]/g, ""));
56+
const minVersionNum = parseFloat(minVersionToBuild.replace(/[^\d.]/g, ""));
57+
return versionNum >= minVersionNum;
58+
}
59+
4360
// Build everything.
4461
return true;
4562
};
4663

64+
const filterFilePathByVersion = (filePath: string): boolean => {
65+
// Extract version from file path (e.g., /docs/developer-docs/5.40.x/... or /docs/user-guides/5.40.x/...)
66+
const versionMatch = filePath.match(/\/(\d+\.\d+\.x)\//);
67+
68+
if (!versionMatch) {
69+
// If no version in path, include the file (e.g., non-versioned docs)
70+
return true;
71+
}
72+
73+
const versionString = versionMatch[1];
74+
75+
// Use the same filtering logic as filterByEnvironment
76+
if (preview && whitelistedVersions.length > 0) {
77+
return whitelistedVersions.includes(versionString);
78+
}
79+
80+
if (minVersionToBuild) {
81+
if (minVersionToBuild === "latest") {
82+
// For file paths, we can't determine if it's "latest" without more context
83+
// So we'll include all versioned files when minVersionToBuild is "latest"
84+
return true;
85+
}
86+
const versionNum = parseFloat(versionString.replace(/[^\d.]/g, ""));
87+
const minVersionNum = parseFloat(minVersionToBuild.replace(/[^\d.]/g, ""));
88+
return versionNum >= minVersionNum;
89+
}
90+
91+
return true;
92+
};
93+
4794
const existsInDocs = (link: string) => {
4895
return fs.pathExists(path.join(__dirname, `src/pages/${link}.js`));
4996
};
5097

5198
export default {
5299
projectRootDir: __dirname,
53-
cleanOutputDir: path.resolve("src/pages/docs"),
100+
cleanOutputDir: [path.resolve("src/pages/docs"), path.resolve("public/raw/docs")],
54101
sitemapOutputPath: path.resolve("public/algolia/sitemap.xml"),
55-
linkValidator: new LinkValidator(linkWhitelist, link => {
56-
return existsInDocs(link);
57-
}),
102+
linkValidator: new LinkValidator(
103+
linkWhitelist,
104+
link => {
105+
return existsInDocs(link);
106+
},
107+
filterFilePathByVersion
108+
),
58109
documentRoots: [
59110
/* Developer Docs */
60111
new VersionedDocumentRootConfig({

docs/developer-docs/5.28.x/core-development-concepts/scaffolding/react-application.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ import { createWatchApp, createBuildApp } from "@webiny/project-utils";
227227

228228
// Exports fundamental watch and build commands.
229229
// Need to inject environment variables or link your application with an existing GraphQL API?
230-
// See https://www.webiny.com/docs/core-development-concepts/scaffolding/full-stack-application/webiny-config.
230+
// See https://www.webiny.com/docs/{version}/core-development-concepts/scaffolding/full-stack-application/webiny-config.
231231
export default {
232232
commands: {
233233
async watch(options, context) {

docs/developer-docs/5.28.x/custom-app-tutorial/adding-user-pools/adding-user-pool-and-user-pool-domain.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ import Cloudfront from "./cloudfront";
124124
const DEBUG = String(process.env.DEBUG);
125125

126126
// Enables logs forwarding.
127-
// https://www.webiny.com/docs/core-development-concepts/basics/watch-command#enabling-logs-forwarding
127+
// https://www.webiny.com/docs/{version}/core-development-concepts/basics/watch-command#enabling-logs-forwarding
128128
const WEBINY_LOGS_FORWARD_URL = String(process.env.WEBINY_LOGS_FORWARD_URL);
129129

130130
export default () => {

docs/developer-docs/5.28.x/custom-app-tutorial/securing-graphql-api/initial-setup.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ import Cognito from "./cognito";
7373
import S3 from "./s3";
7474

7575
// Among other things, this determines the amount of information we reveal on runtime errors.
76-
// https://www.webiny.com/docs/core-development-concepts/environment-variables/#debug-environment-variable
76+
// https://www.webiny.com/docs/{version}/core-development-concepts/environment-variables/#debug-environment-variable
7777
const DEBUG = String(process.env.DEBUG);
7878

7979
// Enables logs forwarding.

0 commit comments

Comments
 (0)