@lowdefy/docs-content 0.0.0-experimental-20260928120643 → 6.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 +0 -1
- package/content/actions/link.md +0 -17
- package/content/actions/login.md +5 -23
- package/content/actions/logout.md +5 -5
- package/content/actions/pdfmake.md +2 -2
- package/content/actions/setdarkmode.md +2 -2
- package/content/agents/agent-properties.md +2 -4
- package/content/agents/agentchat.md +6 -21
- package/content/agents/agentconversations.md +2 -2
- package/content/concepts/ai-agent-docs.md +101 -313
- package/content/concepts/cli.md +3 -34
- package/content/concepts/connections-and-requests.md +0 -402
- package/content/concepts/custom-html.md +0 -40
- package/content/concepts/custom-styling.md +5 -50
- package/content/concepts/events-and-actions.md +2 -64
- package/content/concepts/i18n.md +2 -7
- package/content/concepts/keyboard-shortcuts.md +2 -2
- package/content/concepts/layout-overview.md +1 -1
- package/content/concepts/logger.md +0 -81
- package/content/concepts/lowdefy-schema.md +1 -4
- package/content/concepts/menus.md +7 -7
- package/content/concepts/module-authoring.md +2 -2
- package/content/connections/anthropic.md +2 -162
- package/content/connections/awss3.md +0 -54
- package/content/connections/google.md +2 -162
- package/content/connections/mongodb.md +3 -121
- package/content/connections/openai-connection.md +2 -162
- package/content/container-blocks/affix.md +7 -47
- package/content/container-blocks/alert.md +24 -76
- package/content/container-blocks/badge.md +24 -100
- package/content/container-blocks/box.md +9 -9
- package/content/container-blocks/card.md +25 -80
- package/content/container-blocks/carousel.md +7 -60
- package/content/container-blocks/collapse.md +9 -87
- package/content/container-blocks/configprovider.md +13 -35
- package/content/container-blocks/confirmmodal.md +23 -69
- package/content/container-blocks/content.md +98 -62
- package/content/container-blocks/descriptions.md +4 -45
- package/content/container-blocks/drawer.md +28 -92
- package/content/container-blocks/dropdownmenu.md +31 -119
- package/content/container-blocks/flex.md +62 -40
- package/content/container-blocks/footer.md +11 -15
- package/content/container-blocks/googlemapsheatmap.md +1 -1
- package/content/container-blocks/googlemapsscript.md +2 -2
- package/content/container-blocks/header.md +36 -71
- package/content/container-blocks/label.md +7 -34
- package/content/container-blocks/layout.md +34 -52
- package/content/container-blocks/masonry.md +71 -17
- package/content/container-blocks/mobilemenu.md +88 -131
- package/content/container-blocks/modal.md +26 -114
- package/content/container-blocks/pageheadermenu.md +31 -81
- package/content/container-blocks/pagesidebarlayout.md +26 -169
- package/content/container-blocks/pagesidermenu.md +42 -95
- package/content/container-blocks/popover.md +31 -34
- package/content/container-blocks/result.md +21 -32
- package/content/container-blocks/sider.md +122 -85
- package/content/container-blocks/span.md +7 -7
- package/content/container-blocks/spinner.md +3 -3
- package/content/container-blocks/splitter.md +68 -150
- package/content/container-blocks/tabs.md +12 -64
- package/content/container-blocks/tooltip.md +46 -22
- package/content/container-blocks/watermark.md +4 -22
- package/content/controls/reject.md +2 -4
- package/content/controls/throw.md +0 -1
- package/content/controls/try.md +2 -3
- package/content/deployment/deployment-environments.md +6 -8
- package/content/deployment/docker.md +7 -22
- package/content/deployment/node-server.md +0 -4
- package/content/deployment/vercel.md +6 -13
- package/content/display-blocks/aggrid.md +11 -26
- package/content/display-blocks/anchor.md +15 -15
- package/content/display-blocks/avatar.md +37 -57
- package/content/display-blocks/breadcrumb.md +21 -70
- package/content/display-blocks/button.md +18 -92
- package/content/display-blocks/calendar.md +0 -12
- package/content/display-blocks/dangeroushtml.md +1 -1
- package/content/display-blocks/difflist.md +1 -1
- package/content/display-blocks/difftimeline.md +1 -1
- package/content/display-blocks/divider.md +3 -64
- package/content/display-blocks/dropdownbutton.md +28 -79
- package/content/display-blocks/echart.md +1 -35
- package/content/display-blocks/floatbutton.md +42 -129
- package/content/display-blocks/html.md +1 -61
- package/content/display-blocks/icon.md +67 -250
- package/content/display-blocks/menu.md +73 -145
- package/content/display-blocks/message.md +124 -38
- package/content/display-blocks/notification.md +222 -94
- package/content/display-blocks/paragraph.md +9 -59
- package/content/display-blocks/progress.md +17 -96
- package/content/display-blocks/qrcode.md +4 -19
- package/content/display-blocks/s3download.md +1 -1
- package/content/display-blocks/search.md +7 -17
- package/content/display-blocks/skeletonbutton.md +0 -1
- package/content/display-blocks/skeletoninput.md +0 -1
- package/content/display-blocks/statistic.md +17 -75
- package/content/display-blocks/steps.md +25 -58
- package/content/display-blocks/tag.md +17 -102
- package/content/display-blocks/title.md +11 -50
- package/content/display-blocks/tour.md +23 -33
- package/content/input-blocks/autocomplete.md +9 -81
- package/content/input-blocks/buttonselector.md +8 -45
- package/content/input-blocks/checkboxselector.md +7 -97
- package/content/input-blocks/checkboxswitch.md +3 -33
- package/content/input-blocks/colorselector.md +14 -63
- package/content/input-blocks/daterangeselector.md +45 -165
- package/content/input-blocks/dateselector.md +41 -139
- package/content/input-blocks/datetimeselector.md +49 -158
- package/content/input-blocks/inputgallery.md +3 -3
- package/content/input-blocks/monthselector.md +52 -120
- package/content/input-blocks/multipleselector.md +39 -150
- package/content/input-blocks/numberinput.md +12 -98
- package/content/input-blocks/pagination.md +14 -70
- package/content/input-blocks/paragraphinput.md +37 -51
- package/content/input-blocks/passwordinput.md +6 -60
- package/content/input-blocks/phonenumberinput.md +26 -59
- package/content/input-blocks/radioselector.md +7 -83
- package/content/input-blocks/ratingslider.md +26 -57
- package/content/input-blocks/s3uploadbutton.md +24 -24
- package/content/input-blocks/s3uploaddragger.md +3 -3
- package/content/input-blocks/s3uploadphoto.md +5 -5
- package/content/input-blocks/segmentedselector.md +32 -72
- package/content/input-blocks/selector.md +21 -109
- package/content/input-blocks/switch.md +17 -65
- package/content/input-blocks/textarea.md +3 -32
- package/content/input-blocks/textinput.md +28 -69
- package/content/input-blocks/tiptapmentioninput.md +1 -1
- package/content/input-blocks/titleinput.md +12 -39
- package/content/input-blocks/treeinput.md +25 -49
- package/content/input-blocks/treemultipleselector.md +10 -127
- package/content/input-blocks/treeselector.md +9 -97
- package/content/input-blocks/upload.md +15 -64
- package/content/input-blocks/uploaddragger.md +1 -17
- package/content/input-blocks/uploadphoto.md +1 -18
- package/content/input-blocks/weekselector.md +55 -120
- package/content/list-blocks/controlledlist.md +15 -24
- package/content/list-blocks/list.md +11 -11
- package/content/list-blocks/masonrylist.md +34 -7
- package/content/migration/upgrade-guide.md +0 -1
- package/content/operators/_app.md +1 -2
- package/content/operators/_error.md +1 -23
- package/content/operators/_get.md +6 -6
- package/content/operators/_operator.md +3 -17
- package/content/operators/_ref.md +0 -258
- package/content/operators/_type.md +3 -14
- package/content/operators/_user.md +3 -3
- package/content/other/introduction.md +1 -1
- package/content/plugins/plugins-dev.md +0 -66
- package/content/plugins/plugins-introduction.md +1 -27
- package/content/testing/e2e-configuration.md +1 -8
- package/content/testing/e2e-getting-started.md +1 -1
- package/content/testing/e2e-introduction.md +1 -1
- package/content/tutorial/tutorial-actions-operators.md +2 -2
- package/content/tutorial/tutorial-add-blocks.md +2 -2
- package/content/tutorial/tutorial-create-page.md +2 -48
- package/content/tutorial/tutorial-display-data-page.md +3 -3
- package/content/tutorial/tutorial-requests-sql.md +0 -153
- package/content/tutorial/tutorial-start.md +1 -66
- package/content/user-authentication/login-and-logout.md +8 -158
- package/content/user-authentication/users-introduction.md +0 -8
- package/index.json +2 -6065
- package/package.json +1 -7
- package/scripts/extractAgentDocs.js +4 -36
- package/content/actions/emailotpsend.md +0 -58
- package/content/actions/emailotpverify.md +0 -77
- package/content/actions/getlocalstorage.md +0 -41
- package/content/actions/magiclinkverify.md +0 -113
- package/content/actions/posthogalias.md +0 -29
- package/content/actions/posthogcapture.md +0 -49
- package/content/actions/posthogcapturepageleave.md +0 -38
- package/content/actions/posthogfeatureflag.md +0 -50
- package/content/actions/posthoggroup.md +0 -37
- package/content/actions/posthogidentify.md +0 -54
- package/content/actions/posthoginit.md +0 -66
- package/content/actions/posthogoptin.md +0 -29
- package/content/actions/posthogoptout.md +0 -29
- package/content/actions/posthogpageview.md +0 -37
- package/content/actions/posthogreloadfeatureflags.md +0 -47
- package/content/actions/posthogreset.md +0 -28
- package/content/actions/posthogsetpersonproperties.md +0 -36
- package/content/actions/removelocalstorage.md +0 -26
- package/content/actions/setlocalstorage.md +0 -32
- package/content/adapter-reference/mongodbauthadapter.md +0 -46
- package/content/agents/agents-introduction.md +0 -107
- package/content/callback-reference/auth0logoutcallback.md +0 -54
- package/content/concepts/blocks.md +0 -150
- package/content/concepts/dynamic-page-content.md +0 -304
- package/content/concepts/html-attributes.md +0 -285
- package/content/concepts/lowdefy-api.md +0 -1110
- package/content/concepts/notifications.md +0 -155
- package/content/concepts/page-and-app-state.md +0 -244
- package/content/concepts/theming.md +0 -582
- package/content/connections/aigateway.md +0 -368
- package/content/connections/axioshttp.md +0 -181
- package/content/controls/while.md +0 -46
- package/content/display-blocks/clickablehtml.md +0 -239
- package/content/display-blocks/eventlog.md +0 -363
- package/content/display-blocks/pollingtimer.md +0 -263
- package/content/input-blocks/captcha.md +0 -40
- package/content/input-blocks/placesautocomplete.md +0 -319
- package/content/input-blocks/tagmultipleselector.md +0 -114
- package/content/input-blocks/tagselector.md +0 -114
- package/content/migration/auth-upgrade.md +0 -327
- package/content/migration/v3-to-v4.md +0 -417
- package/content/migration/v6-to-v7.md +0 -222
- package/content/operators/_cron.md +0 -292
- package/content/other/mongodbadapter.md +0 -3
- package/content/plugins/plugins-icon-sets.md +0 -267
- package/content/plugins/posthog.md +0 -275
- package/content/provider-reference/auth-js-providers.md +0 -107
- package/content/provider-reference/openidconnectprovider.md +0 -44
- package/content/testing/config-tests.md +0 -278
- package/content/tutorial/tutorial-requests-api.md +0 -155
- package/content/user-authentication/auth-configuration.md +0 -266
- package/content/user-authentication/auth-steps.md +0 -138
- package/content/user-authentication/mcp-oauth.md +0 -292
- package/content/user-authentication/organizations.md +0 -221
- package/content/user-authentication/protected-pages-apis.md +0 -97
- package/content/user-authentication/roles.md +0 -49
- package/content/user-authentication/two-factor.md +0 -229
- package/content/user-authentication/user-object.md +0 -58
- package/content/websockets/websocket-publish.md +0 -108
- package/content/websockets/websocket-subscriptions.md +0 -100
- package/content/websockets/websockets-introduction.md +0 -97
- package/hazards.json +0 -44
- package/scripts/hashDocSources.js +0 -38
- package/scripts/recordSourceHashes.js +0 -88
|
@@ -341,39 +341,6 @@ Free standard shipping (3-5 business days). Express shipping available for $9.99
|
|
|
341
341
|
for $9.99 (1-2 business days).
|
|
342
342
|
```
|
|
343
343
|
|
|
344
|
-
Billed every month. Cancel any time.
|
|
345
|
-
|
|
346
|
-
Billed once a year with two months free.
|
|
347
|
-
|
|
348
|
-
```yaml
|
|
349
|
-
- id: centered_tabs
|
|
350
|
-
type: Tabs
|
|
351
|
-
properties:
|
|
352
|
-
centered: true
|
|
353
|
-
tabBarGutter: 40
|
|
354
|
-
indicator:
|
|
355
|
-
size: 24
|
|
356
|
-
align: center
|
|
357
|
-
tabs:
|
|
358
|
-
- key: centered_monthly
|
|
359
|
-
title: Monthly
|
|
360
|
-
- key: centered_yearly
|
|
361
|
-
title: Yearly
|
|
362
|
-
slots:
|
|
363
|
-
centered_monthly:
|
|
364
|
-
blocks:
|
|
365
|
-
- id: centered_monthly_content
|
|
366
|
-
type: Paragraph
|
|
367
|
-
properties:
|
|
368
|
-
content: Billed every month. Cancel any time.
|
|
369
|
-
centered_yearly:
|
|
370
|
-
blocks:
|
|
371
|
-
- id: centered_yearly_content
|
|
372
|
-
type: Paragraph
|
|
373
|
-
properties:
|
|
374
|
-
content: Billed once a year with two months free.
|
|
375
|
-
```
|
|
376
|
-
|
|
377
344
|
**Small:**
|
|
378
345
|
|
|
379
346
|
Compact tabs for dense interfaces where screen space is at a premium. Ideal for side panels and secondary navigation.
|
|
@@ -654,16 +621,16 @@ Monthly target progress at 85%. On track for completion by end of quarter.
|
|
|
654
621
|
tabs:
|
|
655
622
|
- key: icon_home
|
|
656
623
|
title: Home
|
|
657
|
-
icon:
|
|
624
|
+
icon: AiOutlineHome
|
|
658
625
|
- key: icon_users
|
|
659
626
|
title: Users
|
|
660
|
-
icon:
|
|
627
|
+
icon: AiOutlineTeam
|
|
661
628
|
- key: icon_settings
|
|
662
629
|
title: Settings
|
|
663
|
-
icon:
|
|
630
|
+
icon: AiOutlineSetting
|
|
664
631
|
- key: icon_chart
|
|
665
632
|
title: Analytics
|
|
666
|
-
icon:
|
|
633
|
+
icon: AiOutlineBarChart
|
|
667
634
|
slots:
|
|
668
635
|
icon_home:
|
|
669
636
|
blocks:
|
|
@@ -717,17 +684,17 @@ Monthly target progress at 85%. On track for completion by end of quarter.
|
|
|
717
684
|
- key: ci_success
|
|
718
685
|
title: Passed
|
|
719
686
|
icon:
|
|
720
|
-
name:
|
|
687
|
+
name: AiOutlineCheckCircle
|
|
721
688
|
color: "#52c41a"
|
|
722
689
|
- key: ci_warning
|
|
723
690
|
title: Warnings
|
|
724
691
|
icon:
|
|
725
|
-
name:
|
|
692
|
+
name: AiOutlineWarning
|
|
726
693
|
color: "#faad14"
|
|
727
694
|
- key: ci_error
|
|
728
695
|
title: Failed
|
|
729
696
|
icon:
|
|
730
|
-
name:
|
|
697
|
+
name: AiOutlineCloseCircle
|
|
731
698
|
color: "#ff4d4f"
|
|
732
699
|
slots:
|
|
733
700
|
ci_success:
|
|
@@ -885,7 +852,7 @@ Your video library. Supports MP4, WebM, and MOV formats. Maximum file size is 50
|
|
|
885
852
|
flex: 0 0 auto
|
|
886
853
|
properties:
|
|
887
854
|
title: Upload
|
|
888
|
-
icon:
|
|
855
|
+
icon: AiOutlineUpload
|
|
889
856
|
color: primary
|
|
890
857
|
variant: solid
|
|
891
858
|
size: small
|
|
@@ -932,13 +899,13 @@ Yesterday - Alex created 3 new issues in the backlog tracker.
|
|
|
932
899
|
tabs:
|
|
933
900
|
- key: rich_dashboard
|
|
934
901
|
title: Dashboard
|
|
935
|
-
icon:
|
|
902
|
+
icon: AiOutlineDashboard
|
|
936
903
|
- key: rich_team
|
|
937
904
|
title: Team
|
|
938
|
-
icon:
|
|
905
|
+
icon: AiOutlineTeam
|
|
939
906
|
- key: rich_activity
|
|
940
907
|
title: Activity
|
|
941
|
-
icon:
|
|
908
|
+
icon: AiOutlineHistory
|
|
942
909
|
slots:
|
|
943
910
|
rich_dashboard:
|
|
944
911
|
blocks:
|
|
@@ -1697,13 +1664,7 @@ Press Cmd+3 (Mac) or Ctrl+3 (Windows) to jump to this tab.
|
|
|
1697
1664
|
| Property | Type | Default | Description |
|
|
1698
1665
|
| --- | --- | --- | --- |
|
|
1699
1666
|
| `animated` | boolean | `true` | Whether to change tabs with animation. Only works while tabPlacement is top or bottom. |
|
|
1700
|
-
| `centered` | boolean | `false` | Center the tabs in the tab bar. |
|
|
1701
1667
|
| `defaultActiveKey` | string | - | Initial active TabPane's key, if activeKey is not set. |
|
|
1702
|
-
| `destroyOnHidden` | boolean | `false` | Unmount the content of inactive tabs. Blocks in a hidden tab keep their state values. |
|
|
1703
|
-
| `indicator` | object | - | Size and alignment of the active tab indicator (ink bar). |
|
|
1704
|
-
| `indicator.size` | number | - | Length of the indicator in pixels. Defaults to the width of the tab. |
|
|
1705
|
-
| `indicator.align` | string | `"center"` | Alignment of the indicator along the tab when size is set. Enum: `start`, `center`, `end`. |
|
|
1706
|
-
| `tabBarGutter` | number | - | Gap between tabs in pixels. |
|
|
1707
1668
|
| `size` | string | `"default"` | Size of the tabs. Enum: `default`, `small`, `large`. |
|
|
1708
1669
|
| `tabPlacement` | string | `"top"` | Position of the tabs. Enum: `top`, `end`, `bottom`, `start`. |
|
|
1709
1670
|
| `tabType` | string | `"line"` | Type of tabs. Enum: `line`, `card`. |
|
|
@@ -1712,24 +1673,13 @@ Press Cmd+3 (Mac) or Ctrl+3 (Windows) to jump to this tab.
|
|
|
1712
1673
|
| `tabs.$.key` | string | - | Area key of the tab. |
|
|
1713
1674
|
| `tabs.$.eventName` | string | - | Block-level event name to trigger when this tab becomes active, in addition to onChange. Declare an event with this name under `events:`. The event receives `{ key }` of the now-active tab. |
|
|
1714
1675
|
| `tabs.$.disabled` | boolean | `false` | Disable the tab if true. |
|
|
1715
|
-
| `tabs.$.icon` | string \| object | - |
|
|
1716
|
-
| `tabs.$.icon.name` | string | - | Icon name: a semantic name like `edit`, a Lucide icon name like `Pencil`, or a set-qualified name like `tabler:Pencil`. |
|
|
1717
|
-
| `tabs.$.icon.color` | string | - | Icon color. |
|
|
1718
|
-
| `tabs.$.icon.size` | string \| number | - | Size of the icon. Defaults to `theme.icons.size`. |
|
|
1719
|
-
| `tabs.$.icon.rotate` | number | - | Number of degrees to rotate the icon. |
|
|
1720
|
-
| `tabs.$.icon.spin` | boolean | - | Continuously spin the icon with animation. |
|
|
1721
|
-
| `tabs.$.icon.strokeWidth` | number | - | Stroke width of the icon lines, in pixels of the 24px icon grid. Defaults to `theme.icons.strokeWidth` (2). |
|
|
1722
|
-
| `tabs.$.icon.nonScalingStroke` | boolean | - | Keep the stroke width constant at any icon size. Defaults to `theme.icons.nonScalingStroke`. |
|
|
1723
|
-
| `tabs.$.icon.title` | string | - | Icon hover title for accessibility. An empty string marks the icon as decorative. |
|
|
1724
|
-
| `tabs.$.icon.disableLoadingIcon` | boolean | - | While loading after the icon has been clicked, don't render the loading icon. |
|
|
1676
|
+
| `tabs.$.icon` | string \| object | - | Name of an React-Icon (See all icons) or properties of an Icon block to customize icon to show in tab title. |
|
|
1725
1677
|
| `tabs.$.shortcut` | string | - | Keyboard shortcut to switch to this tab. Use "mod" for Cmd/Ctrl. |
|
|
1726
1678
|
| `extraAreaKey` | string | - | Area key for the extra area blocks. |
|
|
1727
1679
|
| `theme` | object | - | Antd design token overrides for this block. See [antd design tokens](https://ant.design/components/overview#design-token). See [Ant Design tabs tokens](https://ant.design/components/tabs#design-token). |
|
|
1728
1680
|
| `theme.cardBg` | string | `"rgba(0, 0, 0, 0.02)"` | Background color of card-type tab. |
|
|
1729
1681
|
| `theme.cardGutter` | number | `2` | Gap between card-type tabs. |
|
|
1730
1682
|
| `theme.cardHeight` | number | `40` | Height of card-type tab. |
|
|
1731
|
-
| `theme.cardHeightSM` | number | `32` | Height of small card-type tab. |
|
|
1732
|
-
| `theme.cardHeightLG` | number | `48` | Height of large card-type tab. |
|
|
1733
1683
|
| `theme.cardPadding` | string | `"8px 16px"` | Padding of card-type tab. |
|
|
1734
1684
|
| `theme.cardPaddingLG` | string | `"11px 16px"` | Padding of large card-type tab. |
|
|
1735
1685
|
| `theme.cardPaddingSM` | string | `"4px 8px"` | Padding of small card-type tab. |
|
|
@@ -1764,7 +1714,5 @@ Press Cmd+3 (Mac) or Ctrl+3 (Windows) to jump to this tab.
|
|
|
1764
1714
|
| `/tabBar` | The Tabs tab bar. |
|
|
1765
1715
|
| `/tabPane` | The Tabs tab pane. |
|
|
1766
1716
|
| `/inkBar` | The Tabs ink bar. |
|
|
1767
|
-
| `/item` | Each tab in the tab bar. |
|
|
1768
|
-
| `/popup` | The dropdown that lists tabs that overflow the tab bar. |
|
|
1769
1717
|
|
|
1770
1718
|
Slot keys are user-defined in your config and resolved at build time — not generated at runtime. The block typically pairs slots with an array property (`tabs`, `panels`, `slides`) listed in the Properties table; see the examples above for the expected shape.
|
|
@@ -689,7 +689,7 @@ Hover over this text to see the tooltip.
|
|
|
689
689
|
layout:
|
|
690
690
|
flex: 0 0 auto
|
|
691
691
|
properties:
|
|
692
|
-
icon:
|
|
692
|
+
icon: AiOutlineDelete
|
|
693
693
|
hideTitle: true
|
|
694
694
|
color: danger
|
|
695
695
|
variant: text
|
|
@@ -749,8 +749,7 @@ Hover over this text to see the tooltip.
|
|
|
749
749
|
flex: 0 0 auto
|
|
750
750
|
properties:
|
|
751
751
|
title: Tooltip with custom overlay style
|
|
752
|
-
|
|
753
|
-
.inner:
|
|
752
|
+
overlayStyle:
|
|
754
753
|
boxShadow: 0 4px 12px rgba(0, 0, 0, 0.3)
|
|
755
754
|
blocks:
|
|
756
755
|
- id: tooltip_overlay_style_btn
|
|
@@ -921,7 +920,7 @@ Hover me (Tailwind element class)
|
|
|
921
920
|
properties:
|
|
922
921
|
title: Tailwind on element wrapper
|
|
923
922
|
class:
|
|
924
|
-
|
|
923
|
+
element: cursor-help
|
|
925
924
|
blocks:
|
|
926
925
|
- id: tooltip_class_element_text
|
|
927
926
|
type: Paragraph
|
|
@@ -934,7 +933,7 @@ Hover me (Tailwind element class)
|
|
|
934
933
|
properties:
|
|
935
934
|
title: Tailwind on inner popup
|
|
936
935
|
class:
|
|
937
|
-
|
|
936
|
+
inner: text-lg font-bold
|
|
938
937
|
blocks:
|
|
939
938
|
- id: tooltip_class_inner_btn
|
|
940
939
|
type: Button
|
|
@@ -1089,19 +1088,47 @@ $8,230
|
|
|
1089
1088
|
properties:
|
|
1090
1089
|
label:
|
|
1091
1090
|
title: Username
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1091
|
+
extra:
|
|
1092
|
+
- id: tooltip_form_username_help
|
|
1093
|
+
type: Tooltip
|
|
1094
|
+
layout:
|
|
1095
|
+
flex: 0 0 auto
|
|
1096
|
+
properties:
|
|
1097
|
+
title: Your unique username. Must be 3-20 characters, letters and numbers only.
|
|
1098
|
+
placement: right
|
|
1099
|
+
blocks:
|
|
1100
|
+
- id: tooltip_form_username_icon
|
|
1101
|
+
type: Icon
|
|
1102
|
+
layout:
|
|
1103
|
+
flex: 0 0 auto
|
|
1104
|
+
properties:
|
|
1105
|
+
name: AiOutlineQuestionCircle
|
|
1106
|
+
size: 14
|
|
1107
|
+
color: "#8c8c8c"
|
|
1095
1108
|
placeholder: Enter your username
|
|
1096
1109
|
- id: tooltip_form_email
|
|
1097
1110
|
type: TextInput
|
|
1098
1111
|
properties:
|
|
1099
1112
|
label:
|
|
1100
1113
|
title: Email Address
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1114
|
+
extra:
|
|
1115
|
+
- id: tooltip_form_email_help
|
|
1116
|
+
type: Tooltip
|
|
1117
|
+
layout:
|
|
1118
|
+
flex: 0 0 auto
|
|
1119
|
+
properties:
|
|
1120
|
+
title: We will send account notifications to this address. You can change it at
|
|
1121
|
+
any time.
|
|
1122
|
+
placement: right
|
|
1123
|
+
blocks:
|
|
1124
|
+
- id: tooltip_form_email_icon
|
|
1125
|
+
type: Icon
|
|
1126
|
+
layout:
|
|
1127
|
+
flex: 0 0 auto
|
|
1128
|
+
properties:
|
|
1129
|
+
name: AiOutlineQuestionCircle
|
|
1130
|
+
size: 14
|
|
1131
|
+
color: "#8c8c8c"
|
|
1105
1132
|
placeholder: Enter your email
|
|
1106
1133
|
```
|
|
1107
1134
|
|
|
@@ -1148,7 +1175,7 @@ Monthly Revenue
|
|
|
1148
1175
|
layout:
|
|
1149
1176
|
flex: 0 0 auto
|
|
1150
1177
|
properties:
|
|
1151
|
-
name:
|
|
1178
|
+
name: AiOutlineInfoCircle
|
|
1152
1179
|
size: 14
|
|
1153
1180
|
color: "#8c8c8c"
|
|
1154
1181
|
- id: tooltip_dashboard_users_stat
|
|
@@ -1193,7 +1220,7 @@ Monthly Revenue
|
|
|
1193
1220
|
layout:
|
|
1194
1221
|
flex: 0 0 auto
|
|
1195
1222
|
properties:
|
|
1196
|
-
name:
|
|
1223
|
+
name: AiOutlineInfoCircle
|
|
1197
1224
|
size: 14
|
|
1198
1225
|
color: "#8c8c8c"
|
|
1199
1226
|
- id: tooltip_dashboard_revenue_stat
|
|
@@ -1210,18 +1237,15 @@ Monthly Revenue
|
|
|
1210
1237
|
|
|
1211
1238
|
| Property | Type | Default | Description |
|
|
1212
1239
|
| --- | --- | --- | --- |
|
|
1213
|
-
| `
|
|
1214
|
-
| `arrow.pointAtCenter` | boolean | `false` | Whether the arrow is pointed at the center of target. |
|
|
1215
|
-
| `arrowPointAtCenter` | boolean | `false` | Whether the arrow is pointed at the center of target. Same as `arrow: { pointAtCenter: true }`. |
|
|
1240
|
+
| `arrowPointAtCenter` | boolean | `false` | Whether the arrow is pointed at the center of target. |
|
|
1216
1241
|
| `autoAdjustOverflow` | boolean | `true` | Whether to adjust popup placement automatically when popup is off screen. |
|
|
1217
1242
|
| `color` | string | - | The background color. |
|
|
1218
1243
|
| `defaultOpen` | boolean | `false` | Whether the floating tooltip card is visible by default. |
|
|
1219
|
-
| `
|
|
1220
|
-
| `destroyTooltipOnHide` | boolean | `false` | Same as destroyOnHidden, which takes precedence. |
|
|
1244
|
+
| `destroyTooltipOnHide` | boolean | `false` | Whether to destroy the tooltip DOM when hidden. |
|
|
1221
1245
|
| `mouseEnterDelay` | number | `0.1` | Delay in seconds, before tooltip is shown on mouse enter. |
|
|
1222
|
-
| `mouseLeaveDelay` | number | `0.1` | Delay in seconds, before tooltip is
|
|
1246
|
+
| `mouseLeaveDelay` | number | `0.1` | Delay in seconds, before tooltip is shown on mouse enter. |
|
|
1223
1247
|
| `placement` | string | `"top"` | The position of the tooltip relative to the target. Enum: `top`, `left`, `right`, `bottom`, `topLeft`, `topRight`, `bottomLeft`, `bottomRight`, `leftTop`, `leftBottom`, `rightTop`, `rightBottom`. |
|
|
1224
|
-
| `trigger` | string | `"hover"` | Tooltip trigger mode.
|
|
1248
|
+
| `trigger` | string | `"hover"` | Tooltip trigger mode. Enum: `hover`, `focus`, `click`. |
|
|
1225
1249
|
| `title` | string | - | Title to show in the title area - supports html. Overwritten by blocks in the title content area. |
|
|
1226
1250
|
| `zIndex` | integer | - | The z-index of the Tooltip. |
|
|
1227
1251
|
| `theme` | object | - | Antd design token overrides for this block. See [antd design tokens](https://ant.design/components/overview#design-token). See [Ant Design tooltip tokens](https://ant.design/components/tooltip#design-token). |
|
|
@@ -1237,7 +1261,7 @@ Monthly Revenue
|
|
|
1237
1261
|
|
|
1238
1262
|
| Event | Event Data | Description |
|
|
1239
1263
|
| --- | --- | --- |
|
|
1240
|
-
| `onOpenChange` |
|
|
1264
|
+
| `onOpenChange` | \- | Trigger action when visibility of the tooltip card is changed. |
|
|
1241
1265
|
|
|
1242
1266
|
| Key | Target |
|
|
1243
1267
|
| --- | --- |
|
|
@@ -91,24 +91,6 @@ Watermark overlay with text, image, and font customization.
|
|
|
91
91
|
height: 200px
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
```yaml
|
|
95
|
-
- id: per_line_font
|
|
96
|
-
type: Watermark
|
|
97
|
-
properties:
|
|
98
|
-
text:
|
|
99
|
-
- text: CONFIDENTIAL
|
|
100
|
-
font:
|
|
101
|
-
fontSize: 22
|
|
102
|
-
fontWeight: bold
|
|
103
|
-
color: rgba(255, 0, 0, 0.12)
|
|
104
|
-
- Prepared for the finance team
|
|
105
|
-
blocks:
|
|
106
|
-
- id: per_line_font_child
|
|
107
|
-
type: Box
|
|
108
|
-
style:
|
|
109
|
-
height: 200px
|
|
110
|
-
```
|
|
111
|
-
|
|
112
94
|
```yaml
|
|
113
95
|
- id: align_left
|
|
114
96
|
type: Watermark
|
|
@@ -296,7 +278,7 @@ Drag and drop files here or click to browse
|
|
|
296
278
|
- id: css_gradient_bg
|
|
297
279
|
type: Watermark
|
|
298
280
|
class:
|
|
299
|
-
|
|
281
|
+
element: bg-gradient-to-br from-primary/10 to-primary/5 rounded-lg p-4
|
|
300
282
|
properties:
|
|
301
283
|
text: Preview
|
|
302
284
|
font:
|
|
@@ -313,7 +295,7 @@ Drag and drop files here or click to browse
|
|
|
313
295
|
- id: css_dark_surface
|
|
314
296
|
type: Watermark
|
|
315
297
|
class:
|
|
316
|
-
|
|
298
|
+
element: bg-bg-layout rounded-lg p-4
|
|
317
299
|
properties:
|
|
318
300
|
text: Dark Theme
|
|
319
301
|
font:
|
|
@@ -338,7 +320,7 @@ Drag and drop files here or click to browse
|
|
|
338
320
|
- id: css_bordered_area
|
|
339
321
|
type: Watermark
|
|
340
322
|
class:
|
|
341
|
-
|
|
323
|
+
element: border-2 border-dashed border-border rounded-xl p-6
|
|
342
324
|
properties:
|
|
343
325
|
text: Upload Area
|
|
344
326
|
font:
|
|
@@ -513,7 +495,7 @@ Mobile app for real-time inventory tracking across multiple warehouses. Integrat
|
|
|
513
495
|
| `inherit` | boolean | `true` | Inherit watermark config from parent Watermark block. |
|
|
514
496
|
| `offset` | array | - | Offset of the watermark from the top-left as [x, y]. |
|
|
515
497
|
| `rotate` | number | `-22` | Rotation angle of watermark in degrees. |
|
|
516
|
-
| `text` | string \| array | - | Watermark text content.
|
|
498
|
+
| `text` | string \| array | - | Watermark text content. Maps to antd "content" prop. |
|
|
517
499
|
| `theme` | object | - | Antd design token overrides for this block. See [antd design tokens](https://ant.design/components/overview#design-token). See [Ant Design watermark tokens](https://ant.design/components/watermark#design-token). |
|
|
518
500
|
| `theme.colorFill` | string | - | Default watermark text color when font.color is not set. Maps to the global colorFill token. |
|
|
519
501
|
| `theme.fontSizeLG` | number | `16` | Default watermark font size when font.fontSize is not set. Maps to the global fontSizeLG token. |
|
|
@@ -7,11 +7,9 @@
|
|
|
7
7
|
The `:reject` control is used to return a user-friendly error to the client when validation fails or business rules are violated.
|
|
8
8
|
Unlike [`:throw`](/:throw), which indicates a system error, `:reject` represents an expected failure condition that should be communicated to the user.
|
|
9
9
|
The control immediately stops routine execution and returns with a `"reject"` status.
|
|
10
|
-
Importantly, `:reject` does not trigger `:catch` blocks in [`:try`](/:try) statements
|
|
11
|
-
This makes `:reject` ideal for handling validation and business logic errors separately from system errors.
|
|
12
|
-
Choose [`:throw`](/:throw) when a step failed and the routine may recover; choose `:reject` when the routine decided the request cannot be fulfilled.
|
|
10
|
+
Importantly, `:reject` does not trigger `:catch` blocks in [`:try`](/:try) statements, making it ideal for handling validation and business logic errors separately from system errors.
|
|
13
11
|
|
|
14
|
-
`:reject` also takes an Error as its message, such as the error a `:catch` caught: `:reject: { _error: true }`. The reject message is then "Something went wrong.", unless the error was a `UserError` or an
|
|
12
|
+
`:reject` also takes an Error as its message, such as the error a `:catch` caught: `:reject: { _error: true }`. The reject message is then "Something went wrong.", unless the error was a `UserError` or an authentication error, whose message is kept. To reject with the caught error's real message, name it: `:reject: { _error: message }`. See [`_error`](/_error).
|
|
15
13
|
|
|
16
14
|
#### Keys
|
|
17
15
|
|
|
@@ -8,7 +8,6 @@ The `:throw` control creates a system error that immediately stops routine execu
|
|
|
8
8
|
Unlike [`:reject`](/:reject), which handles expected user errors, `:throw` is designed for unexpected system failures, programming errors, or critical issues that require attention.
|
|
9
9
|
The key difference is that `:throw` can be caught and handled by [`:try`](/:try)/`:catch` blocks, while [`:reject`](/:reject) cannot.
|
|
10
10
|
This makes `:throw` ideal for recoverable system errors where you might want to implement fallback logic.
|
|
11
|
-
Choose `:throw` when a step failed and the routine may recover; choose [`:reject`](/:reject) when the routine decided the request cannot be fulfilled.
|
|
12
11
|
|
|
13
12
|
`:throw` also takes an Error as its message, such as the error a `:catch` caught: `:throw: { _error: true }`. The error is rethrown as it is, with its own class and cause, and `:cause` is ignored. The client receives it with the message "Something went wrong.", keeping its `code` and `statusCode`, unless it was a `UserError`, whose message is kept. To show the user the caught error's real message, name it: `:throw: { _error: message }`. See [`_error`](/_error).
|
|
14
13
|
|
package/content/controls/try.md
CHANGED
|
@@ -7,14 +7,13 @@
|
|
|
7
7
|
If one control in the routine chain defined in the `:try` key fails by throwing an error, the steps in the list following the failed control will not be executed.
|
|
8
8
|
To handle any errors thrown by a routine element, a routine can be provided using `catch` key.
|
|
9
9
|
The routine defined using the `:finally` key will be run regardless of whether or not the routine throws an error.
|
|
10
|
-
A [`:reject`](/:reject) inside the `:try` routine is __not__ caught. `:reject` is the routine's own reply — it stops the routine, returns a `"reject"` status to the caller, and flows past every enclosing `:catch`. `:finally` still runs. Use [`:throw`](/:throw) for failures a `:catch` should handle.
|
|
11
10
|
Inside the `:catch` routine, the [`_error`](/_error) operator returns the error that was caught, so the routine can branch on its `statusCode` or `code`, or read its `message`. `_error` returns the error of the innermost `:catch` that encloses it, and `null` outside a `:catch`.
|
|
12
11
|
|
|
13
12
|
#### Keys
|
|
14
13
|
|
|
15
14
|
- `:try: routine`: __Required__ - The routine to be run.
|
|
16
|
-
- `:catch: routine`: The routine to execute if any step in the routine defined errors.
|
|
17
|
-
- `:finally: routine`: The routine to be run regardless of the out come of the initial routine.
|
|
15
|
+
- `:catch: routine`: The routine to execute if any step in the routine defined errors.
|
|
16
|
+
- `:finally: routine`: The routine to be run regardless of the out come of the initial routine.
|
|
18
17
|
|
|
19
18
|
#### Examples
|
|
20
19
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Deployment environments
|
|
2
2
|
|
|
3
|
-
Most apps run as more than one deployment: production, a staging copy, a developer's machine. Everything that differs between them is declared once, under `config.environments`, and each deployment says which environment it is with the `LOWDEFY_ENVIRONMENT` environment variable. Lowdefy then takes every environment-specific default from the **current environment** — the app URL, crons, the email delivery filter, Sentry,
|
|
3
|
+
Most apps run as more than one deployment: production, a staging copy, a developer's machine. Everything that differs between them is declared once, under `config.environments`, and each deployment says which environment it is with the `LOWDEFY_ENVIRONMENT` environment variable. Lowdefy then takes every environment-specific default from the **current environment** — the app URL, crons, the email delivery filter, Sentry, and the feature switches — so none of them needs its own variable or operator chain.
|
|
4
4
|
|
|
5
5
|
```yaml
|
|
6
6
|
# lowdefy.yaml
|
|
@@ -46,18 +46,17 @@ Every setting is optional, and every feature is **on by default**: only an expli
|
|
|
46
46
|
| `email.filter` | none | Delivery filter (`replaceAddress`, `allowlist`, `regex`) for mail requests. |
|
|
47
47
|
| `email.enabled` | `true` | `false`: mail requests send nothing. |
|
|
48
48
|
| `sentry.enabled` | `true` | `false`: Sentry off, server and client. |
|
|
49
|
-
| `posthog.enabled` | `true` | `false`: PostHog off — `PostHogInit` behaves as `enabled: false`. |
|
|
50
49
|
| `guards.secrets`, `guards.env` | none | Regular expressions the named secrets and environment variables must match, or the build fails. |
|
|
51
50
|
|
|
52
51
|
## URL
|
|
53
52
|
|
|
54
53
|
The current environment's `url` is the default for:
|
|
55
54
|
|
|
56
|
-
- the auth
|
|
55
|
+
- the auth base URL (`AUTH_URL`) — sign-in callbacks and auth links;
|
|
57
56
|
- the `serverUrl` of `RenderNotification` steps — the links and logo in notification emails;
|
|
58
57
|
- where crons are forwarded to, when another environment forwards to this one.
|
|
59
58
|
|
|
60
|
-
An explicit `
|
|
59
|
+
An explicit `AUTH_URL` / `NEXTAUTH_URL` or `serverUrl` still wins. The dev server (`lowdefy dev`) never uses the current environment's `url`: auth and notification links use the request origin, the local app, even when your local `.env` names a deployed environment. Production never uses the request origin, since a spoofed `Host` header would then steer the links in outgoing mail.
|
|
61
60
|
|
|
62
61
|
Every deployment that names an environment is taken to be served at its `url`. Preview deployments that should not sign users in on the staging host need their own environment, e.g. a `preview` environment with no `url` and the same `email.filter` and guards as staging.
|
|
63
62
|
|
|
@@ -81,11 +80,10 @@ Endpoint `schedules` can be keyed by environment name, with a `default` for the
|
|
|
81
80
|
|
|
82
81
|
See the [SMTP](/SMTP) and [SendGridMail](/SendGridMail) connections for the filter fields.
|
|
83
82
|
|
|
84
|
-
## Logs
|
|
83
|
+
## Logs and Sentry
|
|
85
84
|
|
|
86
85
|
- Every server log line carries `environment` next to `app_name`, `app_version` and `git_sha`, so one log drain can hold every environment. Logging cannot be switched off.
|
|
87
86
|
- Sentry reports under the environment name unless `logger.sentry.environment` is set, and `sentry.enabled: false` turns it off on the server and in the browser.
|
|
88
|
-
- `PostHogInit` registers the environment name as the `environment` super property, so every PostHog event carries it. `posthog.enabled: false` switches PostHog off in that environment: `PostHogInit` behaves as `enabled: false` whatever its params say, needs no `apiKey`, and every other PostHog action is a no-op.
|
|
89
87
|
|
|
90
88
|
## Guards
|
|
91
89
|
|
|
@@ -100,7 +98,7 @@ config:
|
|
|
100
98
|
secrets: # Lowdefy secrets, by name (LOWDEFY_SECRET_<name>)
|
|
101
99
|
MONGODB_URI: 'acme-prod\.a1b2c\.mongodb\.net'
|
|
102
100
|
env: # any environment variable
|
|
103
|
-
|
|
101
|
+
AUTH_URL: '^https://app\.example\.com$'
|
|
104
102
|
```
|
|
105
103
|
|
|
106
104
|
- Patterns match anywhere in the value, so a distinctive substring is enough; add `^` and `$` to pin the whole value. A pattern is committed with your config, so never put the sensitive part of a secret in it — a host name or database name is enough.
|
|
@@ -113,7 +111,7 @@ config:
|
|
|
113
111
|
Environment settings stay on the server. The browser only learns the current environment's **name** and the list of features it switches off, through the app metadata:
|
|
114
112
|
|
|
115
113
|
- `_app: environment` — the current environment's name.
|
|
116
|
-
- `_app: disabled` — the switched-off features, e.g. `[email,
|
|
114
|
+
- `_app: disabled` — the switched-off features, e.g. `[email, sentry]`.
|
|
117
115
|
|
|
118
116
|
Other environments' settings, URLs, secret names, email filters and guards never reach the client bundle. Only the current environment's guards are kept in the build output, in the server-only `config.json`, for the startup check.
|
|
119
117
|
|
|
@@ -15,7 +15,7 @@ The generated Dockerfile:
|
|
|
15
15
|
```text
|
|
16
16
|
# syntax=docker/dockerfile:1
|
|
17
17
|
|
|
18
|
-
FROM node:
|
|
18
|
+
FROM node:22-slim AS builder
|
|
19
19
|
|
|
20
20
|
WORKDIR /lowdefy
|
|
21
21
|
|
|
@@ -41,7 +41,7 @@ RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
|
|
41
41
|
&& npx lowdefy@"$LOWDEFY_VERSION" build \
|
|
42
42
|
&& npx lowdefy@"$LOWDEFY_VERSION" docker-output
|
|
43
43
|
|
|
44
|
-
FROM node:
|
|
44
|
+
FROM node:22-slim AS runner
|
|
45
45
|
|
|
46
46
|
ENV NODE_ENV=production
|
|
47
47
|
ENV PORT=3000
|
|
@@ -93,7 +93,7 @@ Key properties of this setup:
|
|
|
93
93
|
- **Fast rebuilds**: the pnpm store is kept in a BuildKit cache mount, so changing app config only re-downloads dependencies that actually changed.
|
|
94
94
|
- **Small runtime image**: `docker-output` traces the server's real import graph and copies only what the server loads at runtime — a fraction of the installed `node_modules`, since the client-side block packages are already compiled into `dist/client` and never imported by the server.
|
|
95
95
|
- **Non-root**: the server runs as the `node` user built into the official Node.js images.
|
|
96
|
-
- For stronger supply-chain guarantees, pin the base images by digest (`node:
|
|
96
|
+
- For stronger supply-chain guarantees, pin the base images by digest (`node:22-slim@sha256:...`) and let a bot like Renovate or Dependabot keep the digest updated.
|
|
97
97
|
|
|
98
98
|
### Health checks
|
|
99
99
|
|
|
@@ -124,7 +124,7 @@ The server is configured entirely through environment variables at runtime — t
|
|
|
124
124
|
| `LOWDEFY_SECRET_*` | App secrets, accessed with the [`_secret`](/_secret) operator. |
|
|
125
125
|
| `AUTH_SECRET` | Required when using [Lowdefy Auth](/users-introduction). |
|
|
126
126
|
| `LOWDEFY_ENVIRONMENT` | Read at build time: the environment this image is built for, one of `config.environments`. |
|
|
127
|
-
| `
|
|
127
|
+
| `AUTH_URL` | The deployed app URL, required for OAuth providers. Defaults to the `url` of the current environment in `config.environments`. |
|
|
128
128
|
| `CRON_SECRET` | Bearer token protecting `/api/cron/*` and `/api/detached/*` endpoints. |
|
|
129
129
|
| `LOWDEFY_LOG_LEVEL` | Server log level: `debug`, `info` (default), `warn`, `error`. |
|
|
130
130
|
| `SENTRY_DSN` | Enables Sentry error reporting when set. |
|
|
@@ -148,21 +148,6 @@ RUN --mount=type=secret,id=sentry,env=SENTRY_AUTH_TOKEN \
|
|
|
148
148
|
npx lowdefy@"$LOWDEFY_VERSION" build
|
|
149
149
|
```
|
|
150
150
|
|
|
151
|
-
### Behind a reverse proxy
|
|
152
|
-
|
|
153
|
-
The server takes each request's client address from its connection. Auth rate limits count attempts per client address (for example 3 sign-in attempts per 10 seconds), sessions record it, and the request log writes it as `client_address`. `X-Forwarded-For` is not read by default, because any client can send it.
|
|
154
|
-
|
|
155
|
-
Behind a reverse proxy, load balancer or ingress, every connection comes from the proxy, so every client would share its address and its rate limits. List the proxy addresses, or CIDR ranges, in `config.trustedProxies`:
|
|
156
|
-
|
|
157
|
-
```yaml
|
|
158
|
-
config:
|
|
159
|
-
trustedProxies:
|
|
160
|
-
- 10.0.0.0/8
|
|
161
|
-
- 172.16.0.0/12
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
When a request's connection comes from a trusted proxy, the server reads `X-Forwarded-For` from the right, skips every trusted hop, and takes the first address that is not trusted. Entries further left were written by the client and are ignored. Do not list `0.0.0.0/0` or `::/0`: they trust every address, so any client could choose its own, and the build warns about them. The proxy must append to `X-Forwarded-For` (nginx: `proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;`). The server logs a warning the first time a request carries `X-Forwarded-For` while `trustedProxies` is not set.
|
|
165
|
-
|
|
166
151
|
### Logging
|
|
167
152
|
|
|
168
153
|
The server writes structured JSON logs (one JSON object per line, via [pino](https://getpino.io)) to stdout — the format container platforms and log collectors (CloudWatch, Loki, Datadog, etc.) expect. Nothing is written to files inside the container.
|
|
@@ -203,7 +188,7 @@ The container inherits the Dockerfile `HEALTHCHECK`, so `docker compose ps` repo
|
|
|
203
188
|
docker compose up --build
|
|
204
189
|
```
|
|
205
190
|
|
|
206
|
-
If you set a container memory limit, Node.js
|
|
191
|
+
If you set a container memory limit, Node.js 22+ sizes its heap from the container's cgroup limit automatically. To control it explicitly, set `NODE_OPTIONS=--max-old-space-size=<MiB>` a comfortable margin below the container limit.
|
|
207
192
|
|
|
208
193
|
### Config files or plugins outside the config directory
|
|
209
194
|
|
|
@@ -214,7 +199,7 @@ Sometimes files outside of the config directory need to be accessed by the Lowde
|
|
|
214
199
|
```text
|
|
215
200
|
# syntax=docker/dockerfile:1
|
|
216
201
|
|
|
217
|
-
FROM node:
|
|
202
|
+
FROM node:22-slim AS builder
|
|
218
203
|
|
|
219
204
|
WORKDIR /lowdefy
|
|
220
205
|
|
|
@@ -232,7 +217,7 @@ RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
|
|
232
217
|
&& npx lowdefy@"$LOWDEFY_VERSION" build --config-directory ./app \
|
|
233
218
|
&& npx lowdefy@"$LOWDEFY_VERSION" docker-output --config-directory ./app
|
|
234
219
|
|
|
235
|
-
FROM node:
|
|
220
|
+
FROM node:22-slim AS runner
|
|
236
221
|
|
|
237
222
|
ENV NODE_ENV=production
|
|
238
223
|
ENV PORT=3000
|
|
@@ -22,10 +22,6 @@ from inside the folder, or `pnpm start`. The server listens on `PORT` (default 3
|
|
|
22
22
|
|
|
23
23
|
Always run the build before restarting the server — the server reads the client asset manifest once at startup.
|
|
24
24
|
|
|
25
|
-
With `auth.email` configured, the server needs the app's canonical origin — `BETTER_AUTH_URL`, or the `url` of the current environment in `config.environments` — or it refuses to start, so emailed auth links cannot take their host from a request. To test the production server locally, set `BETTER_AUTH_URL=http://localhost:3000`.
|
|
26
|
-
|
|
27
|
-
Behind a reverse proxy or load balancer, list its addresses in `config.trustedProxies` so auth rate limits count each client, not the proxy. See [Behind a reverse proxy](/docker#behind-a-reverse-proxy).
|
|
28
|
-
|
|
29
25
|
### Alternative
|
|
30
26
|
|
|
31
27
|
An alternative option would be to make use of [Docker](./docker) to deploy the app. Docker has a few advantages, including scalability, application portability, version control and deployment speed, amoung others.
|
|
@@ -27,17 +27,14 @@ In the Vercel project:
|
|
|
27
27
|
- Eg: if `lowdefy.yaml` is at the top level of the repository, set the root directory to `deploy`; if it is in `apps/app_name`, set it to `apps/app_name/deploy`.
|
|
28
28
|
- **Install Command:** `bash vercel.install.sh`. Leave the **Build Command** to `vercel.json` (do not override it in the dashboard). There is no **Output Directory** setting — the build emits `.vercel/output`, which Vercel detects automatically.
|
|
29
29
|
- Enable **"Include files outside the root directory in the Build Step"** — the Lowdefy config usually lives in the parent of `deploy/`.
|
|
30
|
-
- **Node.js Version:** `24.x` or newer. The install and build steps run the Lowdefy CLI, which requires Node.js 24; the function itself runs on the `nodejs24.x` runtime set in the generated Build Output.
|
|
31
30
|
|
|
32
31
|
###### Public files
|
|
33
32
|
|
|
34
|
-
Files in your app's `public/` directory (favicon, icons, images, `manifest.webmanifest`, etc.) are copied into `dist/client` by Vite during the build, placed in `.vercel/output/static`, and served by the Vercel CDN — no extra configuration needed.
|
|
33
|
+
Files in your app's `public/` directory (favicon, icons, images, `manifest.webmanifest`, etc.) are copied into `dist/client` by Vite during the build, placed in `.vercel/output/static`, and served by the Vercel CDN — no extra configuration needed.
|
|
35
34
|
|
|
36
35
|
###### Secrets and environment variables
|
|
37
36
|
|
|
38
|
-
Secrets can be set in the Environment Variables settings section by creating environment variables prefixed with `LOWDEFY_SECRET_`.
|
|
39
|
-
|
|
40
|
-
On Vercel the client address used by auth rate limits, sessions and request logs comes from the platform (`x-real-ip`), which Vercel sets on every request. `config.trustedProxies` is not used.
|
|
37
|
+
Secrets can be set in the Environment Variables settings section by creating environment variables prefixed with `LOWDEFY_SECRET_`. Use `AUTH_SECRET` (and `AUTH_URL` for OAuth, which defaults to the current environment's `url` — see [Deployment environments](#deployment-environments)) for authentication. Different secrets can be set for production and preview deployments.
|
|
41
38
|
|
|
42
39
|
###### Function settings
|
|
43
40
|
|
|
@@ -85,11 +82,11 @@ Each schedule becomes a cron job pointing at `/api/cron/<endpointId>`. When it f
|
|
|
85
82
|
|
|
86
83
|
###### Deployment environments
|
|
87
84
|
|
|
88
|
-
Declare the app's environments once under `config.environments` and name the current one with the `LOWDEFY_ENVIRONMENT` Environment Variable — see [Deployment environments](/deployment-environments) for every setting (URL, crons, email, Sentry,
|
|
85
|
+
Declare the app's environments once under `config.environments` and name the current one with the `LOWDEFY_ENVIRONMENT` Environment Variable — see [Deployment environments](/deployment-environments) for every setting (URL, crons, email, Sentry, feature switches, guards). On Vercel, add `LOWDEFY_ENVIRONMENT` to each Vercel environment (for example `prod` on Production and `staging` on the staging branch's Preview environment). Vercel Environment Variables are available at build time, which is when Lowdefy reads it and checks guards.
|
|
89
86
|
|
|
90
87
|
###### Crons for staging and other environments
|
|
91
88
|
|
|
92
|
-
Vercel fires cron jobs only on the **production** deployment — a staging or preview deployment never runs its schedules on its own. Give an environment a `cron.secret` and the environment Vercel fires crons on registers that environment's schedules too; when one fires, production forwards it to that environment's own `/api/cron/<endpointId>` at its `url`
|
|
89
|
+
Vercel fires cron jobs only on the **production** deployment — a staging or preview deployment never runs its schedules on its own. Give an environment a `cron.secret` and the environment Vercel fires crons on registers that environment's schedules too; when one fires, production forwards it to that environment's own `/api/cron/<endpointId>` at its `url` and answers Vercel immediately (the ping is fire-and-forget, kept alive via the request context and bounded by `maxDuration`; its outcome is logged as `forward_scheduled_endpoint_done` / `_failed`).
|
|
93
90
|
|
|
94
91
|
- **Forwarded environments:** an environment with a `cron.secret` is forwarded to, so it must have a `url`. `cron.secret` is the **name** of the Lowdefy secret holding that environment's own `CRON_SECRET` — a plain string such as `STAGING_CRON_SECRET`, not `{ _secret: ... }`: environment settings are resolved at build time, and the forward route reads the value at runtime from `LOWDEFY_SECRET_<name>`. Set `cron.enabled: false` on an environment to register no crons for it.
|
|
95
92
|
- **Secrets on production:** for each forwarded environment add an Environment Variable `LOWDEFY_SECRET_<secret name>` (for example `LOWDEFY_SECRET_STAGING_CRON_SECRET`) to the production deployment, with that environment's `CRON_SECRET` as value. The forward route `/api/cron-forward/*` itself is secured by production's own `CRON_SECRET` like every cron route, and fails closed when the environment's secret is missing.
|
|
@@ -110,13 +107,9 @@ See [Async Endpoints](/lowdefy-api) and [Detached Endpoint Calls](/lowdefy-api)
|
|
|
110
107
|
|
|
111
108
|
Vercel Fluid bills by execution duration, so a request that hangs (a stuck database, SMTP or external API call) is a real cost risk. Two guardrails apply:
|
|
112
109
|
|
|
113
|
-
- **`config.requestTimeout`** (in `lowdefy.yaml`, default `30000` ms) — the server returns a timeout instead of letting a request run on
|
|
110
|
+
- **`config.requestTimeout`** (in `lowdefy.yaml`, default `30000` ms) — the server returns a timeout instead of letting a request run on. Set to `0` to disable. Agent streaming routes are exempt.
|
|
114
111
|
- **`config.vercel.maxDuration`** (default `60`) — a hard platform cap; Vercel stops the function at this many seconds. See Function settings above.
|
|
115
112
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
On Vercel, only the request timeout cancels an AI model call a request is waiting on. A client that disconnects does not: the call runs until it finishes, reaches its own `timeout`, or hits the request timeout. On the Node server a disconnect cancels it too.
|
|
119
|
-
|
|
120
|
-
> The function runs on Vercel's Node.js runtime. Streaming agent responses (`/api/agent/*`) are exempt from `config.requestTimeout` and are bounded only by `maxDuration` — for heavy streaming or agent workloads, a long-lived Node host (Docker, Fly.io, Railway, Render) may suit better. An agent run keeps running to the end when its client disconnects, so its work completes; a `GET` stream (such as an MCP client's notification stream) stops when its client goes, instead of holding the function until `maxDuration`.
|
|
113
|
+
> The function runs on Vercel's Node.js runtime. Streaming agent responses (`/api/agent/*`) are exempt from `config.requestTimeout` and are bounded only by `maxDuration` — for heavy streaming or agent workloads, a long-lived Node host (Docker, Fly.io, Railway, Render) may suit better.
|
|
121
114
|
|
|
122
115
|
All other Vercel configuration like domain names, preview deploy branches, serverless regions and redirects can be configured as desired.
|