fimo 2.2.0-staging.16 → 2.2.0-staging.18

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.
Files changed (30) hide show
  1. package/assets/agent-templates/_default/config.yaml +6 -0
  2. package/assets/skills/fimo-cli/references/agents.md +3 -2
  3. package/dist/cli/bundle.json +1 -1
  4. package/dist/cli/index.js +1 -1
  5. package/package.json +8 -8
  6. package/templates/astro/package.json +2 -2
  7. package/templates/nextjs/package.json +3 -3
  8. package/templates/react-router/package.json +4 -4
  9. package/templates/sveltekit/package.json +2 -2
  10. package/templates/vite/package.json +4 -4
  11. package/templates/welcome/manifest.json +306 -55
  12. package/templates/welcome/template/.fimo/agents/welcome-guide/GOAL.md +9 -4
  13. package/templates/welcome/template/.fimo/agents/welcome-guide/capabilities.yaml +3 -0
  14. package/templates/welcome/template/.fimo/agents/welcome-guide/config.yaml +4 -4
  15. package/templates/welcome/template/src/pages/ArticleDetail.tsx +42 -6
  16. package/templates/welcome/template/src/pages/Index.tsx +6 -2
  17. package/templates/welcome/template/src/pages/SiteContent.tsx +296 -35
  18. package/templates/welcome/template/src/pages/fallback-content.ts +34 -15
  19. package/templates/welcome/template/src/schemas/Article.json +27 -5
  20. package/templates/welcome/template/src/schemas/Article.ts +16 -21
  21. package/templates/welcome/template/src/schemas/Article.types.ts +40 -20
  22. package/templates/welcome/template/src/schemas/Author.json +17 -0
  23. package/templates/welcome/template/src/schemas/Author.ts +51 -0
  24. package/templates/welcome/template/src/schemas/Author.types.ts +54 -0
  25. package/templates/welcome/template/src/schemas/Category.json +17 -0
  26. package/templates/welcome/template/src/schemas/Category.ts +51 -0
  27. package/templates/welcome/template/src/schemas/Category.types.ts +54 -0
  28. package/templates/welcome/template/src/schemas/HomePage.json +94 -23
  29. package/templates/welcome/template/src/schemas/HomePage.ts +22 -0
  30. package/templates/welcome/template/src/schemas/HomePage.types.ts +2 -0
@@ -1,6 +1,7 @@
1
- import type { Article } from '@/schemas/Article';
2
1
  import type { HomePage } from '@/schemas/HomePage';
3
2
 
3
+ import type { TutorialArticle } from './SiteContent';
4
+
4
5
  // Generated from the starter seed (../../manifest.json): the loading
5
6
  // fallback renders the real TutorialPage with this data so the live CMS
6
7
  // values swap in without any visible change. Regenerate when the seed
@@ -10,7 +11,7 @@ import type { HomePage } from '@/schemas/HomePage';
10
11
  // live values arrive.
11
12
 
