diff --git a/.eslintignore b/.eslintignore
index fe799b02..c323aa6f 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -4,3 +4,4 @@
**/dist
CHANGELOG.md
docs
+packages/*/template/*
diff --git a/packages/cra-template-apps-starter-kit/LICENSE b/packages/cra-template-apps-starter-kit/LICENSE
new file mode 100644
index 00000000..1f9985e0
--- /dev/null
+++ b/packages/cra-template-apps-starter-kit/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2022-Present Datadog, Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/packages/cra-template-apps-starter-kit/README.md b/packages/cra-template-apps-starter-kit/README.md
new file mode 100644
index 00000000..afbf9083
--- /dev/null
+++ b/packages/cra-template-apps-starter-kit/README.md
@@ -0,0 +1,25 @@
+# Datadog UI App React Starter Kit
+
+This is a [`create-react-app`](https://create-react-app.dev/) [custom template](https://create-react-app.dev/docs/custom-templates) that helps you get started building a Datadog UI App.
+
+## Getting Started
+
+### Using npx
+
+```sh
+npx create-react-app starter-kit --template @datadog/apps-starter-kit
+```
+
+### Using npm
+
+```sh
+npm init react-app starter-kit --template @datadog/apps-starter-kit
+```
+
+### Using yarn
+
+```sh
+yarn create react-app starter-kit --template @datadog/apps-starter-kit
+```
+
+**Note**: This template currently uses v17 of React due to the `peerDependency` that `"@datadog/ui-extensions-react"` has on `17.0.2`; once the relevant `@types/` packages for React and ReactDOM are updated and we can move to v18 across the board, we will.
diff --git a/packages/cra-template-apps-starter-kit/package.json b/packages/cra-template-apps-starter-kit/package.json
new file mode 100644
index 00000000..9ca01e58
--- /dev/null
+++ b/packages/cra-template-apps-starter-kit/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "@datadog/cra-template-apps-starter-kit",
+ "version": "1.0.0",
+ "keywords": [
+ "react",
+ "create-react-app",
+ "template",
+ "datadog"
+ ],
+ "description": "Datadog UI Apps Starter Kit",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/DataDog/apps.git",
+ "directory": "packages/cra-template-apps-starter-kit"
+ },
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=16"
+ },
+ "bugs": {
+ "url": "https://github.com/DataDog/apps/issues"
+ },
+ "main": "template.json",
+ "files": [
+ "template",
+ "template.json"
+ ],
+ "publishConfig": {
+ "access": "public"
+ },
+ "scripts": {
+ "prepare": "exit 0"
+ }
+}
diff --git a/packages/cra-template-apps-starter-kit/template.json b/packages/cra-template-apps-starter-kit/template.json
new file mode 100644
index 00000000..007328df
--- /dev/null
+++ b/packages/cra-template-apps-starter-kit/template.json
@@ -0,0 +1,27 @@
+{
+ "package": {
+ "dependencies": {
+ "@datadog/ui-extensions-react": "0.30.1",
+ "@datadog/ui-extensions-sdk": "0.30.1",
+ "milligram": "^1.4.1",
+ "react": "^17.0.2",
+ "react-dom": "^17.0.2",
+ "typeface-roboto": "^1.1.13"
+ },
+ "eslintConfig": {
+ "extends": ["react-app", "react-app/jest"]
+ },
+ "browserslist": {
+ "production": [
+ ">0.2%",
+ "not dead",
+ "not op_mini all"
+ ],
+ "development": [
+ "last 1 chrome version",
+ "last 1 firefox version",
+ "last 1 safari version"
+ ]
+ }
+ }
+}
diff --git a/packages/cra-template-apps-starter-kit/template/.prettierignore b/packages/cra-template-apps-starter-kit/template/.prettierignore
new file mode 100644
index 00000000..0c50478f
--- /dev/null
+++ b/packages/cra-template-apps-starter-kit/template/.prettierignore
@@ -0,0 +1,3 @@
+build
+CHANGELOG.md
+dist
diff --git a/packages/cra-template-apps-starter-kit/template/LICENSE b/packages/cra-template-apps-starter-kit/template/LICENSE
new file mode 100644
index 00000000..1f9985e0
--- /dev/null
+++ b/packages/cra-template-apps-starter-kit/template/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2022-Present Datadog, Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/packages/cra-template-apps-starter-kit/template/app_manifest.json b/packages/cra-template-apps-starter-kit/template/app_manifest.json
new file mode 100644
index 00000000..22854671
--- /dev/null
+++ b/packages/cra-template-apps-starter-kit/template/app_manifest.json
@@ -0,0 +1,98 @@
+{
+ "schemaVersion": "v2",
+ "display_on_public_website": false,
+ "app_id": null,
+ "support_type": "partner",
+ "tile": {
+ "description": "A hello-world like application used as a starting point for apps",
+ "logo_media": {
+ "light": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/48/Emojione_1F44B.svg/1024px-Emojione_1F44B.svg.png"
+ },
+ "title": "Your first app!"
+ },
+ "author": {},
+ "pricing": [],
+ "legal_terms": {},
+ "proxy_scopes": [],
+ "assets": {
+ "ui_extensions": {
+ "debug_mode_url": "http://localhost:3000",
+ "secured": false,
+ "main_url": "http://localhost:3000",
+ "api_version": "v1.0",
+ "features": [
+ {
+ "name": "dashboard_custom_widget",
+ "options": {
+ "widgets": [
+ {
+ "name": "Your first app",
+ "has_title": true,
+ "custom_widget_key": "your_first_app",
+ "source": "widget",
+ "options": [
+ {
+ "enum": [
+ "system.cpu.idle",
+ "system.load.1",
+ "system.load.5",
+ "system.load.15"
+ ],
+ "type": "string",
+ "name": "metric",
+ "label": "Your favorite metric"
+ },
+ {
+ "enum": [
+ "Chevre",
+ "Gruyere",
+ "Mozzarella"
+ ],
+ "type": "string",
+ "name": "favorite-cheese",
+ "label": "Your favorite cheese"
+ }
+ ],
+ "icon": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/48/Emojione_1F44B.svg/1024px-Emojione_1F44B.svg.png"
+ }
+ ]
+ }
+ },
+ {
+ "name": "dashboard_cog_menu",
+ "options": {
+ "items": [
+ {
+ "action_type": "event",
+ "key": "open-confirmation",
+ "label": "Please confirm"
+ },
+ {
+ "action_type": "event",
+ "key": "open-custom-modal",
+ "label": "Open a custom modal"
+ },
+ {
+ "action_type": "event",
+ "key": "open-custom-panel",
+ "label": "Open a custom side panel with args"
+ }
+ ]
+ }
+ },
+ {
+ "name": "modals",
+ "options": {}
+ },
+ {
+ "name": "side_panels",
+ "options": {}
+ },
+ {
+ "name": "widget_context_menu",
+ "options": { "items": [] }
+ }
+ ]
+ }
+ }
+}
diff --git a/packages/cra-template-apps-starter-kit/template/gitignore b/packages/cra-template-apps-starter-kit/template/gitignore
new file mode 100644
index 00000000..b8fba009
--- /dev/null
+++ b/packages/cra-template-apps-starter-kit/template/gitignore
@@ -0,0 +1,24 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+.eslintcache
+
+# testing
+/coverage
+
+# production
+/build
+
+# misc
+.DS_Store
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
diff --git a/packages/cra-template-apps-starter-kit/template/public/_redirects b/packages/cra-template-apps-starter-kit/template/public/_redirects
new file mode 100644
index 00000000..2ccd43ba
--- /dev/null
+++ b/packages/cra-template-apps-starter-kit/template/public/_redirects
@@ -0,0 +1,3 @@
+/widget /index.html 200
+/modal /index.html 200
+/panel /index.html 200
\ No newline at end of file
diff --git a/packages/cra-template-apps-starter-kit/template/public/favicon.ico b/packages/cra-template-apps-starter-kit/template/public/favicon.ico
new file mode 100644
index 00000000..a11777cc
Binary files /dev/null and b/packages/cra-template-apps-starter-kit/template/public/favicon.ico differ
diff --git a/packages/cra-template-apps-starter-kit/template/public/index.html b/packages/cra-template-apps-starter-kit/template/public/index.html
new file mode 100644
index 00000000..0d815837
--- /dev/null
+++ b/packages/cra-template-apps-starter-kit/template/public/index.html
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+ Datadog UI App
+
+
+
+
+
+
diff --git a/packages/cra-template-apps-starter-kit/template/public/robots.txt b/packages/cra-template-apps-starter-kit/template/public/robots.txt
new file mode 100644
index 00000000..e9e57dc4
--- /dev/null
+++ b/packages/cra-template-apps-starter-kit/template/public/robots.txt
@@ -0,0 +1,3 @@
+# https://www.robotstxt.org/robotstxt.html
+User-agent: *
+Disallow:
diff --git a/packages/cra-template-apps-starter-kit/template/src/controller/dashboard-cog-menu.js b/packages/cra-template-apps-starter-kit/template/src/controller/dashboard-cog-menu.js
new file mode 100644
index 00000000..fd920dd4
--- /dev/null
+++ b/packages/cra-template-apps-starter-kit/template/src/controller/dashboard-cog-menu.js
@@ -0,0 +1,107 @@
+export const setupDashboardCogMenu = client => {
+ // provide cog menu items dynamically if needed
+ client.dashboard.cogMenu.onRequest(() => {
+ return {
+ items: [
+ {
+ actionType: 'link',
+ href: 'https://google.com',
+ label: 'link to google',
+ key: 'link',
+ order: -1
+ }
+ ]
+ };
+ });
+
+ client.events.on('widget_settings_menu_click', context => {
+ if (context.menuItem.key === 'open-confirmation') {
+ client.modal.open({
+ actionLabel: 'Yes',
+ cancelLabel: 'Nevermind',
+ title: 'Please verify!',
+ key: 'confirmation-modal',
+ actionLevel: 'danger',
+ message: 'Are you sure really sure?'
+ });
+ }
+
+ // open an iframe modal defined inline here in controller
+ if (context.menuItem.key === 'open-custom-modal') {
+ client.modal.open(
+ {
+ key: 'custom-modal',
+ size: 'lg',
+ source: 'modal'
+ },
+ {
+ message:
+ 'Hi! I was sent here from the custom widget settings menu 👋',
+ options: context.widget.definition.options
+ }
+ );
+ }
+
+ // open an iframe side panel defined inline here in controller
+ if (context.menuItem.key === 'open-custom-panel') {
+ console.log('xxxx context', context);
+ client.sidePanel.open(
+ {
+ key: 'custom-panel-from-controller',
+ source: 'panel',
+ title: 'Custom Sidepanel'
+ },
+ {
+ message:
+ 'Hi! I was sent here from the custom widget settings menu 👋',
+ options: context.widget.definition.options
+ }
+ );
+ }
+ });
+
+ // listen for cog menu click events
+ client.events.on('dashboard_cog_menu_click', context => {
+ if (context.menuItem.key === 'open-confirmation') {
+ client.modal.open({
+ actionLabel: 'Yes',
+ cancelLabel: 'Nevermind',
+ title: 'Please verify!',
+ key: 'confirmation-modal',
+ actionLevel: 'danger',
+ message: 'Are you sure really sure?'
+ });
+ }
+
+ // open an iframe modal defined inline here in controller
+ if (context.menuItem.key === 'open-custom-modal') {
+ client.modal.open(
+ {
+ key: 'custom-modal',
+ size: 'lg',
+ source: 'modal'
+ },
+ {
+ message:
+ 'Hi! I was sent here from the dashboard cog menu 👋'
+ }
+ );
+ }
+
+ // open an iframe side panel defined inline here in controller
+ if (context.menuItem.key === 'open-custom-panel') {
+ console.log('xxxx context', context);
+ client.sidePanel.open(
+ {
+ key: 'custom-panel-from-controller',
+ source: 'panel',
+ title: 'Custom Sidepanel'
+ },
+ {
+ message:
+ 'Hi! I was sent here from the dashboard cog menu 👋'
+ }
+ );
+ }
+ });
+};
diff --git a/packages/cra-template-apps-starter-kit/template/src/controller/index.js b/packages/cra-template-apps-starter-kit/template/src/controller/index.js
new file mode 100644
index 00000000..2003aa45
--- /dev/null
+++ b/packages/cra-template-apps-starter-kit/template/src/controller/index.js
@@ -0,0 +1,26 @@
+import { init } from '@datadog/ui-extensions-sdk';
+
+import { setupDashboardCogMenu } from './dashboard-cog-menu';
+import { setupModal } from './modal';
+import { setupWidgetCtxMenu } from './widget-ctx-menu';
+
+export default function setup() {
+ const client = init();
+
+ setupModal(client);
+ setupWidgetCtxMenu(client);
+ setupDashboardCogMenu(client);
+
+ const root = document.getElementById('root');
+
+ if (!root) {
+ return;
+ }
+
+ root.innerHTML = `
+
+
The application controller is running in the background.
+ You can open a side panel programatically and pass to it your
+ favorite metric by clicking{' '}
+ {' '}
+
+
+ The red button in the modal has been clicked:{' '}
+ {broadcastClickCount} time(s)
+
+
+ );
+}
+
+export default function render() {
+ ReactDOM.render(
+ {},
+ document.getElementById('root')
+ );
+}
diff --git a/packages/cra-template-apps-typescript-starter-kit/LICENSE b/packages/cra-template-apps-typescript-starter-kit/LICENSE
new file mode 100644
index 00000000..1f9985e0
--- /dev/null
+++ b/packages/cra-template-apps-typescript-starter-kit/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2022-Present Datadog, Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/packages/cra-template-apps-typescript-starter-kit/README.md b/packages/cra-template-apps-typescript-starter-kit/README.md
new file mode 100644
index 00000000..91a056c3
--- /dev/null
+++ b/packages/cra-template-apps-typescript-starter-kit/README.md
@@ -0,0 +1,25 @@
+# Datadog UI App React TypeScript Starter Kit
+
+This is a [`create-react-app`](https://create-react-app.dev/) [custom template](https://create-react-app.dev/docs/custom-templates) that helps you get started building a Datadog UI App.
+
+## Getting Started
+
+### Using npx
+
+```sh
+npx create-react-app starter-kit --template @datadog/apps-typescript-starter-kit
+```
+
+### Using npm
+
+```sh
+npm init react-app starter-kit --template @datadog/apps-typescript-starter-kit
+```
+
+### Using yarn
+
+```sh
+yarn create react-app starter-kit --template @datadog/apps-typescript-starter-kit
+```
+
+**Note**: This template currently uses v17 of React due to the `peerDependency` that `"@datadog/ui-extensions-react"` has on `17.0.2`; once the relevant `@types/` packages for React and ReactDOM are updated and we can move to v18 across the board, we will.
diff --git a/packages/cra-template-apps-typescript-starter-kit/package.json b/packages/cra-template-apps-typescript-starter-kit/package.json
new file mode 100644
index 00000000..4db0db30
--- /dev/null
+++ b/packages/cra-template-apps-typescript-starter-kit/package.json
@@ -0,0 +1,35 @@
+{
+ "name": "@datadog/cra-template-apps-typescript-starter-kit",
+ "version": "1.0.0",
+ "keywords": [
+ "react",
+ "create-react-app",
+ "template",
+ "typescript",
+ "datadog"
+ ],
+ "description": "Datadog UI Apps Starter Kit",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/DataDog/apps.git",
+ "directory": "packages/cra-template-apps-typescript-starter-kit"
+ },
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=16"
+ },
+ "bugs": {
+ "url": "https://github.com/DataDog/apps/issues"
+ },
+ "main": "template.json",
+ "files": [
+ "template",
+ "template.json"
+ ],
+ "publishConfig": {
+ "access": "public"
+ },
+ "scripts": {
+ "prepare": "exit 0"
+ }
+}
diff --git a/packages/cra-template-apps-typescript-starter-kit/template.json b/packages/cra-template-apps-typescript-starter-kit/template.json
new file mode 100644
index 00000000..a66375e2
--- /dev/null
+++ b/packages/cra-template-apps-typescript-starter-kit/template.json
@@ -0,0 +1,33 @@
+{
+ "package": {
+ "dependencies": {
+ "@datadog/ui-extensions-react": "0.30.1",
+ "@datadog/ui-extensions-sdk": "0.30.1",
+ "milligram": "^1.4.1",
+ "react": "^17.0.2",
+ "react-dom": "^17.0.2",
+ "typeface-roboto": "^1.1.13"
+ },
+ "devDependencies": {
+ "@types/node": "^16.7.13",
+ "@types/react": "^17.0.43",
+ "@types/react-dom": "^17.0.14",
+ "typescript": "^4.4.2"
+ },
+ "eslintConfig": {
+ "extends": ["react-app", "react-app/jest"]
+ },
+ "browserslist": {
+ "production": [
+ ">0.2%",
+ "not dead",
+ "not op_mini all"
+ ],
+ "development": [
+ "last 1 chrome version",
+ "last 1 firefox version",
+ "last 1 safari version"
+ ]
+ }
+ }
+}
diff --git a/packages/cra-template-apps-typescript-starter-kit/template/.prettierignore b/packages/cra-template-apps-typescript-starter-kit/template/.prettierignore
new file mode 100644
index 00000000..0c50478f
--- /dev/null
+++ b/packages/cra-template-apps-typescript-starter-kit/template/.prettierignore
@@ -0,0 +1,3 @@
+build
+CHANGELOG.md
+dist
diff --git a/packages/cra-template-apps-typescript-starter-kit/template/LICENSE b/packages/cra-template-apps-typescript-starter-kit/template/LICENSE
new file mode 100644
index 00000000..1f9985e0
--- /dev/null
+++ b/packages/cra-template-apps-typescript-starter-kit/template/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2022-Present Datadog, Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/packages/cra-template-apps-typescript-starter-kit/template/app_manifest.json b/packages/cra-template-apps-typescript-starter-kit/template/app_manifest.json
new file mode 100644
index 00000000..22854671
--- /dev/null
+++ b/packages/cra-template-apps-typescript-starter-kit/template/app_manifest.json
@@ -0,0 +1,98 @@
+{
+ "schemaVersion": "v2",
+ "display_on_public_website": false,
+ "app_id": null,
+ "support_type": "partner",
+ "tile": {
+ "description": "A hello-world like application used as a starting point for apps",
+ "logo_media": {
+ "light": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/48/Emojione_1F44B.svg/1024px-Emojione_1F44B.svg.png"
+ },
+ "title": "Your first app!"
+ },
+ "author": {},
+ "pricing": [],
+ "legal_terms": {},
+ "proxy_scopes": [],
+ "assets": {
+ "ui_extensions": {
+ "debug_mode_url": "http://localhost:3000",
+ "secured": false,
+ "main_url": "http://localhost:3000",
+ "api_version": "v1.0",
+ "features": [
+ {
+ "name": "dashboard_custom_widget",
+ "options": {
+ "widgets": [
+ {
+ "name": "Your first app",
+ "has_title": true,
+ "custom_widget_key": "your_first_app",
+ "source": "widget",
+ "options": [
+ {
+ "enum": [
+ "system.cpu.idle",
+ "system.load.1",
+ "system.load.5",
+ "system.load.15"
+ ],
+ "type": "string",
+ "name": "metric",
+ "label": "Your favorite metric"
+ },
+ {
+ "enum": [
+ "Chevre",
+ "Gruyere",
+ "Mozzarella"
+ ],
+ "type": "string",
+ "name": "favorite-cheese",
+ "label": "Your favorite cheese"
+ }
+ ],
+ "icon": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/48/Emojione_1F44B.svg/1024px-Emojione_1F44B.svg.png"
+ }
+ ]
+ }
+ },
+ {
+ "name": "dashboard_cog_menu",
+ "options": {
+ "items": [
+ {
+ "action_type": "event",
+ "key": "open-confirmation",
+ "label": "Please confirm"
+ },
+ {
+ "action_type": "event",
+ "key": "open-custom-modal",
+ "label": "Open a custom modal"
+ },
+ {
+ "action_type": "event",
+ "key": "open-custom-panel",
+ "label": "Open a custom side panel with args"
+ }
+ ]
+ }
+ },
+ {
+ "name": "modals",
+ "options": {}
+ },
+ {
+ "name": "side_panels",
+ "options": {}
+ },
+ {
+ "name": "widget_context_menu",
+ "options": { "items": [] }
+ }
+ ]
+ }
+ }
+}
diff --git a/packages/cra-template-apps-typescript-starter-kit/template/gitignore b/packages/cra-template-apps-typescript-starter-kit/template/gitignore
new file mode 100644
index 00000000..b8fba009
--- /dev/null
+++ b/packages/cra-template-apps-typescript-starter-kit/template/gitignore
@@ -0,0 +1,24 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+.eslintcache
+
+# testing
+/coverage
+
+# production
+/build
+
+# misc
+.DS_Store
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
diff --git a/packages/cra-template-apps-typescript-starter-kit/template/public/_redirects b/packages/cra-template-apps-typescript-starter-kit/template/public/_redirects
new file mode 100644
index 00000000..2ccd43ba
--- /dev/null
+++ b/packages/cra-template-apps-typescript-starter-kit/template/public/_redirects
@@ -0,0 +1,3 @@
+/widget /index.html 200
+/modal /index.html 200
+/panel /index.html 200
\ No newline at end of file
diff --git a/packages/cra-template-apps-typescript-starter-kit/template/public/favicon.ico b/packages/cra-template-apps-typescript-starter-kit/template/public/favicon.ico
new file mode 100644
index 00000000..a11777cc
Binary files /dev/null and b/packages/cra-template-apps-typescript-starter-kit/template/public/favicon.ico differ
diff --git a/packages/cra-template-apps-typescript-starter-kit/template/public/index.html b/packages/cra-template-apps-typescript-starter-kit/template/public/index.html
new file mode 100644
index 00000000..0d815837
--- /dev/null
+++ b/packages/cra-template-apps-typescript-starter-kit/template/public/index.html
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+ Datadog UI App
+
+
+
+
+
+
diff --git a/packages/cra-template-apps-typescript-starter-kit/template/public/robots.txt b/packages/cra-template-apps-typescript-starter-kit/template/public/robots.txt
new file mode 100644
index 00000000..e9e57dc4
--- /dev/null
+++ b/packages/cra-template-apps-typescript-starter-kit/template/public/robots.txt
@@ -0,0 +1,3 @@
+# https://www.robotstxt.org/robotstxt.html
+User-agent: *
+Disallow:
diff --git a/packages/cra-template-apps-typescript-starter-kit/template/src/controller/dashboard-cog-menu.ts b/packages/cra-template-apps-typescript-starter-kit/template/src/controller/dashboard-cog-menu.ts
new file mode 100644
index 00000000..40456a60
--- /dev/null
+++ b/packages/cra-template-apps-typescript-starter-kit/template/src/controller/dashboard-cog-menu.ts
@@ -0,0 +1,115 @@
+import {
+ DDClient,
+ EventType,
+ ModalSize,
+ ModalActionLevel,
+ MenuItemType
+} from '@datadog/ui-extensions-sdk';
+
+export const setupDashboardCogMenu = (client: DDClient) => {
+ // provide cog menu items dynamically if needed
+ client.dashboard.cogMenu.onRequest(() => {
+ return {
+ items: [
+ {
+ actionType: MenuItemType.LINK,
+ href: 'https://google.com',
+ label: 'link to google',
+ key: 'link',
+ order: -1
+ }
+ ]
+ };
+ });
+
+ client.events.on(EventType.WIDGET_SETTINGS_MENU_CLICK, context => {
+ if (context.menuItem.key === 'open-confirmation') {
+ client.modal.open({
+ actionLabel: 'Yes',
+ cancelLabel: 'Nevermind',
+ title: 'Please verify!',
+ key: 'confirmation-modal',
+ actionLevel: ModalActionLevel.DANGER,
+ message: 'Are you sure really sure?'
+ });
+ }
+
+ // open an iframe modal defined inline here in controller
+ if (context.menuItem.key === 'open-custom-modal') {
+ client.modal.open(
+ {
+ key: 'custom-modal',
+ size: ModalSize.LARGE,
+ source: 'modal'
+ },
+ {
+ message:
+ 'Hi! I was sent here from the custom widget settings menu 👋',
+ options: context.widget.definition.options
+ }
+ );
+ }
+
+ // open an iframe side panel defined inline here in controller
+ if (context.menuItem.key === 'open-custom-panel') {
+ console.log('xxxx context', context);
+ client.sidePanel.open(
+ {
+ key: 'custom-panel-from-controller',
+ source: 'panel',
+ title: 'Custom Sidepanel'
+ },
+ {
+ message:
+ 'Hi! I was sent here from the custom widget settings menu 👋',
+ options: context.widget.definition.options
+ }
+ );
+ }
+ });
+
+ // listen for cog menu click events
+ client.events.on(EventType.DASHBOARD_COG_MENU_CLICK, context => {
+ if (context.menuItem.key === 'open-confirmation') {
+ client.modal.open({
+ actionLabel: 'Yes',
+ cancelLabel: 'Nevermind',
+ title: 'Please verify!',
+ key: 'confirmation-modal',
+ actionLevel: ModalActionLevel.DANGER,
+ message: 'Are you sure really sure?'
+ });
+ }
+
+ // open an iframe modal defined inline here in controller
+ if (context.menuItem.key === 'open-custom-modal') {
+ client.modal.open(
+ {
+ key: 'custom-modal',
+ size: ModalSize.LARGE,
+ source: 'modal'
+ },
+ {
+ message:
+ 'Hi! I was sent here from the dashboard cog menu 👋'
+ }
+ );
+ }
+
+ // open an iframe side panel defined inline here in controller
+ if (context.menuItem.key === 'open-custom-panel') {
+ console.log('xxxx context', context);
+ client.sidePanel.open(
+ {
+ key: 'custom-panel-from-controller',
+ source: 'panel',
+ title: 'Custom Sidepanel'
+ },
+ {
+ message:
+ 'Hi! I was sent here from the dashboard cog menu 👋'
+ }
+ );
+ }
+ });
+};
diff --git a/packages/cra-template-apps-typescript-starter-kit/template/src/controller/index.ts b/packages/cra-template-apps-typescript-starter-kit/template/src/controller/index.ts
new file mode 100644
index 00000000..c06d15e9
--- /dev/null
+++ b/packages/cra-template-apps-typescript-starter-kit/template/src/controller/index.ts
@@ -0,0 +1,23 @@
+import { init } from '@datadog/ui-extensions-sdk';
+
+import { setupDashboardCogMenu } from './dashboard-cog-menu';
+import { setupModal } from './modal';
+import { setupWidgetCtxMenu } from './widget-ctx-menu';
+
+export default function setup() {
+ const client = init();
+ setupModal(client);
+ setupWidgetCtxMenu(client);
+ setupDashboardCogMenu(client);
+
+ const root = document.getElementById('root');
+ if (!root) {
+ return;
+ }
+ root.innerHTML = `
+
+ The application controller is running in the background.
+
+ Click here to open your widget
+ `;
+}
diff --git a/packages/cra-template-apps-typescript-starter-kit/template/src/controller/modal.ts b/packages/cra-template-apps-typescript-starter-kit/template/src/controller/modal.ts
new file mode 100644
index 00000000..9eaeb423
--- /dev/null
+++ b/packages/cra-template-apps-typescript-starter-kit/template/src/controller/modal.ts
@@ -0,0 +1,21 @@
+import { DDClient, EventType } from '@datadog/ui-extensions-sdk';
+
+export const setupModal = (client: DDClient) => {
+ // listen for modal events
+ client.events.on(EventType.MODAL_ACTION, () => {
+ console.log('Confirmed!');
+ });
+
+ client.events.on(EventType.MODAL_CANCEL, () => {
+ console.log('Denied!');
+ });
+
+ client.events.on(EventType.MODAL_CLOSE, definition => {
+ console.log(`User exited modal ${definition.key}`);
+ });
+
+ // listen for a custom event sent from modal IFrame
+ client.events.onCustom('modal_button_click', (count: number) => {
+ console.log(`The user has clicked the button ${count} times`);
+ });
+};
diff --git a/packages/cra-template-apps-typescript-starter-kit/template/src/controller/widget-ctx-menu.ts b/packages/cra-template-apps-typescript-starter-kit/template/src/controller/widget-ctx-menu.ts
new file mode 100644
index 00000000..9d8465a2
--- /dev/null
+++ b/packages/cra-template-apps-typescript-starter-kit/template/src/controller/widget-ctx-menu.ts
@@ -0,0 +1,42 @@
+import { MenuItemType, EventType, DDClient } from '@datadog/ui-extensions-sdk';
+
+export const setupWidgetCtxMenu = (client: DDClient) => {
+ // provide widget context menu items dynamically
+ client.widgetContextMenu.onRequest(({ widget }) => {
+ return {
+ items: [
+ {
+ href: `https://docs.datadoghq.com/dashboards/widgets/${widget.definition.type}/`,
+ actionType: MenuItemType.LINK,
+ key: 'link-item',
+ label: `Read about ${widget.definition.type} widgets`,
+ order: 3
+ },
+ {
+ actionType: MenuItemType.EVENT,
+ // this key is used below to determine which action to take upon click
+ key: 'sidepanel-trigger',
+ label: `Open a sidepanel`,
+ order: 1
+ }
+ ]
+ };
+ });
+
+ // listen for ctx menu click events
+
+ client.events.on(EventType.WIDGET_CONTEXT_MENU_CLICK, context => {
+ if (context.menuItem.key === 'sidepanel-trigger') {
+ client.sidePanel.open(
+ {
+ key: 'custom-panel-from-controller',
+ source: 'panel'
+ },
+ {
+ message:
+ 'Hi! I was sent here from the widget context menu 👋'
+ }
+ );
+ }
+ });
+};
diff --git a/packages/cra-template-apps-typescript-starter-kit/template/src/index.tsx b/packages/cra-template-apps-typescript-starter-kit/template/src/index.tsx
new file mode 100644
index 00000000..0e9508c0
--- /dev/null
+++ b/packages/cra-template-apps-typescript-starter-kit/template/src/index.tsx
@@ -0,0 +1,23 @@
+const init = async () => {
+ switch (window.location.pathname) {
+ case '/widget': {
+ const widget = await import('./widget');
+ return widget.default();
+ }
+ case '/panel': {
+ const sidepanel = await import('./side-panel');
+ return sidepanel.default();
+ }
+ case '/modal': {
+ const modal = await import('./modal');
+ return modal.default();
+ }
+ default: {
+ const controller = await import('./controller');
+ return controller.default();
+ }
+ }
+};
+
+init();
+export {};
diff --git a/packages/cra-template-apps-typescript-starter-kit/template/src/modal/index.tsx b/packages/cra-template-apps-typescript-starter-kit/template/src/modal/index.tsx
new file mode 100644
index 00000000..0430298b
--- /dev/null
+++ b/packages/cra-template-apps-typescript-starter-kit/template/src/modal/index.tsx
@@ -0,0 +1,57 @@
+import { useContext } from '@datadog/ui-extensions-react';
+import { init } from '@datadog/ui-extensions-sdk';
+import ReactDOM from 'react-dom';
+import React, { useState } from 'react';
+
+const client = init();
+
+function Modal() {
+ const [clickCount, setClickCount] = useState(0);
+ const context = useContext(client);
+ const args = context?.args;
+
+ const onClick = () => {
+ setClickCount(clickCount + 1);
+
+ client.events.broadcast('modal_button_click', clickCount + 1);
+ };
+
+ return (
+
+
+ This modal was opened programatically from the main app
+ controller with these args
+