diff --git a/assets/scss/_styles_project.scss b/assets/scss/_styles_project.scss index 15c9d9d4db..58371dbf9e 100644 --- a/assets/scss/_styles_project.scss +++ b/assets/scss/_styles_project.scss @@ -3364,6 +3364,10 @@ div.tablestep > table td, div.tablestep table td { margin-left: 1.0rem; } +.td-content > ol li { + margin-bottom: 0.5rem; +} + .td-content > ul { padding-left: 1rem; } diff --git a/assets/tutorials/air-quality-fleet/get-readings.png b/assets/tutorials/air-quality-fleet/get-readings.png index e637ab5270..709710c93f 100644 Binary files a/assets/tutorials/air-quality-fleet/get-readings.png and b/assets/tutorials/air-quality-fleet/get-readings.png differ diff --git a/docs/dev/reference/changelog.md b/docs/dev/reference/changelog.md index 902132cc52..9813b20146 100644 --- a/docs/dev/reference/changelog.md +++ b/docs/dev/reference/changelog.md @@ -42,6 +42,13 @@ date: "2024-09-18" # updated: "" # When the content was last entirely checked --- +{{% changelog color="added" title="Build custom Viam applications" date="2025-07-17" %}} + +You can now create and use Viam applications to build custom applications that interact with your Viam-powered machines through the Viam SDKs. +For more information, see [Viam applications](/operate/control/viam-applications/). + +{{% /changelog %}} + {{% changelog color="added" title="Start modules with a TCP connection" date="2025-07-14" %}} You can now configure to start modules with a TCP connection. See [Module Configuration](/operate/get-started/other-hardware/module-configuration/) for more information. diff --git a/docs/operate/control/viam-applications.md b/docs/operate/control/viam-applications.md new file mode 100644 index 0000000000..02e0d52482 --- /dev/null +++ b/docs/operate/control/viam-applications.md @@ -0,0 +1,245 @@ +--- +title: "Create a Viam application" +linkTitle: "Create a Viam application" +weight: 5 +layout: "docs" +type: "docs" +description: "Create and deploy a custom web interface for your machines without managing hosting and authentication." +--- + +Create and deploy a custom web interface for your machines without managing hosting and authentication. +Once deployed, your application is accessible from a dedicated URL (`appname_publicnamespace.viamapplications.com`), and hosting and authentication is handled for you. + +Users log into your application and select a machine they have access to. +The application then renders your custom interface for interacting with the user's machine. + +{{}} + +## Requirements + +{{< expand "Install the Viam CLI and authenticate." >}} +Install the Viam CLI using the option below that matches your system architecture: + +{{< readfile "/static/include/how-to/install-cli.md" >}} + +Then authenticate your CLI session with Viam using one of the following options: + +{{< readfile "/static/include/how-to/auth-cli.md" >}} + +{{< /expand >}} + +## Build a custom web interface + +You can build a custom web interface to access your machines using your preferred framework like React, Vue, Angular, or others. + +### Access machines from your application + +When logging into a Viam application and selecting a machine to use it with, the machine's API key is stored as a cookie. +You can access the data from your browser's cookies as follows: + +```ts {class="line-numbers linkable-line-numbers" data-line=""} +import Cookies from "js-cookie"; + +let apiKeyId = ""; +let apiKeySecret = ""; +let host = ""; +let machineId = ""; + +// Extract the machine identifier from the URL +const machineCookieKey = window.location.pathname.split("/")[2]; +({ + apiKey: { id: apiKeyId, key: apiKeySecret }, + machineId: machineId, + hostname: host, +} = JSON.parse(Cookies.get(machineCookieKey)!)); +``` + +### Local development + +For developing your application on localhost: + +1. Run your web server. +1. Run the following command specifying the address where your app is running on localhost and a machine to test on. + The command will proxy your local app and open a browser window and navigate to `http://localhost:8000/machine/` for the machine provided with --machine-id. + + {{< tabs >}} + {{% tab name="Template" %}} + +```sh {class="command-line" data-prompt="$" data-output="2-10"} +viam login +viam module local-app-testing --app-url http://localhost: --machine-id +``` + +{{% /tab %}} +{{% tab name="Example" %}} + +```sh {class="command-line" data-prompt="$" data-output="2-10"} +viam login +viam module local-app-testing --app-url http://localhost:3000 --machine-id a1b2c3d4-e5f6-7890-abcd-ef1234567890 +``` + +{{% /tab %}} +{{< /tabs >}} + +### Configure routing + +When using your deployed application, static files will be accessible at `https://your-app-name_your-public-namespace.viamapplications.com/machine//`. +If your HTML file loads other files, use relative paths to ensure your files are accessible. + +## Deploy your web interface as a Viam application + +To deploy your application with Viam you must package it as a module and upload it using the Viam CLI. + +{{< table >}} +{{% tablestep number=1 %}} + +**Create a meta.json** file for your module using this template: + +{{< tabs >}} +{{% tab name="Template" %}} + +```json +{ + "module_id": "your-namespace:your-module", + "visibility": "public", + "url": "https://github.com/your-org/your-repo", + "description": "Your module description", + "applications": [ + { + "name": "your-app-name", + "type": "single_machine", + "entrypoint": "dist/index.html" + } + ] +} +``` + +{{% /tab %}} +{{% tab name="Example" %}} + +```json +{ + "module_id": "acme:dashboard", + "visibility": "public", + "url": "https://github.com/acme/dashboard", + "description": "An example dashboard for a fictitious company called Acme.", + "applications": [ + { + "name": "dashboard", + "type": "single_machine", + "entrypoint": "dist/index.html" + } + ] +} +``` + +{{% /tab %}} +{{< /tabs >}} + +This file specifies the contents of the module. +It is required for your module. + +{{% expand "Click to view more information on attributes." %}} + + +| Name | Type | Inclusion | Description | +|------|------|-----------|-------------| +| `module_id` | string | **Required** | The module ID, which includes the organization name and the module name. `module_id` uniquely identifies your module. | +| `visibility` | string | **Required** | Must be `"public"`. | +| `description` | string | **Required** | A description of your module and what it provides. | +| `url` | string | Optional | The URL of the GitHub repository containing the source code of the module. | +| `applications` | array | Optional | Objects that provide information about the [applications](/operate/control/viam-applications/) associated with the module. | +| `models` | array | Optional | Empty unless you are shipping the app alongside models. For information on how to add models, see [Integrate other hardware](/operate/get-started/other-hardware/). | + +{{% /expand%}} + +The `applications` field is an array of application objects with the following properties: + + +| Property | Type | Description | +| ------------ | ------ | ----------- | +| `name` | string | The name of your application, which will be a part of the application's URL (`name_publicnamespace.viamapplications.com`). For more information on valid names see [Valid application identifiers](/operate/reference/naming-modules/#valid-application-identifiers). | +| `type` | string | The type of application (currently only `"single_machine"` is supported). | +| `entrypoint` | string | The path to the HTML entry point for your application. The `entrypoint` field specifies the path to your application's entry point. For example:
  • "dist/index.html": Static content rooted at the `dist` directory
  • "dist/foo.html": Static content rooted at the `dist` directory, with `foo.html` as the entry point
  • "dist/": Static content rooted at the `dist` directory (assumes `dist/index.html` exists)
  • "dist/bar/foo.html": Static content rooted at `dist/bar` with `foo.html` as the entry point
