Skip to content
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions docs/build-apps/concepts/how-apps-connect.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ layout: "docs"
type: "docs"
description: "The transport paths the SDK uses, the session safety mechanism, and what the SDK reconnects automatically."
date: "2026-04-10"
aliases:
- /operate/reference/sessions/
---

A Viam client application needs to reach a machine that may be on a different network, behind a NAT, or both. This page describes the transport paths the SDK uses, the session safety mechanism, and how the SDK reconnects when the network drops.
Expand Down
1 change: 1 addition & 0 deletions docs/build-apps/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type: "docs"
description: "Build software that uses a Viam SDK to talk to your machines and the Viam cloud, from web dashboards to long-running backend services."
date: "2026-04-10"
aliases:
- /operate/control/
- /operate/control/headless-app/
- /product-overviews/sdk-as-client/
- /program/sdk-as-client/
Expand Down
175 changes: 175 additions & 0 deletions docs/build-modules/advanced-patterns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
---
linkTitle: "Advanced patterns"
title: "Advanced module patterns"
weight: 38
layout: "docs"
type: "docs"
description: "Define new resource APIs, deploy custom components as remote parts, and package modules with Docker."
date: "2026-04-20"
aliases:
- /operate/reference/advanced-modules/
- /operate/reference/advanced-modules/create-subtype/
- /operate/reference/advanced-modules/custom-components-remotes/
- /operate/reference/advanced-modules/docker-modules/
- /program/extend/
- /modular-resources/advanced/
- /registry/advanced/
- /extend/modular-resources/create/create-subtype/
- /modular-resources/advanced/create-subtype/
- /registry/advanced/create-subtype/
- /program/extend/sdk-as-server/
- /program/extend/custom-components-remotes/
- /extend/custom-components-remotes/
- /modular-resources/advanced/custom-components-remotes/
- /registry/advanced/custom-components-remotes/
---

Some use cases require approaches beyond the standard module workflow. This page covers three advanced patterns: defining a new resource API, deploying custom components as remote parts, and packaging modules with Docker.

## Define a new resource API

You can define a new, custom resource API if:

