flutterflow-mcp 0.1.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 +124 -0
- package/build/api/flutterflow.d.ts +11 -0
- package/build/api/flutterflow.js +61 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +54 -0
- package/build/prompts/dev-workflow.d.ts +2 -0
- package/build/prompts/dev-workflow.js +68 -0
- package/build/prompts/generate-page.d.ts +2 -0
- package/build/prompts/generate-page.js +36 -0
- package/build/prompts/inspect-project.d.ts +2 -0
- package/build/prompts/inspect-project.js +30 -0
- package/build/prompts/modify-component.d.ts +2 -0
- package/build/prompts/modify-component.js +39 -0
- package/build/resources/docs.d.ts +2 -0
- package/build/resources/docs.js +76 -0
- package/build/resources/projects.d.ts +3 -0
- package/build/resources/projects.js +60 -0
- package/build/tools/find-component-usages.d.ts +7 -0
- package/build/tools/find-component-usages.js +225 -0
- package/build/tools/find-page-navigations.d.ts +7 -0
- package/build/tools/find-page-navigations.js +228 -0
- package/build/tools/get-component-summary.d.ts +22 -0
- package/build/tools/get-component-summary.js +193 -0
- package/build/tools/get-page-by-name.d.ts +3 -0
- package/build/tools/get-page-by-name.js +56 -0
- package/build/tools/get-page-summary.d.ts +22 -0
- package/build/tools/get-page-summary.js +220 -0
- package/build/tools/get-yaml-docs.d.ts +6 -0
- package/build/tools/get-yaml-docs.js +217 -0
- package/build/tools/get-yaml.d.ts +3 -0
- package/build/tools/get-yaml.js +47 -0
- package/build/tools/list-files.d.ts +3 -0
- package/build/tools/list-files.js +30 -0
- package/build/tools/list-pages.d.ts +25 -0
- package/build/tools/list-pages.js +101 -0
- package/build/tools/list-projects.d.ts +3 -0
- package/build/tools/list-projects.js +19 -0
- package/build/tools/sync-project.d.ts +3 -0
- package/build/tools/sync-project.js +144 -0
- package/build/tools/update-yaml.d.ts +3 -0
- package/build/tools/update-yaml.js +24 -0
- package/build/tools/validate-yaml.d.ts +3 -0
- package/build/tools/validate-yaml.js +22 -0
- package/build/utils/cache.d.ts +48 -0
- package/build/utils/cache.js +162 -0
- package/build/utils/decode-yaml.d.ts +7 -0
- package/build/utils/decode-yaml.js +31 -0
- package/build/utils/page-summary/action-summarizer.d.ts +9 -0
- package/build/utils/page-summary/action-summarizer.js +291 -0
- package/build/utils/page-summary/formatter.d.ts +13 -0
- package/build/utils/page-summary/formatter.js +121 -0
- package/build/utils/page-summary/node-extractor.d.ts +17 -0
- package/build/utils/page-summary/node-extractor.js +207 -0
- package/build/utils/page-summary/tree-walker.d.ts +6 -0
- package/build/utils/page-summary/tree-walker.js +55 -0
- package/build/utils/page-summary/types.d.ts +56 -0
- package/build/utils/page-summary/types.js +4 -0
- package/build/utils/parse-folders.d.ts +9 -0
- package/build/utils/parse-folders.js +29 -0
- package/docs/ff-yaml/00-overview.md +137 -0
- package/docs/ff-yaml/01-project-files.md +513 -0
- package/docs/ff-yaml/02-pages.md +572 -0
- package/docs/ff-yaml/03-components.md +413 -0
- package/docs/ff-yaml/04-widgets/README.md +122 -0
- package/docs/ff-yaml/04-widgets/button.md +444 -0
- package/docs/ff-yaml/04-widgets/container.md +358 -0
- package/docs/ff-yaml/04-widgets/dropdown.md +579 -0
- package/docs/ff-yaml/04-widgets/form.md +256 -0
- package/docs/ff-yaml/04-widgets/image.md +276 -0
- package/docs/ff-yaml/04-widgets/layout.md +355 -0
- package/docs/ff-yaml/04-widgets/misc.md +553 -0
- package/docs/ff-yaml/04-widgets/text-field.md +326 -0
- package/docs/ff-yaml/04-widgets/text.md +302 -0
- package/docs/ff-yaml/05-actions.md +843 -0
- package/docs/ff-yaml/06-variables.md +834 -0
- package/docs/ff-yaml/07-data.md +591 -0
- package/docs/ff-yaml/08-custom-code.md +715 -0
- package/docs/ff-yaml/09-theming.md +592 -0
- package/docs/ff-yaml/10-editing-guide.md +454 -0
- package/docs/ff-yaml/README.md +105 -0
- package/package.json +55 -0
- package/skills/ff-widget-patterns.md +141 -0
- package/skills/ff-yaml-dev.md +58 -0
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
# Pages
|
|
2
|
+
|
|
3
|
+
A page in FlutterFlow is a `Scaffold`-rooted widget tree stored across multiple YAML files: a metadata file, a widget tree outline, and individual node files for each widget.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Page Metadata File
|
|
8
|
+
|
|
9
|
+
**File key:** `page/id-Scaffold_XXX`
|
|
10
|
+
|
|
11
|
+
The metadata file defines the page name, description, parameters (route params), and class model (state fields, database request managers).
|
|
12
|
+
|
|
13
|
+
### Minimal page (no params, no state)
|
|
14
|
+
|
|
15
|
+
```yaml
|
|
16
|
+
name: Welcome
|
|
17
|
+
node:
|
|
18
|
+
key: Scaffold_7o6kzmdm
|
|
19
|
+
classModel: {}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Page with route parameters
|
|
23
|
+
|
|
24
|
+
```yaml
|
|
25
|
+
name: ForgotPassword
|
|
26
|
+
description: ""
|
|
27
|
+
params:
|
|
28
|
+
ea1mfx: # param key (short hash)
|
|
29
|
+
identifier:
|
|
30
|
+
name: forhotOrChange
|
|
31
|
+
key: ea1mfx
|
|
32
|
+
defaultValue:
|
|
33
|
+
serializedValue: Forgot
|
|
34
|
+
dataType:
|
|
35
|
+
scalarType: String
|
|
36
|
+
nonNullable: true
|
|
37
|
+
node:
|
|
38
|
+
key: Scaffold_084rppkk
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Page with Document-type route parameters
|
|
42
|
+
|
|
43
|
+
```yaml
|
|
44
|
+
name: GoldPassLocationDealsNew
|
|
45
|
+
description: ""
|
|
46
|
+
params:
|
|
47
|
+
9sv9w2:
|
|
48
|
+
identifier:
|
|
49
|
+
name: establishment
|
|
50
|
+
key: 9sv9w2
|
|
51
|
+
dataType:
|
|
52
|
+
scalarType: Document
|
|
53
|
+
nonNullable: true
|
|
54
|
+
subType:
|
|
55
|
+
collectionIdentifier:
|
|
56
|
+
name: Establishments
|
|
57
|
+
key: k2ktdun9
|
|
58
|
+
66hyy2:
|
|
59
|
+
identifier:
|
|
60
|
+
name: redeemedDeel
|
|
61
|
+
key: 66hyy2
|
|
62
|
+
dataType:
|
|
63
|
+
scalarType: Document
|
|
64
|
+
nonNullable: false
|
|
65
|
+
subType:
|
|
66
|
+
collectionIdentifier:
|
|
67
|
+
name: EstablishmentDeals
|
|
68
|
+
key: kynkvveh
|
|
69
|
+
node:
|
|
70
|
+
key: Scaffold_4qdr9nq8
|
|
71
|
+
classModel:
|
|
72
|
+
stateFields:
|
|
73
|
+
- ...
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Schema reference
|
|
77
|
+
|
|
78
|
+
| Field | Type | Required | Description |
|
|
79
|
+
|---|---|---|---|
|
|
80
|
+
| `name` | string | yes | Human-readable page name |
|
|
81
|
+
| `description` | string | no | Page description |
|
|
82
|
+
| `params` | map | no | Route parameters keyed by param key hash |
|
|
83
|
+
| `params.<key>.identifier` | `{name, key}` | yes | Parameter identity |
|
|
84
|
+
| `params.<key>.defaultValue` | `{serializedValue}` | no | Default value |
|
|
85
|
+
| `params.<key>.dataType` | object | yes | Type definition (`scalarType`, `nonNullable`, `subType`) |
|
|
86
|
+
| `node.key` | string | yes | Scaffold widget key (format: `Scaffold_XXXXXXXX`) |
|
|
87
|
+
| `classModel` | object | no | State fields and database request managers |
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 2. Widget Tree Outline
|
|
92
|
+
|
|
93
|
+
**File key:** `page/id-Scaffold_XXX/page-widget-tree-outline`
|
|
94
|
+
|
|
95
|
+
Defines the hierarchical parent-child structure of widgets. Contains only keys -- no props, no styling. The Scaffold's `body` is the entry point.
|
|
96
|
+
|
|
97
|
+
```yaml
|
|
98
|
+
node:
|
|
99
|
+
key: Scaffold_084rppkk
|
|
100
|
+
body:
|
|
101
|
+
key: Container_3fyaj5aa
|
|
102
|
+
children:
|
|
103
|
+
- key: Column_ama70fo8
|
|
104
|
+
children:
|
|
105
|
+
- key: IconButton_5n2qcf1m
|
|
106
|
+
- key: Column_cbgwkyuy
|
|
107
|
+
children:
|
|
108
|
+
- key: Text_lrclq8sc
|
|
109
|
+
- key: Text_888c0du0
|
|
110
|
+
- key: Form_wsu51ee2
|
|
111
|
+
children:
|
|
112
|
+
- key: TextField_hsymipjw
|
|
113
|
+
- key: Column_46ybd5zs
|
|
114
|
+
children:
|
|
115
|
+
- key: Button_uaqbabys
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Key format
|
|
119
|
+
|
|
120
|
+
Widget keys follow the pattern `WidgetType_XXXXXXXX` where the suffix is an 8-character alphanumeric hash. Examples:
|
|
121
|
+
- `Scaffold_084rppkk`
|
|
122
|
+
- `Column_ama70fo8`
|
|
123
|
+
- `Text_lrclq8sc`
|
|
124
|
+
- `Button_uaqbabys`
|
|
125
|
+
- `Container_3fyaj5aa`
|
|
126
|
+
|
|
127
|
+
### Structure rules
|
|
128
|
+
|
|
129
|
+
- The root is always `node.key` matching the Scaffold key.
|
|
130
|
+
- `body` contains the top-level child (typically a Container).
|
|
131
|
+
- `children` is an ordered array of child widget key references.
|
|
132
|
+
- Leaf widgets have no `children` field.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 3. Node Files
|
|
137
|
+
|
|
138
|
+
**File key:** `page/id-Scaffold_XXX/page-widget-tree-outline/node/id-Widget_YYY`
|
|
139
|
+
|
|
140
|
+
Each widget in the tree has its own node file containing the full widget definition: type, props, name, and parameter values.
|
|
141
|
+
|
|
142
|
+
### Universal node structure
|
|
143
|
+
|
|
144
|
+
```yaml
|
|
145
|
+
key: Widget_XXXXXXXX # matches the key in the tree outline
|
|
146
|
+
type: WidgetType # Flutter widget type
|
|
147
|
+
props:
|
|
148
|
+
<widgetType>: # type-specific props object
|
|
149
|
+
...
|
|
150
|
+
padding: {} # optional padding
|
|
151
|
+
responsiveVisibility: {} # optional responsive settings
|
|
152
|
+
opacity: # optional opacity
|
|
153
|
+
opacityValue:
|
|
154
|
+
inputValue: 1
|
|
155
|
+
animatedOpacity: {}
|
|
156
|
+
name: OptionalWidgetName # human-readable name (optional)
|
|
157
|
+
parameterValues: {} # parameter pass-through values (optional)
|
|
158
|
+
valueKey: {} # form value key (optional)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Scaffold node
|
|
162
|
+
|
|
163
|
+
```yaml
|
|
164
|
+
key: Scaffold_084rppkk
|
|
165
|
+
type: Scaffold
|
|
166
|
+
props:
|
|
167
|
+
scaffold:
|
|
168
|
+
safeArea: true
|
|
169
|
+
hideKeyboardOnTap: true
|
|
170
|
+
backgroundColorValue:
|
|
171
|
+
variable:
|
|
172
|
+
source: FUNCTION_CALL
|
|
173
|
+
functionCall:
|
|
174
|
+
conditionalValue: ...
|
|
175
|
+
navBarItem:
|
|
176
|
+
navIcon: ...
|
|
177
|
+
show: false
|
|
178
|
+
name: ForgotPassword
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Text node
|
|
182
|
+
|
|
183
|
+
```yaml
|
|
184
|
+
key: Text_lrclq8sc
|
|
185
|
+
type: Text
|
|
186
|
+
props:
|
|
187
|
+
text:
|
|
188
|
+
themeStyle: HEADLINE_MEDIUM
|
|
189
|
+
selectable: false
|
|
190
|
+
textValue:
|
|
191
|
+
variable:
|
|
192
|
+
source: WIDGET_CLASS_PARAMETER
|
|
193
|
+
defaultValue:
|
|
194
|
+
serializedValue: Forgot
|
|
195
|
+
baseVariable:
|
|
196
|
+
widgetClass:
|
|
197
|
+
paramIdentifier:
|
|
198
|
+
name: forhotOrChange
|
|
199
|
+
key: ea1mfx
|
|
200
|
+
nodeKeyRef:
|
|
201
|
+
key: Scaffold_084rppkk
|
|
202
|
+
mostRecentInputValue: Forgot
|
|
203
|
+
colorValue:
|
|
204
|
+
inputValue:
|
|
205
|
+
themeColor: PRIMARY_TEXT
|
|
206
|
+
fontWeightValue:
|
|
207
|
+
inputValue: w600
|
|
208
|
+
padding: {}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Button node
|
|
212
|
+
|
|
213
|
+
```yaml
|
|
214
|
+
key: Button_uaqbabys
|
|
215
|
+
type: Button
|
|
216
|
+
props:
|
|
217
|
+
button:
|
|
218
|
+
text:
|
|
219
|
+
themeStyle: TITLE_MEDIUM
|
|
220
|
+
textValue:
|
|
221
|
+
inputValue: Send OTP
|
|
222
|
+
colorValue:
|
|
223
|
+
inputValue:
|
|
224
|
+
value: "4279506971"
|
|
225
|
+
borderRadius:
|
|
226
|
+
type: FF_BORDER_RADIUS_ALL
|
|
227
|
+
allValue:
|
|
228
|
+
inputValue: 8
|
|
229
|
+
dimensions:
|
|
230
|
+
width:
|
|
231
|
+
pixelsValue:
|
|
232
|
+
inputValue: Infinity # Infinity = match parent
|
|
233
|
+
height:
|
|
234
|
+
pixelsValue:
|
|
235
|
+
inputValue: 50
|
|
236
|
+
elevationValue:
|
|
237
|
+
inputValue: 0
|
|
238
|
+
fillColorValue:
|
|
239
|
+
inputValue:
|
|
240
|
+
value: "4287097512" # ARGB integer as string
|
|
241
|
+
padding: {}
|
|
242
|
+
name: SendLinkButton
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### TextField node
|
|
246
|
+
|
|
247
|
+
```yaml
|
|
248
|
+
key: TextField_hsymipjw
|
|
249
|
+
type: TextField
|
|
250
|
+
props:
|
|
251
|
+
textField:
|
|
252
|
+
textStyle:
|
|
253
|
+
themeStyle: BODY_MEDIUM
|
|
254
|
+
inputDecoration:
|
|
255
|
+
inputBorderType: outline
|
|
256
|
+
borderRadius:
|
|
257
|
+
type: FF_BORDER_RADIUS_ALL
|
|
258
|
+
allValue:
|
|
259
|
+
inputValue: 8
|
|
260
|
+
hintText:
|
|
261
|
+
textValue:
|
|
262
|
+
inputValue: Email
|
|
263
|
+
filledValue:
|
|
264
|
+
inputValue: true
|
|
265
|
+
fillColorValue:
|
|
266
|
+
inputValue:
|
|
267
|
+
themeColor: SECONDARY_BACKGROUND
|
|
268
|
+
keyboardType: EMAIL_ADDRESS
|
|
269
|
+
maxLinesValue:
|
|
270
|
+
inputValue: 1
|
|
271
|
+
padding: {}
|
|
272
|
+
name: emailTextField
|
|
273
|
+
parameterValues: {}
|
|
274
|
+
valueKey: {}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Column node
|
|
278
|
+
|
|
279
|
+
```yaml
|
|
280
|
+
key: Column_ama70fo8
|
|
281
|
+
type: Column
|
|
282
|
+
props:
|
|
283
|
+
column:
|
|
284
|
+
crossAxisAlignment: cross_axis_start
|
|
285
|
+
listSpacing:
|
|
286
|
+
spacingValue:
|
|
287
|
+
inputValue: 24
|
|
288
|
+
minSizeValue:
|
|
289
|
+
inputValue: false
|
|
290
|
+
padding:
|
|
291
|
+
leftValue:
|
|
292
|
+
inputValue: 24
|
|
293
|
+
topValue:
|
|
294
|
+
inputValue: 24
|
|
295
|
+
rightValue:
|
|
296
|
+
inputValue: 24
|
|
297
|
+
bottomValue:
|
|
298
|
+
inputValue: 24
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Container node (body wrapper)
|
|
302
|
+
|
|
303
|
+
```yaml
|
|
304
|
+
key: Container_3fyaj5aa
|
|
305
|
+
type: Container
|
|
306
|
+
props:
|
|
307
|
+
container:
|
|
308
|
+
dimensions: {}
|
|
309
|
+
boxDecoration:
|
|
310
|
+
boxShadow: {}
|
|
311
|
+
image: {}
|
|
312
|
+
maxDimensions: {}
|
|
313
|
+
minDimensions: {}
|
|
314
|
+
responsiveVisibility: {}
|
|
315
|
+
opacity:
|
|
316
|
+
opacityValue:
|
|
317
|
+
inputValue: 1
|
|
318
|
+
animatedOpacity: {}
|
|
319
|
+
valueKey: {}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## 4. Action Triggers
|
|
325
|
+
|
|
326
|
+
**File key:** `page/id-Scaffold_XXX/page-widget-tree-outline/node/id-Widget_YYY/trigger_actions/id-ON_TAP`
|
|
327
|
+
|
|
328
|
+
Action triggers define what happens when a user interacts with a widget. Each trigger file contains the action chain root and its type.
|
|
329
|
+
|
|
330
|
+
### Trigger file
|
|
331
|
+
|
|
332
|
+
```yaml
|
|
333
|
+
rootAction:
|
|
334
|
+
key: w96eorw3
|
|
335
|
+
action:
|
|
336
|
+
key: 3xmlbwbu # references the first action file
|
|
337
|
+
trigger:
|
|
338
|
+
triggerType: ON_TAP
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Common trigger types
|
|
342
|
+
|
|
343
|
+
| Trigger | Description |
|
|
344
|
+
|---|---|
|
|
345
|
+
| `ON_TAP` | Widget tap/click |
|
|
346
|
+
| `ON_INIT_STATE` | Widget initialization |
|
|
347
|
+
| `ON_PAGE_LOAD` | Page load |
|
|
348
|
+
| `CALLBACK-<key>` | Callback from Action parameter (e.g., `CALLBACK-bins86`) |
|
|
349
|
+
|
|
350
|
+
### Chained actions
|
|
351
|
+
|
|
352
|
+
When multiple actions run sequentially, `followUpAction` chains them:
|
|
353
|
+
|
|
354
|
+
```yaml
|
|
355
|
+
rootAction:
|
|
356
|
+
key: hahdlax9
|
|
357
|
+
action:
|
|
358
|
+
key: rpdoow9v # first action
|
|
359
|
+
followUpAction:
|
|
360
|
+
key: v3ka0b6f
|
|
361
|
+
action:
|
|
362
|
+
key: 3pkrta9w # second action
|
|
363
|
+
followUpAction:
|
|
364
|
+
key: fkllh8cj
|
|
365
|
+
conditionActions: # conditional branching
|
|
366
|
+
trueActions:
|
|
367
|
+
- condition:
|
|
368
|
+
variable:
|
|
369
|
+
source: ACTION_OUTPUTS
|
|
370
|
+
...
|
|
371
|
+
trueAction:
|
|
372
|
+
key: gznngoyf
|
|
373
|
+
action:
|
|
374
|
+
key: di4vmbca
|
|
375
|
+
falseAction:
|
|
376
|
+
key: x8ovbrlm
|
|
377
|
+
action:
|
|
378
|
+
key: xw8zabog
|
|
379
|
+
trigger:
|
|
380
|
+
triggerType: ON_TAP
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Action files
|
|
384
|
+
|
|
385
|
+
**File key:** `page/id-Scaffold_XXX/page-widget-tree-outline/node/id-Widget_YYY/trigger_actions/id-ON_TAP/action/id-ACTIONKEY`
|
|
386
|
+
|
|
387
|
+
Each action is a separate file. The action type is the top-level key.
|
|
388
|
+
|
|
389
|
+
**Navigate back:**
|
|
390
|
+
|
|
391
|
+
```yaml
|
|
392
|
+
navigate:
|
|
393
|
+
isNavigateBack: true
|
|
394
|
+
navigateToRootPageOnFailure: true
|
|
395
|
+
key: 3xmlbwbu
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
**Navigate to page with params:**
|
|
399
|
+
|
|
400
|
+
```yaml
|
|
401
|
+
navigate:
|
|
402
|
+
allowBack: true
|
|
403
|
+
passedParameters:
|
|
404
|
+
parameterPasses:
|
|
405
|
+
kawias:
|
|
406
|
+
paramIdentifier:
|
|
407
|
+
name: isChange
|
|
408
|
+
key: kawias
|
|
409
|
+
inputValue: {}
|
|
410
|
+
widgetClassNodeKeyRef:
|
|
411
|
+
key: Scaffold_tydsj8ql
|
|
412
|
+
isNavigateBack: false
|
|
413
|
+
pageNodeKeyRef:
|
|
414
|
+
key: Scaffold_tydsj8ql
|
|
415
|
+
key: f334uqb4
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
**Validate form:**
|
|
419
|
+
|
|
420
|
+
```yaml
|
|
421
|
+
outputVariableName: validateEmail
|
|
422
|
+
validateFormAction:
|
|
423
|
+
formNodeKeyPath:
|
|
424
|
+
keyPath:
|
|
425
|
+
- key: Form_wsu51ee2
|
|
426
|
+
key: rpdoow9v
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
**Execute callback (Action parameter):**
|
|
430
|
+
|
|
431
|
+
```yaml
|
|
432
|
+
key: gt91qt34
|
|
433
|
+
executeCallbackAction:
|
|
434
|
+
parameterIdentifier:
|
|
435
|
+
name: extendAnalysis
|
|
436
|
+
key: 326n4o
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## 5. Page Parameters (Route Params)
|
|
442
|
+
|
|
443
|
+
Page parameters are defined in `params` at the top level of the page metadata file. They are passed when navigating to the page.
|
|
444
|
+
|
|
445
|
+
### Parameter definition schema
|
|
446
|
+
|
|
447
|
+
```yaml
|
|
448
|
+
params:
|
|
449
|
+
<paramKey>:
|
|
450
|
+
identifier:
|
|
451
|
+
name: <paramName> # human-readable name
|
|
452
|
+
key: <paramKey> # short hash key
|
|
453
|
+
defaultValue: # optional
|
|
454
|
+
serializedValue: <value>
|
|
455
|
+
dataType:
|
|
456
|
+
scalarType: <type> # String, Integer, Boolean, Document, etc.
|
|
457
|
+
nonNullable: <bool> # optional, defaults to false
|
|
458
|
+
subType: # required for Document type
|
|
459
|
+
collectionIdentifier:
|
|
460
|
+
name: <CollectionName>
|
|
461
|
+
key: <collectionKey>
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### Referencing a page parameter in a widget
|
|
465
|
+
|
|
466
|
+
Use `source: WIDGET_CLASS_PARAMETER` in a value expression:
|
|
467
|
+
|
|
468
|
+
```yaml
|
|
469
|
+
textValue:
|
|
470
|
+
variable:
|
|
471
|
+
source: WIDGET_CLASS_PARAMETER
|
|
472
|
+
defaultValue:
|
|
473
|
+
serializedValue: Forgot
|
|
474
|
+
baseVariable:
|
|
475
|
+
widgetClass:
|
|
476
|
+
paramIdentifier:
|
|
477
|
+
name: forhotOrChange
|
|
478
|
+
key: ea1mfx
|
|
479
|
+
nodeKeyRef:
|
|
480
|
+
key: Scaffold_084rppkk # the page's Scaffold key
|
|
481
|
+
mostRecentInputValue: Forgot # must match inputValue
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
---
|
|
485
|
+
|
|
486
|
+
## 6. Page State Fields
|
|
487
|
+
|
|
488
|
+
State fields are defined in `classModel.stateFields` in the page metadata file. They are mutable local state scoped to the page.
|
|
489
|
+
|
|
490
|
+
### State field definition
|
|
491
|
+
|
|
492
|
+
```yaml
|
|
493
|
+
classModel:
|
|
494
|
+
stateFields:
|
|
495
|
+
- parameter:
|
|
496
|
+
identifier:
|
|
497
|
+
name: isEntitled
|
|
498
|
+
key: llh25
|
|
499
|
+
defaultValue:
|
|
500
|
+
serializedValue: "false"
|
|
501
|
+
dataType:
|
|
502
|
+
scalarType: Boolean
|
|
503
|
+
nonNullable: true
|
|
504
|
+
serializedDefaultValue:
|
|
505
|
+
- "false"
|
|
506
|
+
- parameter:
|
|
507
|
+
identifier:
|
|
508
|
+
name: selectedDeal
|
|
509
|
+
key: cxtga
|
|
510
|
+
dataType:
|
|
511
|
+
scalarType: Document
|
|
512
|
+
subType:
|
|
513
|
+
collectionIdentifier:
|
|
514
|
+
name: EstablishmentDeals
|
|
515
|
+
key: kynkvveh
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
### Database request managers
|
|
519
|
+
|
|
520
|
+
Pages can also have `databaseRequestManagers` in their classModel for backend queries:
|
|
521
|
+
|
|
522
|
+
```yaml
|
|
523
|
+
classModel:
|
|
524
|
+
databaseRequestManagers:
|
|
525
|
+
- identifier:
|
|
526
|
+
name: dealsNumber
|
|
527
|
+
key: 92hgj
|
|
528
|
+
originalNodeKeyRef:
|
|
529
|
+
key: Container_jpvj37wl
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
### Updating state from an action
|
|
533
|
+
|
|
534
|
+
The `localStateUpdate` action type modifies state fields:
|
|
535
|
+
|
|
536
|
+
```yaml
|
|
537
|
+
localStateUpdate:
|
|
538
|
+
updates:
|
|
539
|
+
- fieldIdentifier:
|
|
540
|
+
key: o29r4 # matches stateField key
|
|
541
|
+
setValue:
|
|
542
|
+
variable:
|
|
543
|
+
source: LOCAL_STATE
|
|
544
|
+
baseVariable:
|
|
545
|
+
localState:
|
|
546
|
+
fieldIdentifier:
|
|
547
|
+
name: user
|
|
548
|
+
key: cxensw6z
|
|
549
|
+
stateVariableType: APP_STATE
|
|
550
|
+
updateType: WIDGET
|
|
551
|
+
stateVariableType: WIDGET_CLASS_STATE
|
|
552
|
+
key: qe82s7k1
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
---
|
|
556
|
+
|
|
557
|
+
## 7. File Key Patterns
|
|
558
|
+
|
|
559
|
+
| Pattern | Purpose |
|
|
560
|
+
|---|---|
|
|
561
|
+
| `page/id-Scaffold_XXX` | Page metadata (name, params, classModel) |
|
|
562
|
+
| `page/id-Scaffold_XXX/page-widget-tree-outline` | Widget tree hierarchy (keys only) |
|
|
563
|
+
| `page/id-Scaffold_XXX/page-widget-tree-outline/node/id-Widget_YYY` | Individual widget definition |
|
|
564
|
+
| `page/id-Scaffold_XXX/page-widget-tree-outline/node/id-Widget_YYY/trigger_actions/id-ON_TAP` | Action trigger (ON_TAP, ON_INIT_STATE, etc.) |
|
|
565
|
+
| `page/id-Scaffold_XXX/page-widget-tree-outline/node/id-Widget_YYY/trigger_actions/id-ON_TAP/action/id-ACTIONKEY` | Individual action in the chain |
|
|
566
|
+
|
|
567
|
+
### Notes
|
|
568
|
+
|
|
569
|
+
- **Page metadata is separate from the widget tree.** The `page/id-Scaffold_XXX` file only stores name, params, and classModel. Widget children embedded inline are stripped by the server.
|
|
570
|
+
- **Use node-level file keys for targeted edits.** Editing a single widget does not require re-uploading the entire page.
|
|
571
|
+
- **Action triggers nest under node files.** The trigger type is the folder name (`id-ON_TAP`, `id-ON_INIT_STATE`, `id-CALLBACK-<key>`).
|
|
572
|
+
- **Action chains are separate files.** Each action in a chain has its own file under the trigger's `action/` subdirectory.
|