diff --git a/.github/workflows/sdk_protos_map.csv b/.github/workflows/sdk_protos_map.csv index bc9514a695..f0a3e41abb 100644 --- a/.github/workflows/sdk_protos_map.csv +++ b/.github/workflows/sdk_protos_map.csv @@ -83,9 +83,7 @@ button,GetResourceName,No,get_resource_name,Name,getResourceName,name button,Close,No,close,Close,, ## Camera -camera,GetImage,,get_image,Image,image,getImage camera,GetImages,,get_images,Images,getImages,getImages -camera,RenderFrame,,,,,renderFrame camera,GetPointCloud,,get_point_cloud,NextPointCloud,pointCloud,getPointCloud camera,GetProperties,,get_properties,Properties,properties,getProperties ## TED: Camera in Go SDK doesn't appear to implement (inherit) these: @@ -173,6 +171,7 @@ motor,IsPowered,No,is_powered,IsPowered,powerState,isPowered ## HACK: No proto for these (and/or inherited in Go SDK), manually mapping: motor,IsMoving,Yes,is_moving,IsMoving,isMoving,isMoving motor,Stop,Yes,stop,Stop,stop,stop +motor,GetGeometries,No,get_geometries,,, motor,Reconfigure,No,,Reconfigure,, # NOT implemented in other languages motor,DoCommand,,do_command,DoCommand,doCommand,doCommand @@ -229,6 +228,7 @@ servo,GetPosition,Yes,get_position,Position,position,getPosition ## HACK: No proto for these (and/or inherited in Go SDK), manually mapping: servo,IsMoving,No,is_moving,IsMoving,isMoving,isMoving servo,Stop,Yes,stop,Stop,stop,stop +servo,GetGeometries,No,get_geometries,,, servo,Reconfigure,No,,Reconfigure,, # NOT implemented in other languages servo,DoCommand,,do_command,DoCommand,doCommand,doCommand @@ -254,7 +254,6 @@ base_remote_control,Close,,,Close,, ## Data Manager data_manager,Sync,No,,Sync,,sync -data_manager,UploadImageToDatasets,No,,UploadImageToDatasets,,, data_manager,UploadBinaryDataToDatasets,No,,UploadBinaryDataToDatasets,,uploadBinaryDataToDatasets ## HACK: No proto for these (and/or inherited in Go SDK), manually mapping: data_manager,Reconfigure,No,,Reconfigure,, @@ -441,6 +440,7 @@ billing,GetOrgBillingInformation,,get_org_billing_information,GetOrgBillingInfor billing,GetInvoicesSummary,,get_invoices_summary,GetInvoicesSummary,,getInvoicesSummary billing,GetInvoicePDF,,get_invoice_pdf,GetInvoicePDF,,getInvoicePdf billing,CreateInvoiceAndChargeImmediately,,create_invoice_and_charge_immediately,,, +billing,ChargeOrganization,,charge_organization,,, ## Data data,GetLatestTabularData,,get_latest_tabular_data,GetLatestTabularData,getLatestTabularData,getLatestTabularData @@ -469,6 +469,13 @@ data,CreateDataPipeline,,create_data_pipeline,CreateDataPipeline,,createDataPipe data,DeleteDataPipeline,,delete_data_pipeline,DeleteDataPipeline,,deleteDataPipeline data,ListDataPipelineRuns,,list_data_pipeline_runs,ListDataPipelineRuns,,listDataPipelineRuns data,RenameDataPipeline,,,RenameDataPipeline,, +data,AddTagsToBinaryDataByFilter,,add_tags_to_binary_data_by_filter,,, +data,CreateBinaryDataSignedURL,,create_binary_data_signed_url,,, +data,CreateIndex,,create_index,,, +data,DeleteIndex,,delete_index,,, +data,ListIndexes,,list_indexes,,, +data,RemoveTagsFromBinaryDataByFilter,,remove_tags_from_binary_data_by_filter,,, +data,UpdateBoundingBox,,update_bounding_box,,, ## Dataset dataset,CreateDataset,,create_dataset,CreateDataset,createDataset,createDataset diff --git a/.htmltest-local.yml b/.htmltest-local.yml index 6066d87071..54f0dc7fcc 100644 --- a/.htmltest-local.yml +++ b/.htmltest-local.yml @@ -9,6 +9,9 @@ IgnoreURLs: - "rtk2go.com" IgnoreDirs: - "lib" + - "operate" + - "manage" + - "data-ai" CacheExpires: "6h" # IgnoreDirs: - if we need to ever ignore files CheckExternal: false \ No newline at end of file diff --git a/assets/scss/_sidebar-tree.scss b/assets/scss/_sidebar-tree.scss index 6cd2996d26..02bfe1e50b 100644 --- a/assets/scss/_sidebar-tree.scss +++ b/assets/scss/_sidebar-tree.scss @@ -187,7 +187,7 @@ li .indent { } .ul-2 > li:not(:last-child) { - padding-bottom: 8px; + padding-bottom: 2px; } } diff --git a/assets/scss/_styles_project.scss b/assets/scss/_styles_project.scss index 39bdc445c2..b06a7ad257 100644 --- a/assets/scss/_styles_project.scss +++ b/assets/scss/_styles_project.scss @@ -177,6 +177,20 @@ h7, .td-content > h3 { margin-bottom: 0.667rem; + margin-top: 1.5rem; +} + +// The float:left on ol > li::before creates floats that escape the ol's +// block formatting context. Since h3 has clear:both, it clears past those +// floats, creating an oversized gap. flow-root contains the floats in +// the ol's own BFC so they don't affect adjacent elements. +// Zero the last li's margin-bottom because flow-root prevents it from +// collapsing with the ol's margin, which would add unwanted extra space. +.td-content > ol { + display: flow-root; +} +.td-content > ol > li:last-child { + margin-bottom: 0; } /* END Adjust Heading sizes*/ @@ -3191,57 +3205,9 @@ nav { background-color: rgb(232, 232, 234); } -.second-nav { - min-width: 100%; - padding: 0.25rem 1rem; - border-top: 1px solid #e4e4e6; - border-bottom: 1px solid #e4e4e6; -} - -.second-nav > ul { - padding: 0; - padding-left: 0.25rem; - margin: 0; -} - -.second-nav > ul > li { - display: inline-block; - font-family: - "Public Sans", - -apple-system, - BlinkMacSystemFont, - "Segoe UI", - Roboto, - "Helvetica Neue", - Arial, - sans-serif, - "Apple Color Emoji", - "Segoe UI Emoji", - "Segoe UI Symbol"; - font-size: 0.875rem; - line-height: 1.25rem; - margin: 5px 0px; - font-weight: 300; -} - -.second-nav > ul > li > a { - color: #333; - padding: 5px 0.5rem; - margin-right: 0.5rem; -} - -.second-nav > ul > li > a:hover, -.second-nav > ul > li > a.active-path { - text-decoration: none; - background-color: rgba(0, 0, 0, 0.03); - border-radius: 4px; - color: #282829; - font-weight: 500; -} - @media (min-width: 768px) { .td-main main { - padding-top: 7.5rem; + padding-top: 5rem; } } @@ -3249,11 +3215,6 @@ nav { min-height: 3.5rem; } -@media (max-width: 767px) { - .second-nav { - display: none; - } -} @media (min-width: 992px) { .d-lg-block { @@ -3261,23 +3222,17 @@ nav { } } -span.section-overview { - display: none; -} ul > li.nav-fold > span > span.link-and-toggle { display: flex !important; flex-direction: row; } -ul > li.nav-fold:last-child { +ul.ul-0 > li.nav-fold:last-child { padding-bottom: 0.5rem; } @media (min-width: 768px) { - .ul-1 > li.nav-fold.hide-if-desktop { - display: none; - } #landing-page-sidebar { display: none; @@ -3290,24 +3245,38 @@ ul > li.nav-fold:last-child { li.nav-fold.header-only > span > span { color: #000000; - margin-top: 1rem; + margin-top: 0.25rem; } li.nav-fold.header-only:first-child > span > a { - margin-top: 0.5rem; + margin-top: 0.25rem; } li.nav-fold.header-only * li { text-transform: unset; } - li > span > ul.ul-2 { - padding-left: 0; + li.nav-top-section > span > span.link-and-toggle > a, + li.nav-top-section > a { + text-transform: uppercase; + font-size: 0.75rem; + letter-spacing: 0.05em; + font-weight: 600; + color: #666; + } + + li.nav-top-section > span > ul.ul-2 { + margin-left: 0.5rem; } ul.ul-2 > li > span > span { color: #282829; - font-weight: 600; + font-weight: 400; + font-size: 0.833rem; + } + + ul.ul-2 > li > a { + font-size: 0.833rem; } li.header-only > span > ul.ul-3 { @@ -3320,21 +3289,26 @@ ul > li.nav-fold:last-child { padding-left: 0.5rem; } - span.section-overview-title { - display: none; - } - .ul-1 > li.nav-fold > span > span.link-and-toggle { - display: none !important; - } .td-sidebar-nav__section .ul-1 ul.ul-2 { - padding-left: 0; + padding-left: 0.5rem; + border-left: 1px solid #e4e4e6; + margin-left: 0.5rem; } .td-sidebar-nav__section ul.ul-1 { margin-left: 0; } + + li.nav-top-section { + margin-bottom: 0.5rem; + border-bottom: 1px solid #e4e4e6; + } + + li.nav-top-section:last-child { + border-bottom: none; + } } .menu-toggle { diff --git a/assets/tutorials/first-project/add-plus-button.png b/assets/tutorials/first-project/add-plus-button.png new file mode 100644 index 0000000000..91f6cf66ed Binary files /dev/null and b/assets/tutorials/first-project/add-plus-button.png differ diff --git a/assets/tutorials/first-project/data-manager-search.png b/assets/tutorials/first-project/data-manager-search.png new file mode 100644 index 0000000000..66a0b14c85 Binary files /dev/null and b/assets/tutorials/first-project/data-manager-search.png differ diff --git a/assets/tutorials/first-project/gz-camera-search.png b/assets/tutorials/first-project/gz-camera-search.png new file mode 100644 index 0000000000..b5e6389be6 Binary files /dev/null and b/assets/tutorials/first-project/gz-camera-search.png differ diff --git a/assets/tutorials/first-project/try-vision-pipeline-fragment.png b/assets/tutorials/first-project/try-vision-pipeline-fragment.png new file mode 100644 index 0000000000..2b2a776b9c Binary files /dev/null and b/assets/tutorials/first-project/try-vision-pipeline-fragment.png differ diff --git a/config.toml b/config.toml index 2f47b84c1f..6c870a4af5 100644 --- a/config.toml +++ b/config.toml @@ -115,9 +115,9 @@ breadcrumb_disable = false footer_about_disable = false navbar_logo = true navbar_translucent_over_cover_disable = false -sidebar_menu_compact = true # When true, the section headings work like an accordian. +sidebar_menu_compact = true # When true, only the active path is expanded in the sidebar. sidebar_search_disable = true -ul_show = 3 # Always expand every first level section of the sidenav -- due to tabs, our 'first level' is 3 +ul_show = 1 # Show only top-level sections; deeper levels collapse unless active [params.ui.feedback] enable = true diff --git a/docs/_index.md b/docs/_index.md index 5da8c88295..e3023a9295 100644 --- a/docs/_index.md +++ b/docs/_index.md @@ -3,17 +3,14 @@ title: "Viam Documentation" linkTitle: "Viam Documentation" description: "Viam integrates with hardware and software on any device. Use AI, machine learning, and more to make any machine smarter — for one machine to thousands." weight: 1 -no_list: true type: "docs" -noToc: true -hide_feedback: true +layout: "empty" +canonical: "/what-is-viam/" sitemap: priority: 1.0 outputs: - html - REDIR -imageAlt: "/general/understand.png" -images: ["/general/understand.png"] noedit: true date: "2024-09-17" updated: "2024-10-11" @@ -26,69 +23,3 @@ aliases: - "/get-started/" - "/platform/" --- - -
-
-
-