- You have a resource that does not fit into any of the existing [component](/reference/apis/#component-apis) or [service](/reference/apis/#service-apis) APIs.
- You have a resource that could fit into an existing API, but you want different methods and messages.

{{% alert title="Tip" color="tip" %}}

Defining a new resource API is significantly more complex than using an existing API. In most cases, use an existing API instead.

If you want to use most of an existing API but need a few additional functions, use the `DoCommand` endpoint with [extra parameters](/reference/sdks/use-extra-params/) to add custom functionality.

If your use case uses only `DoCommand` and no other API methods, define a new model of [generic component](/reference/components/generic/) or [generic service](/reference/services/generic/).

{{% /alert %}}

### Steps to define a new API

Viam uses [protocol buffers](https://protobuf.dev/) for API definition. To define a new API:

1. Decide whether your custom API is a component (interfaces with hardware) or a service (provides higher-level functionality).

2. Choose a name for your API (called the subtype). Determine a valid API namespace triplet. For example, `your-org-namespace:component:gizmo`.

3. Create a directory for your module with a `src` subdirectory.

{{% alert title="Tip" color="tip" %}}
If you are writing your module in Python, you can use this [module generator tool](https://github.com/viam-labs/generator-viam-module) to generate stub files for the new API and a module that implements it.
{{% /alert %}}

4. Write the proto methods in a `<API name>.proto` file inside `src/proto/`. For reference:

- [Example modular component proto file](https://github.com/viamrobotics/viam-python-sdk/blob/main/examples/complex_module/src/proto/gizmo.proto)
- [Example modular service proto file](https://github.com/viam-labs/speech-service-api/blob/main/src/proto/speech.proto)
- [Built-in Viam resource proto files](https://github.com/viamrobotics/api/tree/main/proto/viam)

5. Define the proto methods in Python or Go in a file called `api.py` or `api.go`:

- [Example component in Python](https://github.com/viamrobotics/viam-python-sdk/blob/main/examples/complex_module/src/gizmo/api.py)
- [Example service in Python](https://github.com/viam-labs/speech-service-api/blob/main/src/speech_service_api/api.py)

6. Generate the required configuration files (`buf.yaml`, `buf.gen.yaml`, `buf.lock`). See the [Buf documentation](https://buf.build/docs/generate/usage/).

7. Use the protobuf compiler to [generate](https://buf.build/docs/tutorials/getting-started-with-buf-cli/#generate-code) all other necessary protocol buffer code from your `.proto` file.

### After defining your API

Once your API is defined, [create a model that implements it](/build-modules/write-a-driver-module/).

Keep in mind:

- You cannot use [SDKs](/reference/sdks/) to call your new API unless you build out the client to support it. Write code against the API in the language you used to define it.
- You need a local copy of the module code on whatever machine runs client code against it.
- Import the API definition from the module directory. For example, in Python: `from path.to.module.src.gizmo import Gizmo`.

## Custom components as remote parts

Running modular resources on the computer directly connected to your components is the preferred approach. However, if you cannot use modular resources because you need to host `viam-server` on a non-Linux system or have a compilation issue, you can code a custom resource implementation, host it on a server, and add it as a [remote part](/hardware/multi-machine/add-a-remote-part/) of your machine.

Once configured, you control the custom component with the Viam SDKs like any other component.

### Steps

{{< tabs >}}
{{% tab name="Go" %}}

1. Code a new model of a built-in resource type by creating a new interface that implements the required methods from its [API definition](/reference/apis/).
2. Register the custom component on a new gRPC server instance and start the server.
3. Add the server as a [remote part](/hardware/multi-machine/add-a-remote-part/) of your machine.
4. (Optional) Ensure the remote server automatically starts when the machine boots.

Each remote server can host one or many custom components.

{{% /tab %}}
{{% tab name="Python" %}}

{{< alert title="Tip" color="tip" >}}
For detailed instructions, see the full example in the [Python SDK documentation](https://python.viam.dev/examples/example.html#subclass-a-component).
{{< /alert >}}

1. Code a new model of a built-in resource type by subclassing it (for example, `sensor` or `arm`). Implement any required methods from its [API definition](/reference/apis/).
2. Register the custom component on a new gRPC server instance using the [`viam.rpc` library](https://python.viam.dev/autoapi/viam/rpc/index.html).
3. Add the server as a [remote part](/hardware/multi-machine/add-a-remote-part/) of your machine.
4. (Optional) Ensure the remote server automatically starts when the machine boots.

Each remote server can host one or many custom components.

{{% /tab %}}
{{< /tabs >}}

{{% alert title="Important" color="note" %}}

You must define all methods belonging to a built-in resource type when defining a new model. Otherwise, the class will not instantiate.

- In Python, raise `NotImplementedError()` or use `pass` in methods you do not want to implement.
- In Go, return `errUnimplemented`.

{{% /alert %}}

## Deploy a module using Docker

In rare cases, you may need to package and deploy a module using Docker. Use cases include:

- Your module has complex system dependencies that cannot be easily installed on a machine.
- You use a large container image and some layers are already cached on the machine.
- You have specific security requirements.

If you deploy using Docker, create a "first run" script to handle setup. This is not recommended for modules that do not use Docker.

### Use a `first_run` script

1. Create a tarball containing:

- The module's entrypoint script or binary:

```sh {class="command-line" data-prompt="$"}
#!/bin/bash
exec docker run <YOUR_CONTAINER_IMAGE> <YOUR_CONTAINER_OPTIONS>
```

- A [meta.json](/build-modules/module-reference/#metajson-schema) file.

- A first-run script that runs during setup:

```sh {class="command-line" data-prompt="$"}
#!/usr/bin/env bash
docker pull mongo:6
echo "Setup complete."
exit 0
```

[This example Makefile](https://github.com/viam-labs/wifi-sensor/blob/7823b6ad3edcbbbf20b06c34b3181453f5f3f078/Makefile) builds a module binary and bundles it with a meta.json and first-run script.

2. Edit meta.json to include the `first_run` field:

```json
{
"first_run": "first_run.sh"
}
```

3. Configure the module on your machine normally. The first-run script executes once when `viam-server` receives a new configuration, and once per version update.

4. (Optional) To force the first-run script to run again without changing the module version, delete the marker file at `.viam/packages/data/module/<id>/bin.first_run_succeeded`.

5. (Optional) The default first-run timeout is 1 hour. Adjust with `"first_run_timeout": "5m"` in the module configuration.
1 change: 1 addition & 0 deletions docs/build-modules/deploy-a-module.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type: "docs"
description: "Package, upload, and distribute a module through the Viam registry."
date: "2025-01-30"
aliases:
- /operate/modules/deploy-a-module/
- /build/development/deploy-a-module/
- /development/deploy-a-module/
- /extend/modular-resources/upload/
Expand Down
1 change: 1 addition & 0 deletions docs/build-modules/manage-modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ icon: true
tags: ["modular resources", "components", "services", "registry"]
description: "Update or delete your existing modules, or change their privacy settings."
aliases:
- /operate/modules/advanced/manage-modules/
- /use-cases/deploy-code/
- /use-cases/manage-modules/
- /how-tos/manage-modules/
Expand Down
11 changes: 11 additions & 0 deletions docs/build-modules/module-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ type: "docs"
description: "Reference for module developers: lifecycle, interfaces, meta.json schema, CLI commands, environment variables, and registry rules."
date: "2025-03-05"
aliases:
- /operate/modules/advanced/logging/
- /operate/modules/advanced/metajson/
- /operate/modules/advanced/module-configuration/
- /development/module-reference/
- /operate/modules/lifecycle-module/
- /operate/modules/lifecycle-of-a-module/
Expand All @@ -17,6 +20,14 @@ This page is a reference for module developers. For step-by-step
instructions, see [Write a Module](/build-modules/write-a-driver-module/) and
[Deploy a Module](/build-modules/deploy-a-module/).

## Module configuration {#module-configuration}

For details on configuring modules and modular resources on a machine:

- [Environment variables](#environment-variables) — custom env vars passed to your module
- [Registry validation rules](#registry-validation-rules) — valid API and model identifier formats
- [meta.json schema](#metajson-schema) — module metadata including visibility settings

## Module lifecycle

Every module, local or registry, runs as a separate child process alongside
Expand Down
2 changes: 2 additions & 0 deletions docs/build-modules/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ layout: "docs"
type: "docs"
description: "Understand the two kinds of modules and how to extend your machine with custom hardware drivers and application logic."
aliases:
- /operate/modules/
- /operate/modules/advanced/
- /build-modules/from-hardware-to-logic/
---

Expand Down
1 change: 1 addition & 0 deletions docs/build-modules/platform-apis.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ layout: "docs"
type: "docs"
description: "Write your validate and reconfigure functions to handle dependencies in your custom modular resource."
aliases:
- /operate/modules/advanced/platform-apis/
date: "2025-11-05"
---

Expand Down
2 changes: 2 additions & 0 deletions docs/build-modules/use-registry-modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ layout: "docs"
type: "docs"
description: "Before writing a module, check whether one already exists. The registry has more than hardware drivers."
date: "2026-04-17"
aliases:
- /registry/
---

Before you write a module, check whether one already exists. The Viam registry contains more than hardware drivers. Many software capabilities you might want to build are already published as modules you can configure and use directly.
Expand Down
2 changes: 1 addition & 1 deletion docs/build-modules/write-a-cpp-module.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ For example, the [sensor API](/reference/apis/components/sensor/) has a `GetRead
If instead of just getting readings, you actually have an encoder and need to be able to reset the zero position, use the [encoder API](/reference/apis/components/encoder/) so you can define functionality behind the `GetPosition` and `ResetPosition` methods.

In addition to the list of methods, another reason to choose one API over another is how certain APIs fit into the Viam ecosystem.
For example, though you could technically implement a GPS as a sensor with just the `GetReadings` method, if you implement it as a movement sensor then you have access to methods like `GetCompassHeading` which allow you to use your GPS module with the [navigation service](/operate/reference/services/navigation/).
For example, though you could technically implement a GPS as a sensor with just the `GetReadings` method, if you implement it as a movement sensor then you have access to methods like `GetCompassHeading` which allow you to use your GPS module with the [navigation service](/reference/services/navigation/).
For this reason, it's generally best to choose the API that most closely matches your hardware or software.
{{< /expand >}}

Expand Down
1 change: 1 addition & 0 deletions docs/build-modules/write-a-driver-module.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type: "docs"
description: "Build a module that implements a resource API and runs as a separate process."
date: "2025-01-30"
aliases:
- /operate/modules/write-a-driver-module/
- /build/development/write-a-module/
- /development/write-a-module/
- /development/write-a-driver-module/
Expand Down
2 changes: 2 additions & 0 deletions docs/hardware/common-components/add-a-base.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ type: "docs"
description: "Add and configure a base to drive a mobile robot with movement commands."
date: "2025-03-07"
aliases:
- /operate/reference/components/base/
- /operate/reference/components/base/boat/
- /hardware-components/add-a-base/
---

Expand Down
1 change: 1 addition & 0 deletions docs/hardware/common-components/add-a-board.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type: "docs"
description: "Add and configure a board component to expose GPIO pins, analog readers, and digital interrupts."
date: "2025-03-07"
aliases:
- /operate/reference/components/board/
- /hardware-components/add-a-board/
---

Expand Down
1 change: 1 addition & 0 deletions docs/hardware/common-components/add-a-button.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type: "docs"
description: "Add and configure a button component to detect presses from a physical button."
date: "2025-03-07"
aliases:
- /operate/reference/components/button/
- /hardware-components/add-a-button/
---

Expand Down
5 changes: 5 additions & 0 deletions docs/hardware/common-components/add-a-camera.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type: "docs"
description: "Add and configure a camera component, verify the feed, and capture an image programmatically."
date: "2025-01-30"
aliases:
- /operate/reference/components/camera/
- /build/foundation/add-a-camera/
- /foundation/add-a-camera/
- /hardware-components/add-a-camera/
Expand Down Expand Up @@ -332,6 +333,10 @@ Camera streams use a significant amount of CPU resources. The more CPU resources

{{< /expand >}}

## Camera calibration

If you are using a camera with the motion service for arm movement or pick-and-place, you may need to calibrate it. Calibration computes the camera's intrinsic and distortion parameters so the motion service can project 2D image coordinates into 3D workspace coordinates accurately. See [Calibrate a camera for motion planning](/motion-planning/frame-system/camera-calibration/).

## Related

- [Camera API reference](/reference/apis/components/camera/): full method documentation.
Expand Down
1 change: 1 addition & 0 deletions docs/hardware/common-components/add-a-gantry.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type: "docs"
description: "Add and configure a gantry component for precise linear positioning along one or more axes."
date: "2025-03-07"
aliases:
- /operate/reference/components/gantry/
- /hardware-components/add-a-gantry/
---

Expand Down
1 change: 1 addition & 0 deletions docs/hardware/common-components/add-a-generic.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type: "docs"
description: "Add and configure a generic component for hardware that doesn't fit any other component type."
date: "2025-03-07"
aliases:
- /operate/reference/components/generic/
- /hardware-components/add-a-generic/
---

Expand Down
1 change: 1 addition & 0 deletions docs/hardware/common-components/add-a-gripper.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type: "docs"
description: "Add and configure a gripper component to open, close, and grasp objects."
date: "2025-03-07"
aliases:
- /operate/reference/components/gripper/
- /hardware-components/add-a-gripper/
---

Expand Down
1 change: 1 addition & 0 deletions docs/hardware/common-components/add-a-motor.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type: "docs"
description: "Add and configure a motor component and test it from the Viam app."
date: "2025-03-07"
aliases:
- /operate/reference/components/motor/
- /hardware-components/add-a-motor/
---

Expand Down
2 changes: 2 additions & 0 deletions docs/hardware/common-components/add-a-movement-sensor.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ type: "docs"
description: "Add and configure a movement sensor like a GPS, IMU, or odometry source."
date: "2025-03-07"
aliases:
- /operate/reference/components/movement-sensor/
- /operate/reference/components/movement-sensor/set-up-base-station/
- /hardware-components/add-a-movement-sensor/
---

Expand Down
1 change: 1 addition & 0 deletions docs/hardware/common-components/add-a-power-sensor.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type: "docs"
description: "Add and configure a power sensor to monitor voltage, current, and power consumption."
date: "2025-03-07"
aliases:
- /operate/reference/components/power-sensor/
- /hardware-components/add-a-power-sensor/
---

Expand Down
1 change: 1 addition & 0 deletions docs/hardware/common-components/add-a-sensor.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type: "docs"
description: "Add and configure a sensor to read environmental data like temperature, humidity, or distance."
date: "2025-03-07"
aliases:
- /operate/reference/components/sensor/
- /hardware-components/add-a-sensor/
---

Expand Down
1 change: 1 addition & 0 deletions docs/hardware/common-components/add-a-switch.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type: "docs"
description: "Add and configure a switch component to read and set the position of a multi-position switch."
date: "2025-03-07"
aliases:
- /operate/reference/components/switch/
- /hardware-components/add-a-switch/
---

Expand Down
3 changes: 3 additions & 0 deletions docs/hardware/common-components/add-an-arm.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ type: "docs"
description: "Add and configure a robotic arm, verify joint motion, and test end-effector positioning."
date: "2025-03-07"
aliases:
- /operate/reference/components/arm/
- /operate/reference/components/arm/eva/
- /operate/reference/components/arm/yahboom-dofbot/
- /hardware-components/add-an-arm/
---

Expand Down
Loading
Loading