12
13
  export const FALLBACK_PAGE = {
13
- title: 'This site is yours to change.',
14
+ title: 'Welcome to the Fimo onboarding!',
14
15
  intro: {
15
16
  content: {
16
17
  type: 'doc',
@@ -20,7 +21,12 @@ export const FALLBACK_PAGE = {
20
21
  content: [
21
22
  {
22
23
  type: 'text',
23
- text: 'Four actions, five minutes. Every change is safe to make in this tutorial project.',
24
+ text: 'This is a tutorial project, made for you to practice.',
25
+ },
26
+ { type: 'hardBreak' },
27
+ {
28
+ type: 'text',
29
+ text: 'Four actions, five minutes, and nothing you change here can break anything.',
24
30
  },
25
31
  ],
26
32
  },
@@ -51,7 +57,7 @@ export const FALLBACK_PAGE = {
51
57
  _key: 'fallback-step-3',
52
58
  number: '3',
53
59
  title: 'Explore branches',
54
- body: 'Branches let people and agents work without touching the live site.\n- Try a change on “tutorial/first-change”.',
60
+ body: 'Branches let people and agents work without touching the live site.\n- Create “tutorial/first-change” from the branch menu and change the page title there.',
55
61
  actionLabel: 'Show the branch menu',
56
62
  action: 'openBranches',
57
63
  },
@@ -59,8 +65,8 @@ export const FALLBACK_PAGE = {
59
65
  _key: 'fallback-step-4',
60
66
  number: '4',
61
67
  title: 'Meet your agent',
62
- body: 'Your agent maintains this website on a schedule.\n- Click “Run now” and review the result and cost.',
63
- actionLabel: 'Meet Welcome Guide',
68
+ body: 'Your agent maintains this website on a schedule.\n- Open its latest run, read the report, and accept the proposed change.',
69
+ actionLabel: 'Meet your first agent',
64
70
  action: 'openAgents',
65
71
  },
66
72
  ],
@@ -106,28 +112,41 @@ export const FALLBACK_PAGE = {
106
112
  closingTitle: 'Fimo keeps finished websites autonomous',
107
113
  closingBody:
108
114
  'Fimo Credits are designed for the agents that maintain your website and for teammates who use Studio chat without a local coding tool.',
115
+ footerNote: 'This tutorial website is looked after by your Fimo agent.',
109
116
  } as unknown as HomePage;
110
117
 
111
118
  // Covers are omitted: the card's image box keeps its own aspect ratio, so
112
119
  // the live images arrive without shifting the layout.
120
+ // The author and category shapes mirror a populated read: the cards render
121
+ // them during the loading window too, so a fallback without them would
122
+ // crash the very first paint.
123
+ // Ordered the way the live read returns them (newest entry first), not the
124
+ // way the manifest seeds them: the fallback exists to be replaced without a
125
+ // visible change, and a different order is a visible change.
113
126
  export const FALLBACK_ARTICLES = [
114
127
  {
115
128
  id: 'fallback-article-1',
116
- slug: 'create-your-first-agent',
117
- title: 'Create your first agent',
118
- summary:
119
- 'Build a weekly SEO agent with one prompt: full audit, safe fixes applied to the CMS, and a report you can trust.',
129
+ slug: 'discover-the-analytics',
130
+ title: 'Discover the analytics',
131
+ summary: 'What your traffic numbers mean, and how an agent can use them to improve your pages every week.',
132
+ author: { name: 'Fimo Product', role: 'Product team' },
133
+ category: { name: 'Automation' },
120
134
  },
121
135
  {
122
136
  id: 'fallback-article-2',
123
137
  slug: 'branches-and-environments',
124
138
  title: 'How branches and environments work',
125
- summary: 'Branches isolate changes. Environments group related branches under shared deployment configuration.',
139
+ summary: 'What a branch is, why it keeps your live site safe, and how changes come back together.',
140
+ author: { name: 'Fimo Engineering', role: 'Engineering team' },
141
+ category: { name: 'Concepts' },
126
142
  },
127
143
  {
128
144
  id: 'fallback-article-3',
129
- slug: 'discover-the-analytics',
130
- title: 'Discover the analytics',
131
- summary: 'See who visits your website: pageviews, top pages, sources, devices, and countries.',
145
+ slug: 'create-your-first-agent',
146
+ title: 'Create your first agent',
147
+ summary:
148
+ 'Build a weekly SEO agent with one prompt: full audit, safe fixes applied to the CMS, and a report you can trust.',
149
+ author: { name: 'Fimo Engineering', role: 'Engineering team' },
150
+ category: { name: 'Automation' },
132
151
  },
133
- ] as unknown as Article[];
152
+ ] as unknown as TutorialArticle[];
@@ -2,11 +2,33 @@
2
2
  "uid": "Article",
3
3
  "name": "Articles",
4
4
  "isSingleton": false,
5
- "i18n": { "enabled": false },
5
+ "i18n": {
6
+ "enabled": false
7
+ },
6
8
  "fields": {
7
- "title": { "type": "string", "required": true },
8
- "summary": { "type": "text", "required": true },
9
- "body": { "type": "richtext", "required": true },
10
- "cover": { "type": "media", "required": true }
9
+ "title": {
10
+ "type": "string",
11
+ "required": true
12
+ },
13
+ "summary": {
14
+ "type": "text",
15
+ "required": true
16
+ },
17
+ "body": {
18
+ "type": "richtext",
19
+ "required": true
20
+ },
21
+ "cover": {
22
+ "type": "media",
23
+ "required": true
24
+ },
25
+ "author": {
26
+ "type": "reference",
27
+ "target": "Author"
28
+ },
29
+ "category": {
30
+ "type": "reference",
31
+ "target": "Category"
32
+ }
11
33
  }
12
34
  }