Viam Documentation

-

- Viam integrates with hardware and software on any device in the physical world. Once you set up your machines, you can use Viam SDKs to program your devices and connected hardware. Everything is managed in the cloud and you can use machine learning, data management, and much more for your projects. -

- -
- App illustration -
-
-
- - -
-

The Viam platform - -

-

Viam allows you to control and program any sensor, actuator or other hardware that is connected to a device. The Viam platform offers builtin capabilities to capture data from devices to the cloud, to build and deploy machine learning models, to alert on problems, and much more. With the connection to the cloud, you can configure, control, and manage your devices from anywhere.

-
-
-
- Platform diagram - Platform diagram with connect elements highlighted - Platform diagram with apps element highlighted - Platform diagram with motion elements highlighted -
-
- -
- -
- -
-

Build & integrate

To get started, install Viam on any device and integrate your hardware. Then you can control your device and any attached physical hardware securely from anywhere in the world.

Learn more

-
- -
-

Work with Data and AI

Viam's data and AI capabilities enable you to capture and sync or upload data, build a dataset, train and deploy ML models, and run inference with computer vision. Then, you can act or alert on inferences.

Learn more

-
- -
-

Deploy, manage, and troubleshoot

Viam’s fleet management tooling allows you to remotely deploy and manage software on any fleet of devices. You can monitor all connected devices and troubleshoot any issues - from anywhere.