| + +{{% /tablestep %}} +{{% tablestep number=2 %}} +**Register your module** with Viam: + +{{< tabs >}} +{{% tab name="Template" %}} + +```sh {class="command-line" data-prompt="$" data-output="3-10"} +viam module create --name="app-name" --public-namespace="namespace" +``` + +{{% /tab %}} +{{% tab name="Example" %}} + +```sh {class="command-line" data-prompt="$" data-output="3-10"} +viam module create --name="air-quality" --public-namespace="naomi" +``` + +{{% /tab %}} +{{< /tabs >}} + +{{% /tablestep %}} +{{% tablestep number=3 %}} + +**Package your static files and your meta.json file and upload them** to the Viam Registry: + +```sh {class="command-line" data-prompt="$" data-output="3-10"} +tar -czvf module.tar.gz meta.json +viam module upload --upload=module.tar.gz --platform=any --version=0.0.1 +``` + +For subsequent updates run these commands again with an updated version number. + +{{% /tablestep %}} +{{< /table >}} + +## Access your application + +After uploading your module with the application configuration, your application will be available at: + +```txt +https://your-app-name_your-public-namespace.viamapplications.com +``` + +Users will be prompted to authenticate with their Viam credentials before accessing your application: + +1. User navigates to `your-app-name_your-public-namespace.viamapplications.com`. +1. User authenticates with Viam credentials. +1. User selects an organization, location, and machine. +1. User is redirected to `your-app-name_your-public-namespace.viamapplications.com/machine/`. +1. Your application is rendered with access to the selected machine. + The credentials for that one machine are provided in the cookies. + +## Example + + + +For a React application that shows camera feeds for a machine, see [Viam Camera Viewer](https://github.com/viam-labs/viam-camera-viewer). + +## Limitations + +- Applications currently only support single-machine applications. +- All modules with applications must have public visibility. +- The page will always render the latest version. +- Browsers with cookies disabled are not supported. +- Viam applications serve static files. + If you are building an application with server-side rendering or need other back-end capabilities, Viam applications is not the right choice. + +## Security considerations + +- Customer applications are stored publicly on the internet, so avoid uploading sensitive information in your application code or assets. +- API keys and secrets are stored in the browser's cookies. +- Users authenticate with FusionAuth. + +## FAQ + +### Can I use a custom domain? + +Viam does not currently support using custom domains (for example: `app.mycustomdomain.com/machine/`) to serve your Viam application. +You can, however, redirect from your domain to your Viam application (`app.mycustomdomain.com` -> `your-app-name_your-public-namespace.viamapplications.com`). +You can configure a redirect (HTTP 301) on your web server or hosting provider from `app.mycustomdomain.com/*` to `your-app-name_your-public-namespace.viamapplications.com/*`. diff --git a/docs/operate/control/web-app.md b/docs/operate/control/web-app.md index 6bfdb0ecdf..943426b8d8 100644 --- a/docs/operate/control/web-app.md +++ b/docs/operate/control/web-app.md @@ -13,6 +13,11 @@ The TypeScript SDK includes: - Implementation of the standard component and service APIs to control your hardware and software - Authentication tools so users can log in securely +{{< alert title="Tip: Host your application on Viam" color="tip" >}} +You can host most apps by [deploying them as Viam applications](/operate/control/viam-applications/). +If your application requires server-side rendering or other back-end functionality, self-host your application instead. +{{< /alert >}} + ## Install the TypeScript SDK Run the following command in your terminal to install the Viam TypeScript SDK: diff --git a/docs/operate/get-started/other-hardware/module-configuration.md b/docs/operate/get-started/other-hardware/module-configuration.md index 3bdbebd216..ffae6d1ab6 100644 --- a/docs/operate/get-started/other-hardware/module-configuration.md +++ b/docs/operate/get-started/other-hardware/module-configuration.md @@ -242,6 +242,64 @@ For any version type other than **Patch (X.Y.Z)**, the module will upgrade as so If, for example, the module provides a motor component, and the motor is running, it will stop while the module upgrades. {{% /alert %}} +### Module meta.json configuration + +When creating a module, you'll need to create a `meta.json` file that defines the module's properties. This file includes information about the module's ID, visibility, models, and other features. + +Here's an example of a `meta.json` file: + +```json +{ + "module_id": "your-namespace:your-module", + "visibility": "public", + "url": "https://github.com/your-org/your-repo", + "description": "Your module description", + "models": [ + { + "api": "rdk:component:base", + "model": "your-namespace:your-module:your-model" + } + ], + "entrypoint": "run.sh", + "first_run": "setup.sh" +} +``` + +For modules that include [Viam applications](/operate/control/viam-applications/), you can add the `applications` field: + +```json +{ + "module_id": "your-namespace:your-module", + "visibility": "public", + "url": "https://github.com/your-org/your-repo", + "description": "Your module description", + "models": [ + { + "api": "rdk:component:base", + "model": "your-namespace:your-module:your-model" + } + ], + "entrypoint": "run.sh", + "applications": [ + { + "name": "your-app-name", + "type": "web", + "entrypoint": "dist/index.html" + } + ] +} +``` + +The `applications` field is an array of application objects with the following properties: + +| Property | Type | Description | +| ------------ | ------ | ------------------------------------------------------------------------------------------------- | +| `name` | string | The name of your application, which will be used in the URL (`name.publicnamespace.viamapps.com`) | +| `type` | string | The type of application (currently only `"web"` is supported) | +| `entrypoint` | string | The path to the HTML entry point for your application | + +For more information about Viam applications, see the [Viam applications documentation](/operate/control/viam-applications/). + ### Environment variables Each module has access to the following default environment variables. diff --git a/docs/operate/reference/naming-modules.md b/docs/operate/reference/naming-modules.md index 65b29c67af..328da37668 100644 --- a/docs/operate/reference/naming-modules.md +++ b/docs/operate/reference/naming-modules.md @@ -9,7 +9,7 @@ description: "Add support for a new component or service model by writing a modu languages: ["c++"] viamresources: [] platformarea: ["registry"] -toc_hide: true +toc_hide: false --- Each modular resource has two associated triplets: an API namespace triplet to indicate which [API](/dev/reference/apis/) it implements, and a model namespace triplet to uniquely identify the modular resource {{< glossary_tooltip term_id="model" text="model" >}}. @@ -95,6 +95,30 @@ More requirements: Determine the model name you want to use based on these requirements, then proceed to the next section. +## Valid application identifiers + +If your module includes a [Viam app](/operate/control/viam-applications/), you need to define the application name in your module's `meta.json` file. +Application names have the following requirements: + +- Application names must be all-lowercase. +- Application names may only use alphanumeric (`a-z` and `0-9`) and hyphen (`-`) characters. +- Application names may not start or end with a hyphen. +- Application names must be unique within your organization's namespace. + +The URL for accessing your Viam app will contain your application name: + +```txt +https://app-name_your-public-namespace.viamapps.com +``` + +For example, if your organization namespace is `acme` and your application name is `dashboard`, your application will be accessible at: + +```txt +https://dashboard_acme.viamapps.com +``` + +For more information about Viam apps, see the [Viam apps documentation](/operate/control/viam-applications/). + ## Create a namespace for your organization When uploading modules to the Viam Registry, you must set a unique namespace for your organization to associate your module with. diff --git a/netlify.toml b/netlify.toml index 6151543da3..a39bc0fcec 100644 --- a/netlify.toml +++ b/netlify.toml @@ -57,7 +57,7 @@ [plugins.inputs] # change this key to a new one any time you need to restart from scratch - cacheKey = ["July102025"] + cacheKey = ["July172025"] # either "warn" or "error" failBuildOnError = true diff --git a/static/include/metajson.md b/static/include/metajson.md index 134e71d727..2dc5b8d052 100644 --- a/static/include/metajson.md +++ b/static/include/metajson.md @@ -40,16 +40,16 @@ Do not change the module_id.