@@ -1,33 +1,28 @@
1
1
  // AUTO-GENERATED by `fimo` from src/schemas/Article.json - DO NOT EDIT.
2
2
  // Change content fields in the schema, then run `fimo validate`.
3
- // Runtime implementation lives in the project-local fimo-react package.
4
- import { createContentClient } from 'fimo-react';
5
- import type { CollectionContentClient } from 'fimo-react';
6
- import type { ContentSchema } from 'fimo-react';
3
+ // Runtime implementation lives in the project-local fimo-react package export.
4
+ import { createContentClient } from "fimo-react";
5
+ import type { CollectionContentClient } from "fimo-react";
6
+ import type { ContentSchema } from "fimo-react";
7
7
 
8
- import schema from './Article.json';
9
- import type { Article, ArticleFields, ArticleInput, ArticlePopulate, ArticleQuery } from './Article.types';
8
+ import schema from "./Article.json";
9
+ import * as Author from "./Author";
10
+ import * as Category from "./Category";
11
+ import type { Article, ArticleFields, ArticleInput, ArticlePopulate, ArticleQuery } from "./Article.types";
10
12
 
11
- export type {
12
- Article,
13
- ArticleFields,
14
- ArticleFimoMeta,
15
- ArticleInput,
16
- ArticlePopulate,
17
- ArticleQuery,
18
- ArticleReferences,
19
- ArticleResult,
20
- ArticleSort,
21
- ArticleWhere,
22
- } from './Article.types';
23
- export type { CollectionPage, CollectionPageInfo, InfiniteListResult } from 'fimo-react';
13
+ export type { Article, ArticleFields, ArticleFimoMeta, ArticleInput, ArticlePopulate, ArticleQuery, ArticleReferences, ArticleResult, ArticleSort, ArticleWhere } from "./Article.types";
14
+ export type { CollectionPage, CollectionPageInfo, InfiniteListResult } from "fimo-react";
24
15
  export type InfiniteListQuery<
25
16
  TFields extends ArticleFields | undefined = undefined,
26
17
  TPopulate extends ArticlePopulate | undefined = undefined,
27
- > = Omit<ArticleQuery<TFields, TPopulate>, 'offset'>;
18
+ > = Omit<ArticleQuery<TFields, TPopulate>, "offset">;
28
19
 