Learn more

-
- -
-
diff --git a/docs/build-apps/_index.md b/docs/build-apps/_index.md new file mode 100644 index 0000000000..6599d00c95 --- /dev/null +++ b/docs/build-apps/_index.md @@ -0,0 +1,20 @@ +--- +linkTitle: "Build apps" +title: "Build apps" +weight: 65 +layout: "docs" +type: "docs" +no_list: true +manualLink: "/build-apps/overview/" +description: "Build client apps that talk to your Viam machines and the Viam cloud." +date: "2026-04-10" +aliases: + # The following aliases are deferred. The pages listed still exist in + # the hidden operate/control/ and tutorials/control/ sections. Activate + # these aliases in the PR that deletes the old pages. + - /operate/control/web-app/ + - /operate/control/mobile-app/ + - /operate/control/viam-applications/ + - /operate/control/kiosk-app/ + - /operate/control/voice-app/ +--- diff --git a/docs/build-apps/app-tutorials/_index.md b/docs/build-apps/app-tutorials/_index.md new file mode 100644 index 0000000000..e7686fe1b6 --- /dev/null +++ b/docs/build-apps/app-tutorials/_index.md @@ -0,0 +1,10 @@ +--- +linkTitle: "App tutorials" +title: "App tutorials" +weight: 100 +layout: "docs" +type: "docs" +no_list: true +description: "Guided projects that walk through building a Viam app from start to finish." +date: "2026-04-13" +--- diff --git a/docs/build-apps/app-tutorials/tutorial-dashboard.md b/docs/build-apps/app-tutorials/tutorial-dashboard.md new file mode 100644 index 0000000000..011c4aa140 --- /dev/null +++ b/docs/build-apps/app-tutorials/tutorial-dashboard.md @@ -0,0 +1,280 @@ +--- +linkTitle: "Tutorial: single-machine dashboard" +title: "Build a single-machine dashboard" +weight: 10 +layout: "docs" +type: "docs" +description: "Build a TypeScript web dashboard for a single Viam machine. Displays a camera feed, a live sensor reading, and a motor control button, with a connection status indicator." +date: "2026-04-10" +--- + +In this tutorial, you will build a browser-based dashboard for a single Viam machine. The finished dashboard shows: + +- A live camera feed +- The most recent reading from a sensor +- A start/stop button for a motor +- A connection status indicator + +You will learn the four patterns that almost every Viam client app uses: opening a connection, reading state from a component, changing state on a component, and reacting to connection events. The dashboard runs locally in your browser by the end; deployment is out of scope for this tutorial. + +The tutorial uses vanilla TypeScript and Vite without any frontend framework. The patterns work the same in React, Vue, or Svelte; a vanilla setup keeps the SDK calls visible without framework ceremony. + +## What you need + +- A configured Viam machine with a camera, a sensor, and a motor. Any models work. If you do not have the physical hardware, add fake components in the Viam app's **CONFIGURE** tab: `fake:camera`, `fake:sensor`, and `fake:motor`. The fake components respond to SDK calls the same way real ones do. +- A completed [TypeScript setup](/build-apps/setup/typescript/). You should have a project directory with `@viamrobotics/sdk` installed, a `.env` file holding your machine credentials, and `index.html` plus `src/main.ts` files from the setup page. +- Two browser windows side by side, or two tabs you can switch between. One window runs your dashboard; the other opens the Viam app's **CONTROL** tab for the same machine so you can see server-side state change when your code runs. + +Before continuing, confirm your setup by running `npx vite` and verifying that the page from the setup step shows `Connected. Found N resources.` in the browser. If it does not, go back to [TypeScript setup](/build-apps/setup/typescript/) and fix the connection before continuing. + +## Step 1: Replace the HTML + +Open `index.html` and replace its contents with a layout that has slots for each piece of the dashboard: + +```html + + + + + My Viam Dashboard + + + +