models -object -Required -

A list of one or more {{< glossary_tooltip term_id="model" text="models" >}} provided by your custom module. You must provide at least one model, which consists of an api and model key pair. If you are publishing a public module ("visibility": "public"), the namespace of your model must match the namespace of your organization.

+array +Optional +

A list of one or more {{< glossary_tooltip term_id="model" text="models" >}} provided by your custom module. You must provide at least one model in the models array or one application in the applications array. A model consists of an api and model key pair. If you are publishing a public module ("visibility": "public"), the namespace of your model must match the namespace of your organization.

You are strongly encouraged to include a markdown_link to the section of the README containing configuration information about each model, so that the section will be displayed alongside the configuration panel when configuring the model. For example, "README.md#configure-your-meteo_pm-sensor". Please also include a short_description describing what hardware the model supports.

entrypoint string -Required -The name of the file that starts your module program. This can be a compiled executable, a script, or an invocation of another program. If you are providing your module as a single file to the upload command, provide the path to that single file. If you are providing a directory containing your module to the upload command, provide the path to the entry point file contained within that directory.

If you have a local module, the local module uses its configured executable_path instead of entrypoint. +Optional +The name of the file that starts your module program. This can be a compiled executable, a script, or an invocation of another program. If you are providing your module as a single file to the upload command, provide the path to that single file. If you are providing a directory containing your module to the upload command, provide the path to the entry point file contained within that directory. Required if you are shipping a model. build @@ -69,5 +69,11 @@ Do not change the module_id.

Optional Enables VS Code hover and autocomplete as you edit your module code. Gets auto-generated when you run viam module generate or viam module create. Has no impact on the module's function. + +applications +array +Optional +Objects that provide information about the [applications](/operate/control/viam-applications/) provided by the module. + diff --git a/static/spa.mp4 b/static/spa.mp4 new file mode 100644 index 0000000000..8704d06d6c Binary files /dev/null and b/static/spa.mp4 differ diff --git a/static/spa.webm b/static/spa.webm new file mode 100644 index 0000000000..49caed05ed Binary files /dev/null and b/static/spa.webm differ