29
- const client: CollectionContentClient<Article, ArticleInput> = createContentClient<Article, ArticleInput>({
20
+ const client: CollectionContentClient<Article, ArticleInput> = createContentClient<
21
+ Article,
22
+ ArticleInput
23
+ >({
30
24
  schema: schema as unknown as ContentSchema,
25
+ references: { Author, Category },
31
26
  });
32
27
 
33
28
  export const {
@@ -1,31 +1,36 @@
1
1
  // AUTO-GENERATED ⚠️ – do not edit by hand
2
- import {
3
- type Fields,
4
- type FimoBoolean,
5
- type FimoMedia,
6
- type FimoPolymorphicReference,
7
- type FimoReference,
8
- type FimoRichText,
9
- type FimoRichTextContent,
10
- type FimoString,
11
- type Populate,
12
- type PopulatedResult,
13
- type ProjectedWithPopulate,
14
- type Query,
15
- type Sort,
16
- type Where,
17
- type WithReferences,
18
- } from 'fimo-react';
2
+ import { type Fields, type FimoMedia, type FimoReference, type FimoRichText, type FimoRichTextContent, type FimoString, type Populate, type PopulatedResult, type ProjectedWithPopulate, type Query, type Sort, type Where, type WithReferences } from "fimo-react";
3
+ import type { Author } from "./Author.types";
4
+ import type { Category } from "./Category.types";
19
5
 
20
6
  /*───────────────────────────────────────────────────────────────*/
21
7
  /* ──────────── 📄 Type definitions ──────────── */
22
8
  /*───────────────────────────────────────────────────────────────*/
23
9
 
10
+ /**
11
+ * What a media field stores: a reference to a media-library asset. Point at the
12
+ * asset by `id`, or by the `url` an upload returned and Fimo resolves the `id`
13
+ * for you. `alt` belongs to the entry, so it survives replacing the asset. The
14
+ * facts the asset owns are never copied in, so they cannot go stale.
15
+ */
16
+ export type FimoMediaRef = ({ id: string; url?: string } | { id?: string; url: string }) & {
17
+ alt?: string;
18
+ source?: "local" | "external";
19
+ };
20
+
21
+ /**
22
+ * What a read returns for a media field it named in `populate`: the reference
23
+ * plus the facts the asset owns as of that read. `name`, `mime`, `width`, and
24
+ * `height` remain optional when the asset is external, missing, or incomplete.
25
+ * A read that did not name the field returns `FimoMedia` with those facts absent.
26
+ */
27
+ export type FimoPopulatedMedia = FimoMedia & { name?: string; mime?: string };
28
+
24
29
  /**
25
30
  * Article entity interface
26
31
  */
27
32
  export interface ArticleFimoMeta {
28
- contentType: 'Article';
33
+ contentType: "Article";
29
34
  }
30
35
 
31
36
  export interface Article extends WithReferences<ArticleReferences> {
@@ -41,6 +46,8 @@ export interface Article extends WithReferences<ArticleReferences> {
41
46
  summary: FimoString;
42
47
  body: FimoRichText;
43
48
  cover: FimoMedia;
49
+ author: FimoReference | null;
50
+ category: FimoReference | null;
44
51
  }
45
52
 
46
53
  export interface ArticleInput {
@@ -49,10 +56,23 @@ export interface ArticleInput {
49
56
  title: string;
50
57
  summary: string;
51
58
  body: FimoRichTextContent;
52
- cover: Pick<FimoMedia, 'url' | 'alt' | 'name' | 'mime' | 'width' | 'height'>;
59
+ cover: FimoMediaRef;
60
+ author?: FimoReference | null;
61
+ category?: FimoReference | null;
53
62
  }
54
63
 
55
- export type ArticleReferences = Record<never, never>;
64
+
65
+ /**
66
+ * What each populatable field returns when a read names it in `populate`: a
67
+ * reference field resolves to its target entry, a media field to the asset's
68
+ * current facts, a blocks field to the same items with every media value
69
+ * inside them filled. Fields absent here are returned as stored.
70
+ */
71
+ export interface ArticleReferences {
72
+ author: Author | null;
73
+ category: Category | null;
74
+ cover: FimoPopulatedMedia;
75
+ }
56
76
 
57
77
  export type ArticlePopulate = Populate<Article>;
58
78
 
@@ -0,0 +1,17 @@
1
+ {
2
+ "uid": "Author",
3
+ "name": "Authors",
4
+ "isSingleton": false,
5
+ "i18n": {
6
+ "enabled": false
7
+ },
8
+ "fields": {
9
+ "name": {
10
+ "type": "string",
11
+ "required": true
12
+ },
13
+ "role": {
14
+ "type": "string"
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,51 @@
1
+ // AUTO-GENERATED by `fimo` from src/schemas/Author.json - DO NOT EDIT.
2
+ // Change content fields in the schema, then run `fimo validate`.
3
+ // Runtime implementation lives in the project-local fimo-react package export.
4
+ import { createContentClient } from "fimo-react";
5
+ import type { CollectionContentClient } from "fimo-react";
6
+ import type { ContentSchema } from "fimo-react";
7
+
8
+ import schema from "./Author.json";
9
+ import type { Author, AuthorFields, AuthorInput, AuthorPopulate, AuthorQuery } from "./Author.types";
10
+
11
+ export type { Author, AuthorFields, AuthorFimoMeta, AuthorInput, AuthorPopulate, AuthorQuery, AuthorReferences, AuthorResult, AuthorSort, AuthorWhere } from "./Author.types";
12
+ export type { CollectionPage, CollectionPageInfo, InfiniteListResult } from "fimo-react";
13
+ export type InfiniteListQuery<
14
+ TFields extends AuthorFields | undefined = undefined,
15
+ TPopulate extends AuthorPopulate | undefined = undefined,
16
+ > = Omit<AuthorQuery<TFields, TPopulate>, "offset">;
17
+
18
+ const client: CollectionContentClient<Author, AuthorInput> = createContentClient<
19
+ Author,
20
+ AuthorInput
21
+ >({
22
+ schema: schema as unknown as ContentSchema,
23
+ });
24
+
25
+ export const {
26
+ wrapWithSource,
27
+ meta,
28
+ getById,
29
+ getBySlug,
30
+ getByField,
31
+ list,
32
+ get,
33
+ create,
34
+ update,
35
+ remove,
36
+ useGetById,
37
+ useGetBySlug,
38
+ useGetByField,
39
+ useList,
40
+ useInfiniteList,
41
+ useGet,
42
+ useSuspenseGetById,
43
+ useSuspenseGet,
44
+ useSuspenseGetByField,
45
+ useSuspenseGetBySlug,
46
+ useCreate,
47
+ useUpdate,
48
+ useRemove,
49
+ } = client;
50
+
51
+ export default client;
@@ -0,0 +1,54 @@
1
+ // AUTO-GENERATED ⚠️ – do not edit by hand
2
+ import { type Fields, type FimoString, type Populate, type PopulatedResult, type ProjectedWithPopulate, type Query, type Sort, type Where, type WithReferences } from "fimo-react";
3
+
4
+ /*───────────────────────────────────────────────────────────────*/
5
+ /* ──────────── 📄 Type definitions ──────────── */
6
+ /*───────────────────────────────────────────────────────────────*/
7
+
8
+ /**
9
+ * Author entity interface
10
+ */
11
+ export interface AuthorFimoMeta {
12
+ contentType: "Author";
13
+ }
14
+
15
+ export interface Author extends WithReferences<AuthorReferences> {
16
+ id: string;
17
+ entryId: string;
18
+ documentId: string;
19
+ slug: FimoString;
20
+ locale: string;
21
+ createdAt: string;
22
+ updatedAt: string;
23
+ __fimo: AuthorFimoMeta;
24
+ name: FimoString;
25
+ role: FimoString;
26
+ }
27
+
28
+ export interface AuthorInput {
29
+ slug?: string;
30
+ documentId?: string;
31
+ name: string;
32
+ role?: string;
33
+ }
34
+
35
+
36
+ export type AuthorReferences = Record<never, never>;
37
+
38
+ export type AuthorPopulate = Populate<Author>;
39
+
40
+ /*───────────────────────────────────────────────────────────────*/
41
+ /* ──────────── 🔎 Query types ──────────── */
42
+ /*───────────────────────────────────────────────────────────────*/
43
+
44
+ export type AuthorWhere = Where<Author>;
45
+ export type AuthorSort = Sort<Author>;
46
+ export type AuthorFields = Fields<Author>;
47
+ export type AuthorQuery<
48
+ TFields extends AuthorFields | undefined = AuthorFields | undefined,
49
+ TPopulate extends AuthorPopulate | undefined = AuthorPopulate | undefined,
50
+ > = Query<Author, TFields, TPopulate>;
51
+ export type AuthorResult<
52
+ TFields extends AuthorFields | undefined = undefined,
53
+ TPopulate extends AuthorPopulate | undefined = undefined,
54
+ > = ProjectedWithPopulate<PopulatedResult<Author, TPopulate>, TFields, TPopulate>;
@@ -0,0 +1,17 @@
1
+ {
2
+ "uid": "Category",
3
+ "name": "Categories",
4
+ "isSingleton": false,
5
+ "i18n": {
6
+ "enabled": false
7
+ },
8
+ "fields": {
9
+ "name": {
10
+ "type": "string",
11
+ "required": true
12
+ },
13
+ "description": {
14
+ "type": "text"
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,51 @@
1
+ // AUTO-GENERATED by `fimo` from src/schemas/Category.json - DO NOT EDIT.
2
+ // Change content fields in the schema, then run `fimo validate`.
3
+ // Runtime implementation lives in the project-local fimo-react package export.
4
+ import { createContentClient } from "fimo-react";
5
+ import type { CollectionContentClient } from "fimo-react";
6
+ import type { ContentSchema } from "fimo-react";
7
+
8
+ import schema from "./Category.json";
9
+ import type { Category, CategoryFields, CategoryInput, CategoryPopulate, CategoryQuery } from "./Category.types";
10
+
11
+ export type { Category, CategoryFields, CategoryFimoMeta, CategoryInput, CategoryPopulate, CategoryQuery, CategoryReferences, CategoryResult, CategorySort, CategoryWhere } from "./Category.types";
12
+ export type { CollectionPage, CollectionPageInfo, InfiniteListResult } from "fimo-react";
13
+ export type InfiniteListQuery<
14
+ TFields extends CategoryFields | undefined = undefined,
15
+ TPopulate extends CategoryPopulate | undefined = undefined,
16
+ > = Omit<CategoryQuery<TFields, TPopulate>, "offset">;
17
+
18
+ const client: CollectionContentClient<Category, CategoryInput> = createContentClient<
19
+ Category,
20
+ CategoryInput
21
+ >({
22
+ schema: schema as unknown as ContentSchema,
23
+ });
24
+
25
+ export const {
26
+ wrapWithSource,
27
+ meta,
28
+ getById,
29
+ getBySlug,
30
+ getByField,
31
+ list,
32
+ get,
33
+ create,
34
+ update,
35
+ remove,
36
+ useGetById,
37
+ useGetBySlug,
38
+ useGetByField,
39
+ useList,
40
+ useInfiniteList,
41
+ useGet,
42
+ useSuspenseGetById,
43
+ useSuspenseGet,
44
+ useSuspenseGetByField,
45
+ useSuspenseGetBySlug,
46
+ useCreate,
47
+ useUpdate,
48
+ useRemove,
49
+ } = client;
50
+
51
+ export default client;
@@ -0,0 +1,54 @@
1
+ // AUTO-GENERATED ⚠️ – do not edit by hand
2
+ import { type Fields, type FimoString, type Populate, type PopulatedResult, type ProjectedWithPopulate, type Query, type Sort, type Where, type WithReferences } from "fimo-react";
3
+
4
+ /*───────────────────────────────────────────────────────────────*/
5
+ /* ──────────── 📄 Type definitions ──────────── */
6
+ /*───────────────────────────────────────────────────────────────*/
7
+
8
+ /**
9
+ * Category entity interface
10
+ */
11
+ export interface CategoryFimoMeta {
12
+ contentType: "Category";
13
+ }
14
+
15
+ export interface Category extends WithReferences<CategoryReferences> {
16
+ id: string;
17
+ entryId: string;
18
+ documentId: string;
19
+ slug: FimoString;
20
+ locale: string;
21
+ createdAt: string;
22
+ updatedAt: string;
23
+ __fimo: CategoryFimoMeta;
24
+ name: FimoString;
25
+ description: FimoString;
26
+ }
27
+
28
+ export interface CategoryInput {
29
+ slug?: string;
30
+ documentId?: string;
31
+ name: string;
32
+ description?: string;
33
+ }
34
+
35
+
36
+ export type CategoryReferences = Record<never, never>;
37
+
38
+ export type CategoryPopulate = Populate<Category>;
39
+
40
+ /*───────────────────────────────────────────────────────────────*/
41
+ /* ──────────── 🔎 Query types ──────────── */
42
+ /*───────────────────────────────────────────────────────────────*/
43
+
44
+ export type CategoryWhere = Where<Category>;
45
+ export type CategorySort = Sort<Category>;
46
+ export type CategoryFields = Fields<Category>;
47
+ export type CategoryQuery<
48
+ TFields extends CategoryFields | undefined = CategoryFields | undefined,
49
+ TPopulate extends CategoryPopulate | undefined = CategoryPopulate | undefined,
50
+ > = Query<Category, TFields, TPopulate>;
51
+ export type CategoryResult<
52
+ TFields extends CategoryFields | undefined = undefined,
53
+ TPopulate extends CategoryPopulate | undefined = undefined,
54
+ > = ProjectedWithPopulate<PopulatedResult<Category, TPopulate>, TFields, TPopulate>;
@@ -2,38 +2,109 @@
2
2
  "uid": "HomePage",
3
3
  "name": "Home page",
4
4
  "isSingleton": true,
5
- "i18n": { "enabled": false },
5
+ "i18n": {
6
+ "enabled": false
7
+ },
6
8
  "fields": {
7
- "title": { "type": "string", "required": true },
8
- "intro": { "type": "richtext", "required": true },
9
- "heroImage": { "type": "media", "required": true },
10
- "heroImageHint": { "type": "string", "required": true },
11
- "startLabel": { "type": "string", "required": true },
12
- "tourTitle": { "type": "string", "required": true },
13
- "tourIntro": { "type": "text", "required": true },
9
+ "title": {
10
+ "type": "string",
11
+ "required": true
12
+ },
13
+ "intro": {
14
+ "type": "richtext",
15
+ "required": true
16
+ },
17
+ "heroImage": {
18
+ "type": "media",
19
+ "required": true
20
+ },
21
+ "heroImageHint": {
22
+ "type": "string",
23
+ "required": true
24
+ },
25
+ "startLabel": {
26
+ "type": "string",
27
+ "required": true
28
+ },
29
+ "tourTitle": {
30
+ "type": "string",
31
+ "required": true
32
+ },
33
+ "tourIntro": {
34
+ "type": "text",
35
+ "required": true
36
+ },
14
37
  "steps": {
15
38
  "type": "blocks",
16
39
  "min": 4,
17
40
  "max": 4,
18
41
  "schema": {
19
42
  "fields": {
20
- "number": { "type": "string", "required": true },
21
- "title": { "type": "string", "required": true },
22
- "body": { "type": "text", "required": true },
23
- "highlight": { "type": "text" },
24
- "actionLabel": { "type": "string", "required": true },
25
- "action": { "type": "string", "required": true }
43
+ "number": {
44
+ "type": "string",
45
+ "required": true
46
+ },
47
+ "title": {
48
+ "type": "string",
49
+ "required": true
50
+ },
51
+ "body": {
52
+ "type": "text",
53
+ "required": true
54
+ },
55
+ "highlight": {
56
+ "type": "text"
57
+ },
58
+ "actionLabel": {
59
+ "type": "string",
60
+ "required": true
61
+ },
62
+ "action": {
63
+ "type": "string",
64
+ "required": true
65
+ }
26
66
  }
27
67
  }
28
68
  },
29
- "articlesTitle": { "type": "string", "required": true },
30
- "articlesIntro": { "type": "text", "required": true },
31
- "migrationTitle": { "type": "string", "required": true },
32
- "migrationBody": { "type": "richtext", "required": true },
33
- "migrationPrompt": { "type": "text", "required": true },
34
- "buildTitle": { "type": "string", "required": true },
35
- "buildBody": { "type": "richtext", "required": true },
36
- "closingTitle": { "type": "string", "required": true },
37
- "closingBody": { "type": "text", "required": true }
69
+ "articlesTitle": {
70
+ "type": "string",
71
+ "required": true
72
+ },
73
+ "articlesIntro": {
74
+ "type": "text",
75
+ "required": true
76
+ },
77
+ "migrationTitle": {
78
+ "type": "string",
79
+ "required": true
80
+ },
81
+ "migrationBody": {
82
+ "type": "richtext",
83
+ "required": true
84
+ },
85
+ "migrationPrompt": {
86
+ "type": "text",
87
+ "required": true
88
+ },
89
+ "buildTitle": {
90
+ "type": "string",
91
+ "required": true
92
+ },
93
+ "buildBody": {
94
+ "type": "richtext",
95
+ "required": true
96
+ },
97
+ "closingTitle": {
98
+ "type": "string",
99
+ "required": true
100
+ },
101
+ "closingBody": {
102
+ "type": "text",
103
+ "required": true
104
+ },
105
+ "footerNote": {
106
+ "type": "string",
107
+ "required": true
108
+ }
38
109
  }
39
110
  }