My Viam Dashboard

+

Status: Connecting...

+ +
+

Camera

+ +
+ +
+

Sensor readings

+
+
+ +
+

Motor

+ + +
+ + + + +``` + +Save the file. If Vite is still running, it reloads automatically. You should see the page layout in your browser with empty values and non-functional buttons. + +## Step 2: Connect to your machine + +Open `src/main.ts` and replace its contents with a connection that stores the machine client as a module-level variable. You will add the dashboard logic on top of this connection in the steps that follow. + +```ts +import * as VIAM from "@viamrobotics/sdk"; + +const statusEl = document.getElementById("status") as HTMLSpanElement; +const cameraEl = document.getElementById("camera") as HTMLVideoElement; +const sensorEl = document.getElementById("sensor") as HTMLPreElement; +const startBtn = document.getElementById("start") as HTMLButtonElement; +const stopBtn = document.getElementById("stop") as HTMLButtonElement; + +let machine: VIAM.RobotClient; + +async function main() { + machine = await VIAM.createRobotClient({ + host: import.meta.env.VITE_HOST, + credentials: { + type: "api-key", + authEntity: import.meta.env.VITE_API_KEY_ID, + payload: import.meta.env.VITE_API_KEY, + }, + signalingAddress: "https://app.viam.com:443", + }); + + statusEl.textContent = "Connected"; + statusEl.className = "connected"; +} + +main().catch((err) => { + statusEl.textContent = `Connection failed: ${err.message ?? err}`; + statusEl.className = "disconnected"; +}); +``` + +Save the file. Refresh the browser. The status line should change from `Connecting...` to `Connected` in green. If it shows `Connection failed:`, check that your `.env` file has the right credentials and that your machine is online in the Viam app. + +## Step 3: Display the camera feed + +Add a camera stream to the dashboard. Use a `StreamClient` to attach the camera's WebRTC stream to the `