diff --git a/.github/vale/styles/Viam/AbbreviationsPeriods.yml b/.github/vale/styles/Viam/AbbreviationsPeriods.yml
index 4ca408556d..b5064a2725 100644
--- a/.github/vale/styles/Viam/AbbreviationsPeriods.yml
+++ b/.github/vale/styles/Viam/AbbreviationsPeriods.yml
@@ -1,7 +1,7 @@
# Based on: https://github.com/errata-ai/Google/blob/master/Google/Periods.yml
extends: existence
message: "Don't use periods with acronyms or initialisms such as '%s'."
-link: 'https://docs.rackspace.com/docs/style-guide/style/abbreviations'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/abbreviations.rst'
level: warning
nonword: true
tokens:
diff --git a/.github/vale/styles/Viam/Adverbs.yml b/.github/vale/styles/Viam/Adverbs.yml
index ae116b99aa..55bb65a927 100644
--- a/.github/vale/styles/Viam/Adverbs.yml
+++ b/.github/vale/styles/Viam/Adverbs.yml
@@ -1,6 +1,6 @@
extends: existence
message: "You can remove most adverbs. Use your best judgment."
-link: 'https://docs.rackspace.com/docs/style-guide/writing/write-clear-concise-sentences-paragraphs/'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/writing/write-clear-concise-sentences-paragraphs.rst'
level: suggestion
ignorecase: true
scope: sentence
diff --git a/.github/vale/styles/Viam/Antecedents.yml b/.github/vale/styles/Viam/Antecedents.yml
index 1110b668fc..73348d4812 100644
--- a/.github/vale/styles/Viam/Antecedents.yml
+++ b/.github/vale/styles/Viam/Antecedents.yml
@@ -1,6 +1,6 @@
extends: existence
message: "Avoid using the antecedent '%s' at the beginning of sentences or clauses."
-link: 'https://docs.rackspace.com/docs/style-guide/writing/use-pronouns-carefully/'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/writing/use-pronouns-carefully.rst'
level: suggestion
ignorecase: false
scope: sentence
diff --git a/.github/vale/styles/Viam/Avoid.yml b/.github/vale/styles/Viam/Avoid.yml
index 2d1e3d3967..2100c8c7e9 100644
--- a/.github/vale/styles/Viam/Avoid.yml
+++ b/.github/vale/styles/Viam/Avoid.yml
@@ -1,6 +1,6 @@
extends: existence
message: "Don't use '%s'."
-link: 'https://docs.rackspace.com/docs/style-guide/terminology/alphabetical-terms'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/terminology/alphabetical-terms.rst'
ignorecase: true
level: warning
tokens:
diff --git a/.github/vale/styles/Viam/AvoidAccessible.yml b/.github/vale/styles/Viam/AvoidAccessible.yml
index 213639eb08..6da656497a 100644
--- a/.github/vale/styles/Viam/AvoidAccessible.yml
+++ b/.github/vale/styles/Viam/AvoidAccessible.yml
@@ -1,6 +1,6 @@
extends: existence
message: "Use accessible only to refer to things that all people, including those with disabilities, can easily use. Don’t use it to mean simple or open."
-link: 'https://docs.rackspace.com/docs/style-guide/terminology/alphabetical-terms'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/terminology/alphabetical-terms.rst'
level: warning
ignorecase: false
nonword: false
diff --git a/.github/vale/styles/Viam/AvoidFirstPerson.yml b/.github/vale/styles/Viam/AvoidFirstPerson.yml
index 6e91028978..b4d5df601e 100644
--- a/.github/vale/styles/Viam/AvoidFirstPerson.yml
+++ b/.github/vale/styles/Viam/AvoidFirstPerson.yml
@@ -2,7 +2,7 @@
extends: existence
message: "Avoid first-person pronouns such as '%s' where possible."
-link: 'https://docs.rackspace.com/docs/style-guide/writing/write-to-the-user/'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/writing/write-to-the-user.rst'
ignorecase: true
level: warning
nonword: true
diff --git a/.github/vale/styles/Viam/AvoidFutureTense.yml b/.github/vale/styles/Viam/AvoidFutureTense.yml
index 0c10b9d5ae..e14f600085 100644
--- a/.github/vale/styles/Viam/AvoidFutureTense.yml
+++ b/.github/vale/styles/Viam/AvoidFutureTense.yml
@@ -3,7 +3,7 @@ extends: existence
message: 'Avoid using future tense where possible.'
ignorecase: true
level: warning
-link: 'https://docs.rackspace.com/docs/style-guide/writing/use-present-tense/'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/writing/use-present-tense.rst'
raw:
- "(going to( |\n|[[:punct:]])[a-zA-Z]*|"
- "will( |\n|[[:punct:]])[a-zA-Z]*|"
diff --git a/.github/vale/styles/Viam/AvoidObscure.yml b/.github/vale/styles/Viam/AvoidObscure.yml
index 830ec70b69..8c29a596c8 100644
--- a/.github/vale/styles/Viam/AvoidObscure.yml
+++ b/.github/vale/styles/Viam/AvoidObscure.yml
@@ -1,6 +1,6 @@
extends: substitution
message: "Use '%s' instead of '%s'."
-link: 'https://docs.rackspace.com/docs/style-guide/terminology/general-term-guidelines/avoid-obscure-words'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/terminology/general-term-guidelines/avoid-obscure-words.rst'
level: error
ignorecase: true
action:
diff --git a/.github/vale/styles/Viam/AvoidPastTense.yml b/.github/vale/styles/Viam/AvoidPastTense.yml
index 9ca518c435..9a4c3dc62a 100644
--- a/.github/vale/styles/Viam/AvoidPastTense.yml
+++ b/.github/vale/styles/Viam/AvoidPastTense.yml
@@ -2,7 +2,7 @@ extends: existence
message: 'Avoid using past tense where possible: "%s".'
ignorecase: true
level: warning
-link: 'https://docs.rackspace.com/docs/style-guide/writing/use-present-tense/'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/writing/use-present-tense.rst'
scope: sentence
tokens:
- abode
diff --git a/.github/vale/styles/Viam/AvoidSubjunctive.yml b/.github/vale/styles/Viam/AvoidSubjunctive.yml
index a501cf0f0a..98ed488613 100644
--- a/.github/vale/styles/Viam/AvoidSubjunctive.yml
+++ b/.github/vale/styles/Viam/AvoidSubjunctive.yml
@@ -1,6 +1,6 @@
extends: existence
message: "Avoid the subjuntive '%s'."
-link: 'https://docs.rackspace.com/docs/style-guide/writing/write-to-the-user/'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/writing/write-to-the-user.rst'
ignorecase: true
level: warning
scope: sentence
diff --git a/.github/vale/styles/Viam/AvoidSupported.yml b/.github/vale/styles/Viam/AvoidSupported.yml
index 56a6d4f227..dac1833f93 100644
--- a/.github/vale/styles/Viam/AvoidSupported.yml
+++ b/.github/vale/styles/Viam/AvoidSupported.yml
@@ -1,7 +1,7 @@
extends: existence
message: "Avoid making claims as to supported software unless we are
tracking how this software evolves."
-link: 'https://docs.rackspace.com/docs/style-guide/terminology/alphabetical-terms'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/terminology/alphabetical-terms.rst'
level: suggestion
ignorecase: false
nonword: true
diff --git a/.github/vale/styles/Viam/AvoidWithSubstitution.yml b/.github/vale/styles/Viam/AvoidWithSubstitution.yml
index d7894444ef..a4cc7273ff 100644
--- a/.github/vale/styles/Viam/AvoidWithSubstitution.yml
+++ b/.github/vale/styles/Viam/AvoidWithSubstitution.yml
@@ -1,6 +1,6 @@
extends: substitution
message: "Consider if '%s' makes sense instead of '%s'."
-link: 'https://docs.rackspace.com/docs/style-guide/terminology/alphabetical-terms'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/terminology/alphabetical-terms.rst'
level: suggestion
ignorecase: true
action:
diff --git a/.github/vale/styles/Viam/Careful.yml b/.github/vale/styles/Viam/Careful.yml
index 00647abd46..4f0ea62409 100644
--- a/.github/vale/styles/Viam/Careful.yml
+++ b/.github/vale/styles/Viam/Careful.yml
@@ -1,6 +1,6 @@
extends: existence
message: "Verify your usage of '%s' with the Alphabetical List of Terms in the style guide."
-link: 'https://docs.rackspace.com/docs/style-guide/terminology/alphabetical-terms'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/terminology/alphabetical-terms.rst'
level: suggestion
ignorecase: true
tokens:
diff --git a/.github/vale/styles/Viam/CommaOxford.yml b/.github/vale/styles/Viam/CommaOxford.yml
index 3638278570..3a0ef6fe26 100644
--- a/.github/vale/styles/Viam/CommaOxford.yml
+++ b/.github/vale/styles/Viam/CommaOxford.yml
@@ -2,7 +2,7 @@
extends: existence
message: "Use the Oxford comma in '%s'."
-link: 'https://docs.rackspace.com/docs/style-guide/style/punctuation#commas'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/punctuation#commas.rst'
level: suggestion
nonword: true
tokens:
diff --git a/.github/vale/styles/Viam/CommaQuotation.yml b/.github/vale/styles/Viam/CommaQuotation.yml
index 8a28619420..c3f35014b2 100644
--- a/.github/vale/styles/Viam/CommaQuotation.yml
+++ b/.github/vale/styles/Viam/CommaQuotation.yml
@@ -1,6 +1,6 @@
extends: existence
message: "When a comma is required after a quotation that’s embedded in text, place the comma inside the closing quotation mark."
-link: 'https://docs.rackspace.com/docs/style-guide/style/punctuation#commas'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/punctuation#commas.rst'
level: error
scope: text
nonword: true
diff --git a/.github/vale/styles/Viam/CommaRestrictiveClause.yml b/.github/vale/styles/Viam/CommaRestrictiveClause.yml
index 64c40c85b8..c5c54aa4bd 100644
--- a/.github/vale/styles/Viam/CommaRestrictiveClause.yml
+++ b/.github/vale/styles/Viam/CommaRestrictiveClause.yml
@@ -1,6 +1,6 @@
extends: existence
message: "Don’t use a comma to set off a restrictive clause (one that begins with that)."
-link: 'https://docs.rackspace.com/docs/style-guide/style/punctuation#commas'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/punctuation#commas.rst'
ignorecase: true
level: suggestion
nonword: true
diff --git a/.github/vale/styles/Viam/ConciseTerms.yml b/.github/vale/styles/Viam/ConciseTerms.yml
index 015ab71a47..636b354ea5 100644
--- a/.github/vale/styles/Viam/ConciseTerms.yml
+++ b/.github/vale/styles/Viam/ConciseTerms.yml
@@ -1,6 +1,6 @@
extends: substitution
message: "'%s' is preferred over '%s'."
-link: 'https://docs.rackspace.com/docs/style-guide/terminology/concise-terms#concise-terms'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/terminology/concise-terms#concise-terms.rst'
level: suggestion
ignorecase: false
action:
diff --git a/.github/vale/styles/Viam/ConsistencyEarlierLater.yml b/.github/vale/styles/Viam/ConsistencyEarlierLater.yml
index 9426e21848..cd7eae5366 100644
--- a/.github/vale/styles/Viam/ConsistencyEarlierLater.yml
+++ b/.github/vale/styles/Viam/ConsistencyEarlierLater.yml
@@ -1,6 +1,6 @@
extends: existence
message: "To refer to product releases, use earlier or later."
-link: 'https://docs.rackspace.com/docs/style-guide/terminology/general-term-guidelines/use-consistent-time-references'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/terminology/general-term-guidelines/use-consistent-time-references.rst'
nonword: false
level: suggestion
tokens:
diff --git a/.github/vale/styles/Viam/ConsistencyFollowingPreceding.yml b/.github/vale/styles/Viam/ConsistencyFollowingPreceding.yml
index 81cf16018f..bc985a8820 100644
--- a/.github/vale/styles/Viam/ConsistencyFollowingPreceding.yml
+++ b/.github/vale/styles/Viam/ConsistencyFollowingPreceding.yml
@@ -1,6 +1,6 @@
extends: existence
message: "If you can't use specific references, use following or preceding to reference an item in text or copy."
-link: 'https://docs.rackspace.com/docs/style-guide/terminology/general-term-guidelines/use-consistent-time-references'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/terminology/general-term-guidelines/use-consistent-time-references.rst'
nonword: false
level: suggestion
tokens:
diff --git a/.github/vale/styles/Viam/Contractions.yml b/.github/vale/styles/Viam/Contractions.yml
index 93f5685c87..3503d2cc4b 100644
--- a/.github/vale/styles/Viam/Contractions.yml
+++ b/.github/vale/styles/Viam/Contractions.yml
@@ -1,6 +1,6 @@
extends: substitution
message: "Feel free to use '%s' instead of '%s'."
-link: 'https://docs.rackspace.com/docs/style-guide/style/contractions'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/contractions.rst'
level: suggestion
ignorecase: true
action:
diff --git a/.github/vale/styles/Viam/ContractionsNegative.yml b/.github/vale/styles/Viam/ContractionsNegative.yml
index 8a9af1d6ee..ee59f46ec2 100644
--- a/.github/vale/styles/Viam/ContractionsNegative.yml
+++ b/.github/vale/styles/Viam/ContractionsNegative.yml
@@ -1,7 +1,7 @@
extends: substitution
message: "Feel free to use '%s' instead of '%s', unless you mean to
emphasize the negative."
-link: 'https://docs.rackspace.com/docs/style-guide/style/contractions'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/contractions.rst'
level: suggestion
ignorecase: true
action:
diff --git a/.github/vale/styles/Viam/Dashes.yml b/.github/vale/styles/Viam/Dashes.yml
index 54e35022b8..1edc43f83b 100644
--- a/.github/vale/styles/Viam/Dashes.yml
+++ b/.github/vale/styles/Viam/Dashes.yml
@@ -1,7 +1,7 @@
# Based on: https://github.com/errata-ai/Google/blob/master/Google/EnDash.yml
extends: existence
message: "Use an em dash ('—') instead of '–' unless this is a compound word."
-link: 'https://docs.rackspace.com/docs/style-guide/style/punctuation#dashes'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/punctuation#dashes.rst'
nonword: true
level: suggestion
action:
diff --git a/.github/vale/styles/Viam/DashesSpaces.yml b/.github/vale/styles/Viam/DashesSpaces.yml
index 0f67a87751..f782d493bc 100644
--- a/.github/vale/styles/Viam/DashesSpaces.yml
+++ b/.github/vale/styles/Viam/DashesSpaces.yml
@@ -1,7 +1,7 @@
# Based on: https://github.com/errata-ai/Microsoft/blob/master/Microsoft/Dashes.yml
extends: existence
message: "Remove whitespace around '%s'."
-link: 'https://docs.rackspace.com/docs/style-guide/style/punctuation#dashes'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/punctuation#dashes.rst'
ignorecase: true
scope: sentence
nonword: true
diff --git a/.github/vale/styles/Viam/Dates.yml b/.github/vale/styles/Viam/Dates.yml
index b537c5a7f4..5246f8ba77 100644
--- a/.github/vale/styles/Viam/Dates.yml
+++ b/.github/vale/styles/Viam/Dates.yml
@@ -1,7 +1,7 @@
# Based on: https://github.com/errata-ai/Microsoft/blob/master/Microsoft/DateFormat.yml
extends: existence
message: "Unless space is limited, use 'November 12, 2010' format, not '%s'."
-link: 'https://docs.rackspace.com/docs/style-guide/style/dates'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/dates.rst'
ignorecase: true
level: error
nonword: true
diff --git a/.github/vale/styles/Viam/DatesCommaMDY.yml b/.github/vale/styles/Viam/DatesCommaMDY.yml
index 09efcf6a9f..bb9662838c 100644
--- a/.github/vale/styles/Viam/DatesCommaMDY.yml
+++ b/.github/vale/styles/Viam/DatesCommaMDY.yml
@@ -1,6 +1,6 @@
extends: existence
message: "Use a comma before and after the year '%s' when the month, day, and year are embedded in a sentence."
-link: 'https://docs.rackspace.com/docs/style-guide/style/dates'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/dates.rst'
ignorecase: true
level: error
nonword: true
diff --git a/.github/vale/styles/Viam/DatesCommaMY.yml b/.github/vale/styles/Viam/DatesCommaMY.yml
index 772377800c..69f0399f43 100644
--- a/.github/vale/styles/Viam/DatesCommaMY.yml
+++ b/.github/vale/styles/Viam/DatesCommaMY.yml
@@ -2,7 +2,7 @@ extends: existence
message: "Do not use a comma before and after the year '%s' when only
the month and year are embedded in a sentence unless the syntax would
ordinarily require a comma following the year."
-link: 'https://docs.rackspace.com/docs/style-guide/style/dates'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/dates.rst'
ignorecase: true
level: warning
nonword: true
diff --git a/.github/vale/styles/Viam/DatesOrdinal.yml b/.github/vale/styles/Viam/DatesOrdinal.yml
index a2b2a7b778..06ee36b5b3 100644
--- a/.github/vale/styles/Viam/DatesOrdinal.yml
+++ b/.github/vale/styles/Viam/DatesOrdinal.yml
@@ -1,6 +1,6 @@
extends: existence
message: "Spell out all ordinal numbers ('%s'). For example, don’t use January 1st; use January 1 instead."
-link: 'https://docs.rackspace.com/docs/style-guide/style/dates'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/dates.rst'
level: error
nonword: true
tokens:
diff --git a/.github/vale/styles/Viam/DomainNames.yml b/.github/vale/styles/Viam/DomainNames.yml
index c88f892d96..f5e9d8143d 100644
--- a/.github/vale/styles/Viam/DomainNames.yml
+++ b/.github/vale/styles/Viam/DomainNames.yml
@@ -1,7 +1,7 @@
extends: conditional
message: "Use *.example.com or *.example.org in example domain names
instead of '%s'."
-link: 'https://docs.rackspace.com/docs/style-guide/style/email-addresses'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/email-addresses.rst'
level: suggestion
ignorecase: false
# This is a hack to allow us to make use of exceptions.
diff --git a/.github/vale/styles/Viam/Email.yml b/.github/vale/styles/Viam/Email.yml
index bdee7512f2..c4af88a2bf 100644
--- a/.github/vale/styles/Viam/Email.yml
+++ b/.github/vale/styles/Viam/Email.yml
@@ -1,7 +1,7 @@
extends: conditional
message: "Use @example.com or @example.org as the domain name for example
email addresses instead of '%s'."
-link: 'https://docs.rackspace.com/docs/style-guide/style/email-addresses'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/email-addresses.rst'
level: suggestion
ignorecase: false
# This is a hack to allow us to make use of exceptions.
diff --git a/.github/vale/styles/Viam/GlobalAudienceIdioms.yml b/.github/vale/styles/Viam/GlobalAudienceIdioms.yml
index 79ce21eef2..4202537d2e 100644
--- a/.github/vale/styles/Viam/GlobalAudienceIdioms.yml
+++ b/.github/vale/styles/Viam/GlobalAudienceIdioms.yml
@@ -1,6 +1,6 @@
extends: substitution
message: "Use '%s' instead of the idiom/colloquialism '%s'."
-link: 'https://docs.rackspace.com/docs/style-guide/terminology/terms-for-global-audience#don-t-use-idioms-or-colloquialisms'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/terminology/terms-for-global-audience#don-t-use-idioms-or-colloquialisms.rst'
level: suggestion
ignorecase: true
action:
diff --git a/.github/vale/styles/Viam/GlobalAudienceJargon.yml b/.github/vale/styles/Viam/GlobalAudienceJargon.yml
index a07f7296f8..f9a39414e4 100644
--- a/.github/vale/styles/Viam/GlobalAudienceJargon.yml
+++ b/.github/vale/styles/Viam/GlobalAudienceJargon.yml
@@ -1,6 +1,6 @@
extends: substitution
message: "Consider using '%s' instead of the jargon '%s'."
-link: 'https://docs.rackspace.com/docs/style-guide/terminology/terms-for-global-audience#use-jargon-carefully'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/terminology/terms-for-global-audience#use-jargon-carefully.rst'
level: suggestion
ignorecase: true
action:
diff --git a/.github/vale/styles/Viam/GlobalAudienceMetaphorical.yml b/.github/vale/styles/Viam/GlobalAudienceMetaphorical.yml
index bbf6d275c0..9f695d6c4a 100644
--- a/.github/vale/styles/Viam/GlobalAudienceMetaphorical.yml
+++ b/.github/vale/styles/Viam/GlobalAudienceMetaphorical.yml
@@ -1,6 +1,6 @@
extends: substitution
message: "Use '%s' instead of the metaphor '%s'."
-link: 'https://docs.rackspace.com/docs/style-guide/terminology/terms-for-global-audience#avoid-metaphorical-terms'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/terminology/terms-for-global-audience#avoid-metaphorical-terms.rst'
level: suggestion
ignorecase: true
action:
diff --git a/.github/vale/styles/Viam/IPAdresses.yml b/.github/vale/styles/Viam/IPAdresses.yml
index b74b44e5a8..749c468678 100644
--- a/.github/vale/styles/Viam/IPAdresses.yml
+++ b/.github/vale/styles/Viam/IPAdresses.yml
@@ -1,6 +1,6 @@
extends: conditional
message: "If you need to show an example IP address like '%s', don’t use one that is or might be assigned to an actual host. Use an address that’s globally defined for documentation."
-link: 'https://docs.rackspace.com/docs/style-guide/style/ip-addresses'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/ip-addresses.rst'
level: suggestion
ignorecase: false
# This is a hack to allow us to make use of exceptions.
diff --git a/.github/vale/styles/Viam/IPv4.yml b/.github/vale/styles/Viam/IPv4.yml
index dace7cd8de..9e2c199f47 100644
--- a/.github/vale/styles/Viam/IPv4.yml
+++ b/.github/vale/styles/Viam/IPv4.yml
@@ -1,6 +1,6 @@
extends: existence
message: "IPv4 addresses should use periods (.) as separators ('%s')."
-link: 'https://docs.rackspace.com/docs/style-guide/style/ip-addresses'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/ip-addresses.rst'
level: error
nonword: true
tokens:
diff --git a/.github/vale/styles/Viam/IPv6.yml b/.github/vale/styles/Viam/IPv6.yml
index 20c9c69c6d..d31d19aefd 100644
--- a/.github/vale/styles/Viam/IPv6.yml
+++ b/.github/vale/styles/Viam/IPv6.yml
@@ -1,6 +1,6 @@
extends: existence
message: "IPv6 addresses should use colons (:) as separators ('%s')."
-link: 'https://docs.rackspace.com/docs/style-guide/style/ip-addresses'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/ip-addresses.rst'
level: error
nonword: true
tokens:
diff --git a/.github/vale/styles/Viam/Interjections.yml b/.github/vale/styles/Viam/Interjections.yml
index 8bdb123806..a300a75987 100644
--- a/.github/vale/styles/Viam/Interjections.yml
+++ b/.github/vale/styles/Viam/Interjections.yml
@@ -2,7 +2,7 @@
extends: existence
message: "Use interjections with care."
-link: 'https://docs.rackspace.com/docs/style-guide/writing/use-interjections-with-care/'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/writing/use-interjections-with-care.rst'
nonword: true
level: warning
tokens:
diff --git a/.github/vale/styles/Viam/NegativeWords.yml b/.github/vale/styles/Viam/NegativeWords.yml
index 69656aa4b1..fe7bf8beb9 100644
--- a/.github/vale/styles/Viam/NegativeWords.yml
+++ b/.github/vale/styles/Viam/NegativeWords.yml
@@ -1,6 +1,6 @@
extends: substitution
message: "Use '%s' instead of the negative word '%s'."
-link: 'https://docs.rackspace.com/docs/style-guide/writing/use-positive-statements'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/writing/use-positive-statements.rst'
level: warning
ignorecase: true
action:
diff --git a/.github/vale/styles/Viam/NoContractions.yml b/.github/vale/styles/Viam/NoContractions.yml
index 895f54e392..6ca11dc1f9 100644
--- a/.github/vale/styles/Viam/NoContractions.yml
+++ b/.github/vale/styles/Viam/NoContractions.yml
@@ -1,6 +1,6 @@
extends: substitution
message: "Use %s instead of the contraction '%s' to avoid confustion."
-link: 'https://docs.rackspace.com/docs/style-guide/style/contractions'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/contractions.rst'
level: suggestion
ignorecase: true
action:
diff --git a/.github/vale/styles/Viam/Numbers.yml b/.github/vale/styles/Viam/Numbers.yml
index 64c4cf55cd..fe72120658 100644
--- a/.github/vale/styles/Viam/Numbers.yml
+++ b/.github/vale/styles/Viam/Numbers.yml
@@ -2,7 +2,7 @@ extends: existence
message: "Spell out numbers like '%s' from zero through nine unless the numers are
as displayed or need to be input, are followed by a unit, or indicate
dimensions or time."
-link: 'https://docs.rackspace.com/docs/style-guide/style/numbers'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/numbers.rst'
ignorecase: true
scope: sentence
level: suggestion
diff --git a/.github/vale/styles/Viam/NumbersCommas.yml b/.github/vale/styles/Viam/NumbersCommas.yml
index 28da60bf4b..62af65047f 100644
--- a/.github/vale/styles/Viam/NumbersCommas.yml
+++ b/.github/vale/styles/Viam/NumbersCommas.yml
@@ -2,7 +2,7 @@ extends: existence
message: "Use commas in '%s' unless it is an address, a fractional part of
a decimal number, a page number, or a literal representation of a
user-entered or displayed value."
-link: 'https://docs.rackspace.com/docs/style-guide/style/numbers'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/numbers.rst'
ignorecase: true
level: suggestion
scope: sentence
diff --git a/.github/vale/styles/Viam/NumbersRanges.yml b/.github/vale/styles/Viam/NumbersRanges.yml
index efdaf0973d..9e05c961aa 100644
--- a/.github/vale/styles/Viam/NumbersRanges.yml
+++ b/.github/vale/styles/Viam/NumbersRanges.yml
@@ -1,7 +1,7 @@
extends: existence
message: "Unless space is limited use either 'from 10 to 20 diagrams' or
'between 2010 and 2020' instead of '%s'."
-link: 'https://docs.rackspace.com/docs/style-guide/style/numbers'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/numbers.rst'
ignorecase: true
level: warning
scope: sentence
diff --git a/.github/vale/styles/Viam/NumbersThrough.yml b/.github/vale/styles/Viam/NumbersThrough.yml
index 724b61e38a..baa6bab6f4 100644
--- a/.github/vale/styles/Viam/NumbersThrough.yml
+++ b/.github/vale/styles/Viam/NumbersThrough.yml
@@ -1,6 +1,6 @@
extends: existence
message: "Don’t use the word inclusive in your description ('%s')."
-link: 'https://docs.rackspace.com/docs/style-guide/style/numbers'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/numbers.rst'
ignorecase: true
level: warning
nonword: true
diff --git a/.github/vale/styles/Viam/PhoneNumbers.yml b/.github/vale/styles/Viam/PhoneNumbers.yml
index 4b3257663f..609837a9c8 100644
--- a/.github/vale/styles/Viam/PhoneNumbers.yml
+++ b/.github/vale/styles/Viam/PhoneNumbers.yml
@@ -2,7 +2,7 @@ extends: existence
message: "Use a space, not a dash or parentheses, to separate parts of the
telephone number. Precede phone numbers with the applicable country code
('%s')."
-link: 'https://docs.rackspace.com/docs/style-guide/style/telephone-numbers'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/telephone-numbers.rst'
nonword: true
level: suggestion
tokens:
diff --git a/.github/vale/styles/Viam/PluralsPossibility.yml b/.github/vale/styles/Viam/PluralsPossibility.yml
index 085c0cf53c..b7bb71cbe0 100644
--- a/.github/vale/styles/Viam/PluralsPossibility.yml
+++ b/.github/vale/styles/Viam/PluralsPossibility.yml
@@ -4,7 +4,7 @@ indicate the possibility of more than one item, and don’t combine the
singular and plural forms of a verb, such as is/are. Use the singular
form or the plural form, use both forms joined by a conjunction, or use
the phrase one or more."
-link: 'https://docs.rackspace.com/docs/style-guide/style/plurals'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/plurals.rst'
ignorecase: false
level: error
nonword: true
diff --git a/.github/vale/styles/Viam/PositiveStatements.yml b/.github/vale/styles/Viam/PositiveStatements.yml
index e006dc1fa1..2a4a9efb45 100644
--- a/.github/vale/styles/Viam/PositiveStatements.yml
+++ b/.github/vale/styles/Viam/PositiveStatements.yml
@@ -1,6 +1,6 @@
extends: existence
message: "Avoid negative statements where possible ('%s')."
-link: 'https://docs.rackspace.com/docs/style-guide/writing/use-positive-statements'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/writing/use-positive-statements.rst'
ignorecase: true
level: suggestion
nonword: true
diff --git a/.github/vale/styles/Viam/Semicolons.yml b/.github/vale/styles/Viam/Semicolons.yml
index f7acd74182..52f628d9cd 100644
--- a/.github/vale/styles/Viam/Semicolons.yml
+++ b/.github/vale/styles/Viam/Semicolons.yml
@@ -1,6 +1,6 @@
extends: existence
message: "Avoid using semicolons, which are often misused and, even when used correctly, can make sentences longer and more difficult to understand."
-link: 'https://docs.rackspace.com/docs/style-guide/writing/use-correct-punctuation'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/writing/use-correct-punctuation.rst'
nonword: true
level: suggestion
tokens:
diff --git a/.github/vale/styles/Viam/SentenceLength.yml b/.github/vale/styles/Viam/SentenceLength.yml
index a077731324..e885101ac1 100644
--- a/.github/vale/styles/Viam/SentenceLength.yml
+++ b/.github/vale/styles/Viam/SentenceLength.yml
@@ -1,6 +1,6 @@
extends: occurrence
message: "Try to keep sentences short (< 25 words)."
-link: 'https://docs.rackspace.com/docs/style-guide/writing/write-clear-concise-sentences-paragraphs'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/writing/write-clear-concise-sentences-paragraphs.rst'
scope: sentence
level: suggestion
max: 25
diff --git a/.github/vale/styles/Viam/Slashes.yml b/.github/vale/styles/Viam/Slashes.yml
index f2bd0812fa..ef8400bffa 100644
--- a/.github/vale/styles/Viam/Slashes.yml
+++ b/.github/vale/styles/Viam/Slashes.yml
@@ -2,7 +2,7 @@ extends: conditional
message: "Don’t use a slash mark (/) to present a choice among, or a
series of, actions or objects ('%s'). Rewrite the phrase to eliminate the
slash mark."
-link: 'https://docs.rackspace.com/docs/style-guide/style/punctuation'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/punctuation.rst'
level: suggestion
ignorecase: true
# This is a hack to allow us to make use of exceptions.
diff --git a/.github/vale/styles/Viam/Time12AM12PM.yml b/.github/vale/styles/Viam/Time12AM12PM.yml
index 3b653b5057..8cecd009da 100644
--- a/.github/vale/styles/Viam/Time12AM12PM.yml
+++ b/.github/vale/styles/Viam/Time12AM12PM.yml
@@ -1,7 +1,7 @@
extends: existence
message: When referring to 12 AM, use 12 midnight or just midnight. When
referring to 12 PM, use 12 noon or just noon ('%s').
-link: 'https://docs.rackspace.com/docs/style-guide/style/time'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/time.rst'
level: error
nonword: true
tokens:
diff --git a/.github/vale/styles/Viam/Time24h2Digits.yml b/.github/vale/styles/Viam/Time24h2Digits.yml
index e13b4f116a..43dd485b26 100644
--- a/.github/vale/styles/Viam/Time24h2Digits.yml
+++ b/.github/vale/styles/Viam/Time24h2Digits.yml
@@ -1,7 +1,7 @@
extends: existence
message: Show the hours, minutes, and seconds with two digits each, even
if the leading digit is 0 ('%s').
-link: 'https://docs.rackspace.com/docs/style-guide/style/time'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/time.rst'
level: error
nonword: true
tokens:
diff --git a/.github/vale/styles/Viam/Time24hTimeZone.yml b/.github/vale/styles/Viam/Time24hTimeZone.yml
index 932305b391..ac4df79678 100644
--- a/.github/vale/styles/Viam/Time24hTimeZone.yml
+++ b/.github/vale/styles/Viam/Time24hTimeZone.yml
@@ -1,6 +1,6 @@
extends: existence
message: If you need to show a time zone ('%s'), use Coordinated Universal Time (UTC), and indicate the time-zone offset from UTC.
-link: 'https://docs.rackspace.com/docs/style-guide/style/time'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/time.rst'
level: error
nonword: true
tokens:
diff --git a/.github/vale/styles/Viam/TimeAMPM.yml b/.github/vale/styles/Viam/TimeAMPM.yml
index 93eeb26a1f..ea5891715c 100644
--- a/.github/vale/styles/Viam/TimeAMPM.yml
+++ b/.github/vale/styles/Viam/TimeAMPM.yml
@@ -4,7 +4,7 @@ extends: existence
message: Use uppercase letters for abbreviations of ante meridiem (AM)
and post meridiem (PM). Separate these abbreviations from the time with
a space. Do not use periods in the abbreviations. ('%s')
-link: 'https://docs.rackspace.com/docs/style-guide/style/time'
+link: 'https://github.com/rackerlabs/docs-style-guide/blob/master/style-guide/style/time.rst'
level: error
nonword: true
tokens:
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index dc4014e1cb..a154a8aef0 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -67,16 +67,10 @@ jobs:
uses: actions/download-artifact@v3
with:
name: tutorials-search-file
- - name: Write env
- run: |
- echo TYPESENSE_API_KEY=${{ secrets.TYPESENSE_API_KEY }} > typesense.env
- echo TYPESENSE_HOST=cgnvrk0xwyj9576lp-1.a1.typesense.net >> typesense.env
- echo TYPESENSE_PORT=443 >> typesense.env
- echo TYPESENSE_PROTOCOL=https >> typesense.env
- name: Upload tutorials documents
run: |
jq -c '.[]' typesense.json > documents.jsonl
- curl -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
+ curl -H "X-TYPESENSE-API-KEY: ${{secrets.TYPESENSE_TUTORIALS_API_KEY}}" \
-X POST \
-T documents.jsonl \
"https://cgnvrk0xwyj9576lp-1.a1.typesense.net/collections/tutorials/documents/import?action=upsert"
diff --git a/.htmltest.yml b/.htmltest.yml
index d5c7a7d820..83f93f5401 100644
--- a/.htmltest.yml
+++ b/.htmltest.yml
@@ -24,6 +24,7 @@ IgnoreURLs:
- "universal-robots.com"
- "digikey.com"
- "ufactory.cc"
+- "medium.com"
IgnoreDirs:
- "lib"
CacheExpires: "6h"
diff --git a/README.md b/README.md
index 4f6c553f23..961950fd9c 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,7 @@
> **Note**
> Looking to contribute? Check out the [Contributor Guide](https://github.com/viamrobotics/docs/blob/main/CONTRIBUTING.md).
+> For help knowing what and how to write, check out our templates: our [tutorial template](docs/tutorials/template/) and [component page template](docs/components/component/) are accessible on the site when building the docs in Draft mode, or accessible here on GitHub.
## Build the docs locally
diff --git a/assets/components/arm/fake-arm-ui-config.png b/assets/components/arm/fake-arm-ui-config.png
index fcabcc6020..c54f3f66d5 100644
Binary files a/assets/components/arm/fake-arm-ui-config.png and b/assets/components/arm/fake-arm-ui-config.png differ
diff --git a/assets/components/board/upboard-ui-config.png b/assets/components/board/upboard-ui-config.png
index 539ab81d30..511ad8dcd1 100644
Binary files a/assets/components/board/upboard-ui-config.png and b/assets/components/board/upboard-ui-config.png differ
diff --git a/assets/components/movement-sensor/visual-odometry-poster.jpg b/assets/components/movement-sensor/visual-odometry-poster.jpg
new file mode 100644
index 0000000000..6af391b40e
Binary files /dev/null and b/assets/components/movement-sensor/visual-odometry-poster.jpg differ
diff --git a/assets/extend/modular-resources/configure/add-module-from-registry.png b/assets/extend/modular-resources/configure/add-module-from-registry.png
new file mode 100644
index 0000000000..3792481cd8
Binary files /dev/null and b/assets/extend/modular-resources/configure/add-module-from-registry.png differ
diff --git a/assets/extend/modular-resources/configure/conf-component-from-module.png b/assets/extend/modular-resources/configure/conf-component-from-module.png
new file mode 100644
index 0000000000..44990a5a82
Binary files /dev/null and b/assets/extend/modular-resources/configure/conf-component-from-module.png differ
diff --git a/assets/extend/modular-resources/configure/conf-module-from-registry.png b/assets/extend/modular-resources/configure/conf-module-from-registry.png
new file mode 100644
index 0000000000..ebd4753672
Binary files /dev/null and b/assets/extend/modular-resources/configure/conf-module-from-registry.png differ
diff --git a/static/js/carousel.js b/assets/js/carousel.js
similarity index 92%
rename from static/js/carousel.js
rename to assets/js/carousel.js
index 78a51e438e..0e9ce894d2 100644
--- a/static/js/carousel.js
+++ b/assets/js/carousel.js
@@ -32,8 +32,10 @@ document.addEventListener('DOMContentLoaded', function() {
});
const scrolllength = carousel.querySelector('ul li:nth-child(2)').offsetLeft - carousel.querySelector('ul li:nth-child(1)').offsetLeft;
const nthchild = (Math.round((ele.scrollLeft/scrolllength)+1));
- carousel.querySelector('ol li:nth-child('+nthchild+')').classList.add('selected');
- carousel.querySelector('ul li:nth-child('+nthchild+')').classList.add('selected');
+ let ol_elem = carousel.querySelector('ol li:nth-child('+nthchild+')');
+ let ul_elem = carousel.querySelector('ul li:nth-child('+nthchild+')');
+ if (ol_elem) { ol_elem.classList.add('selected'); }
+ if (ul_elem) { ul_elem.classList.add('selected'); }
if(carousel.parentElement.parentElement.querySelector('.dynamictitle')) {
const title = carousel.querySelector('ul li:nth-child('+nthchild+') img').getAttribute('title');
if(title) carousel.parentElement.parentElement.querySelector('.dynamictitle').innerHTML = title;
@@ -97,7 +99,7 @@ document.addEventListener('DOMContentLoaded', function() {
}
// Add CSS to hide arrows when all elements visible
- var styles = "@media (min-width:" + (slides.length * 100 + 400) "px) {#board-carousel { padding: 0 !important; }#board-carousel div.prev, #board-carousel div.next {visibility: hidden;}}"
+ var styles = "@media (min-width:" + (slides.length * 100 + 400) + "px) {#board-carousel { padding: 0 !important; }#board-carousel div.prev, #board-carousel div.next {visibility: hidden;}}"
var styleSheet = document.createElement("style")
styleSheet.innerText = styles
diff --git a/assets/js/index.js b/assets/js/index.js
index 1fc6c5ca14..f6de00647e 100644
--- a/assets/js/index.js
+++ b/assets/js/index.js
@@ -97,18 +97,21 @@ if (toc) {
for (var i = 0; i < tocItems.length; i++) {
let item = tocItems[i];
- var targetBounds = item.target.getBoundingClientRect();
-
- if( targetBounds.bottom > windowHeight * TOP_MARGIN && targetBounds.top < windowHeight * ( 1 - BOTTOM_MARGIN ) ) {
- visibleItems += 1;
- item.listItem.classList.add( 'toc-active' );
- atLeastOne = true;
- } else {
- item.listItem.classList.remove( 'toc-active' );
- }
+ if (item.target) {
+
+ var targetBounds = item.target.getBoundingClientRect();
+
+ if( targetBounds.bottom > windowHeight * TOP_MARGIN && targetBounds.top < windowHeight * ( 1 - BOTTOM_MARGIN ) ) {
+ visibleItems += 1;
+ item.listItem.classList.add( 'toc-active' );
+ atLeastOne = true;
+ } else {
+ item.listItem.classList.remove( 'toc-active' );
+ }
- if (targetBounds.bottom < windowHeight) {
- lastElem = item;
+ if (targetBounds.bottom < windowHeight) {
+ lastElem = item;
+ }
}
}
@@ -151,7 +154,7 @@ docsearch({
protocol: 'https'
}],
apiKey: 'GHQK6od8KfpvTEh4YpA113gUc2dU5fGR'
- },
+ }
});
docsearch({
inputSelector: '.td-sidebar__search .td-search-input',
@@ -163,5 +166,5 @@ docsearch({
protocol: 'https'
}],
apiKey: 'GHQK6od8KfpvTEh4YpA113gUc2dU5fGR'
- },
+ }
});
\ No newline at end of file
diff --git a/static/js/tutorials.js b/assets/js/tutorials.js
similarity index 95%
rename from static/js/tutorials.js
rename to assets/js/tutorials.js
index 1981eba0eb..1e7a6ec194 100644
--- a/static/js/tutorials.js
+++ b/assets/js/tutorials.js
@@ -85,7 +85,7 @@ search.addWidgets([
templates: {
item: `
-
+
{{#webm}}
@@ -213,3 +213,13 @@ search.on('render', function() {
observer.observe()
});
+
+document.body.addEventListener('click', function(event) {
+ let filter_box = document.getElementById('tutorial-filter-items');
+ if (!filter_box.contains(event.target)) {
+ open_elem = filter_box.getElementsByClassName("show");
+ if (open_elem) {
+ open_elem[0].classList.remove("show");
+ }
+ }
+}, true);
\ No newline at end of file
diff --git a/assets/scss/_styles_project.scss b/assets/scss/_styles_project.scss
index 4909d5b9a2..ff29366baf 100644
--- a/assets/scss/_styles_project.scss
+++ b/assets/scss/_styles_project.scss
@@ -1183,10 +1183,20 @@ ul.sectionlist > li:hover {
}
.search-facets {
- width: 100%;
+ width: 540px;
border: 1px solid black;
margin: 0.2rem;
padding: 0.2rem;
+ position: absolute;
+ z-index: 1;
+ background-color: white;
+}
+
+@media (max-width: 800px) {
+.search-facets {
+ max-width: 86%;
+ width: 445px;
+}
}
.search-facets > ul {
@@ -1272,6 +1282,12 @@ a.ais-Pagination-link:hover {
text-align: center;
padding: 0;
}
+
+// Speed up bootstraps transition animations
+.search-facets.collapsing {
+ transition-duration: 0.000002s;
+}
+
// Pagination CSS end
// Tutorials page end
@@ -1282,6 +1298,24 @@ a.ais-Pagination-link:hover {
flex-grow: 1;
}
+.ds-dataset-1, .ds-dataset-2, .ds-dataset-3 {
+ max-height: 500px !important;
+}
+
+/* Add margin in front of breadcrumbs on small screens */
+@media (max-height: 600px) {
+ .ds-dataset-1, .ds-dataset-2, .ds-dataset-3 {
+ max-height: 300px !important;
+ }
+}
+
+/* Add margin in front of breadcrumbs on small screens */
+@media (max-height: 400px) {
+ .ds-dataset-1, .ds-dataset-2, .ds-dataset-3 {
+ max-height: 200px !important;
+ }
+}
+
// Search-autocomplete end
// Make videos work without js
@@ -1294,4 +1328,4 @@ a.ais-Pagination-link:hover {
.row.flex-xl-nowrap {
min-height: 100%;
-}
\ No newline at end of file
+}
diff --git a/assets/tutorials/blink-an-led/create-component.png b/assets/tutorials/blink-an-led/create-component.png
deleted file mode 100644
index ae8df69cb7..0000000000
Binary files a/assets/tutorials/blink-an-led/create-component.png and /dev/null differ
diff --git a/assets/tutorials/scuttlebot/createcomponent.png b/assets/tutorials/scuttlebot/createcomponent.png
deleted file mode 100644
index 130f3a4f00..0000000000
Binary files a/assets/tutorials/scuttlebot/createcomponent.png and /dev/null differ
diff --git a/assets/tutorials/scuttlebot/scuttle-on-floor-cropped.png b/assets/tutorials/scuttlebot/scuttle-on-floor-cropped.png
new file mode 100644
index 0000000000..9d433a8e91
Binary files /dev/null and b/assets/tutorials/scuttlebot/scuttle-on-floor-cropped.png differ
diff --git a/assets/tutorials/scuttlebot/scuttle-on-floor.png b/assets/tutorials/scuttlebot/scuttle-on-floor.png
new file mode 100644
index 0000000000..d9cf1413e8
Binary files /dev/null and b/assets/tutorials/scuttlebot/scuttle-on-floor.png differ
diff --git a/docs/_index.md b/docs/_index.md
index 85aeb00072..49af563d6f 100644
--- a/docs/_index.md
+++ b/docs/_index.md
@@ -216,5 +216,3 @@ sitemap:
{{< card link="/tutorials/projects/integrating-viam-with-openai/" class="yellow">}}
-
-
diff --git a/docs/components/arm/fake.md b/docs/components/arm/fake.md
index 3787b34080..aea1c28dde 100644
--- a/docs/components/arm/fake.md
+++ b/docs/components/arm/fake.md
@@ -15,10 +15,9 @@ Configure a `fake` arm to test different models of robotic arms without any phys
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your arm, select the type `arm`, and select the `fake` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `arm` type, then select the `fake` model.
+Enter a name for your arm and click **Create**.
![An example configuration for a fake ur5e arm in the Viam app Config Builder.](/components/arm/fake-arm-ui-config.png)
diff --git a/docs/components/arm/ur5e.md b/docs/components/arm/ur5e.md
index 3beb19af7b..78628ff3bd 100644
--- a/docs/components/arm/ur5e.md
+++ b/docs/components/arm/ur5e.md
@@ -14,10 +14,9 @@ Configure a `ur5e` arm to add a [Universal Robots UR5e](https://www.universal-ro
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your arm, select the type `arm`, and select the `ur5e` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `arm` type, then select the `ur5e` model.
+Enter a name for your arm and click **Create**.
![Web UI configuration panel for an arm of model ur5e in the Viam app, with Attributes & Depends On drop-downs and the option to add a frame.](/components/arm/ur5e-ui-config.png)
diff --git a/docs/components/arm/xarm6.md b/docs/components/arm/xarm6.md
index c8e5ef25a8..e9598db784 100644
--- a/docs/components/arm/xarm6.md
+++ b/docs/components/arm/xarm6.md
@@ -15,10 +15,9 @@ Configure an `xArm6` arm to integrate a [UFACTORY xArm 6](https://www.ufactory.c
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your arm, select the type `arm`, and select the `xArm6` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `arm` type, then select the `xArm6` model.
+Enter a name for your arm and click **Create**.
![Web UI configuration panel for an arm of model xArm6 in the Viam app, with Attributes & Depends On drop-downs and the option to add a frame.](/components/arm/xArm6-ui-config.png)
diff --git a/docs/components/arm/xarm7.md b/docs/components/arm/xarm7.md
index 8423bddc65..1e4813b4e1 100644
--- a/docs/components/arm/xarm7.md
+++ b/docs/components/arm/xarm7.md
@@ -15,10 +15,9 @@ Configure an `xArm7` arm to integrate a [UFACTORY xArm 7](https://www.ufactory.c
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your arm, select the type `arm`, and select the `xArm7` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `arm` type, then select the `xArm7` model.
+Enter a name for your arm and click **Create**.
![Web UI configuration panel for an arm of model xArm6 in the Viam app, with Attributes & Depends On drop-downs and the option to add a frame.](/components/arm/xArm7-ui-config.png)
diff --git a/docs/components/arm/xarmlite.md b/docs/components/arm/xarmlite.md
index a5dfa1fbd4..3d48e26dd3 100644
--- a/docs/components/arm/xarmlite.md
+++ b/docs/components/arm/xarmlite.md
@@ -14,10 +14,9 @@ Configure an `xArmLite` arm to add a [UFACTORY Lite 6](https://www.ufactory.cc/p
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your arm, select the type `arm`, and select the `xArmLite` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `arm` type, then select the `xArmLite` model.
+Enter a name for your arm and click **Create**.
![Web UI configuration panel for an arm of model xArmLite in the Viam app, with Attributes & Depends On drop-downs and the option to add a frame.](/components/arm/xArmLite-ui-config.png)
diff --git a/docs/components/arm/yahboom-dofbot.md b/docs/components/arm/yahboom-dofbot.md
index 49bbf4b85a..c2218212f2 100644
--- a/docs/components/arm/yahboom-dofbot.md
+++ b/docs/components/arm/yahboom-dofbot.md
@@ -14,10 +14,9 @@ Configure a `yahboom-dofbot` arm to add a [Yahboom DOFBOT](https://category.yahb
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your arm, select the type `arm`, and select the `yahboom-dofbot` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `arm` type, then select the `yahboom-dofbot` model.
+Enter a name for your arm and click **Create**.
![Web UI configuration panel for an arm of model yahboom-dofbot in the Viam app, with Attributes & Depends On drop-downs and the option to add a frame.](/components/arm/yahboom-dofbot-ui-config.png)
diff --git a/docs/components/base/agilex-limo.md b/docs/components/base/agilex-limo.md
index 923783a61d..82310d8fdb 100644
--- a/docs/components/base/agilex-limo.md
+++ b/docs/components/base/agilex-limo.md
@@ -17,10 +17,9 @@ Configure an `agilex-limo` base as follows:
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your base, select the type `base`, and select the `agilex-limo` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `base` type, then select the `agilex-limo` model.
+Enter a name for your base and click **Create**.
![An example configuration for a agilex-limo base in the Viam app Config Builder.](/components/base/agilex-limo-ui-config.png)
diff --git a/docs/components/base/boat.md b/docs/components/base/boat.md
index 2406778c53..270478c593 100644
--- a/docs/components/base/boat.md
+++ b/docs/components/base/boat.md
@@ -17,10 +17,11 @@ To configure a `boat` base as a component of your robot, first configure the [bo
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your base, select the type `base`, and select the `boat` model.
+Click on the **Components** subtab and click **Create component**.
+Select the `base` type, then select the `boat` model.
+Enter a name for your base and click **Create**.
-Click **Create component** and then fill in the attributes for your model:
+Edit and fill in the attributes as applicable.
{{% /tab %}}
{{% tab name="JSON Template" %}}
diff --git a/docs/components/base/fake.md b/docs/components/base/fake.md
index 437e8431aa..21bdf4190f 100644
--- a/docs/components/base/fake.md
+++ b/docs/components/base/fake.md
@@ -17,10 +17,9 @@ Configure a `fake` base as follows:
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your base, select the type `base`, and select the `fake` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `base` type, then select the `fake` model.
+Enter a name for your base and click **Create**.
![An example configuration for a fake base in the Viam app Config Builder.](/components/base/fake-base-ui-config.png)
diff --git a/docs/components/base/wheeled.md b/docs/components/base/wheeled.md
index e7a054ff93..e7aa582a9f 100644
--- a/docs/components/base/wheeled.md
+++ b/docs/components/base/wheeled.md
@@ -18,10 +18,9 @@ Configure a `wheeled` base as follows:
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your base, select the type `base`, and select the `wheeled` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `base` type, then select the `wheeled` model.
+Enter a name for your arm and click **Create**.
{{< imgproc src="/components/base/wheeled-base-ui-config.png" alt="An example configuration for a wheeled base in the Viam app config builder, with Attributes & Depends On drop-downs and the option to add a frame." resize="600x" >}}
diff --git a/docs/components/board/beaglebone.md b/docs/components/board/beaglebone.md
index 93c7b006f0..e0cc9e53de 100644
--- a/docs/components/board/beaglebone.md
+++ b/docs/components/board/beaglebone.md
@@ -21,10 +21,9 @@ Configure a `beaglebone` board to integrate [BeagleBoard's BeagleBone AI 64](htt
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your board, select the type `board`, and select the `beaglebone` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `board` type, then select the `beaglebone` model.
+Enter a name for your board and click **Create**.
![An example configuration for a beaglebone board in the Viam app Config Builder.](/components/board/beaglebone-ui-config.png)
diff --git a/docs/components/board/fake.md b/docs/components/board/fake.md
index f0cc96ef1a..9de2ac32e3 100644
--- a/docs/components/board/fake.md
+++ b/docs/components/board/fake.md
@@ -15,10 +15,9 @@ Configure a `fake` board to test integrating a board into your robot without phy
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your board, select the type `board`, and select the `fake` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `board` type, then select the `fake` model.
+Enter a name for your board and click **Create**.
![An example configuration for a fake board in the Viam app Config Builder.](/components/board/fake-ui-config.png)
diff --git a/docs/components/board/jetson.md b/docs/components/board/jetson.md
index 9812233b9c..ed8888602a 100644
--- a/docs/components/board/jetson.md
+++ b/docs/components/board/jetson.md
@@ -13,18 +13,25 @@ tags: ["board", "components"]
Follow one of our Jetson [setup guides](/installation/) to prepare your board for running `viam-server` before configuring a `jetson` board.
+If you have a CSI camera, follow [these instructions](/extend/modular-resources/examples/csi/) to configure it using the `viam:camera:csi` model.
+
+{{% /alert %}}
+
+{{% alert title="CAUTION: Use 3.3V inputs and outputs" color="warning" %}}
+
+The jetson's GPIO pins are rated for inputs and outputs at 3.3V. Signals from encoders and sensors at even 5V can cause damage to a pin. We recommend connecting hardware that can operate and send signals at 3.3V or lower. For details, see pages 1-3 of the [Jetson Nano Developer Kit 40-Pin Expansion Header GPIO Usage Considerations Applications Note](https://developer.nvidia.com/jetson-nano-developer-kit-40-pin-expansion-header-gpio-usage-considerations-applications-note)
+
{{% /alert %}}
-Configure a `jetson` board to integrate a [NVIDIA Jetson Orin Module and Developer Kit](https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/jetson-orin/), [NVIDIA Jetson Xavier NX](https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/jetson-agx-xavier/), or [NVIDIA Jetson Nano](https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/jetson-nano/) into your robot:
+Configure a `jetson` board to integrate a [NVIDIA Jetson Orin Module and Developer Kit](https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/jetson-orin/), [NVIDIA Jetson AGX](https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/jetson-agx-xavier/), or [NVIDIA Jetson Nano](https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/jetson-nano/) into your robot:
{{< tabs name="Configure an jetson Board" >}}
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your board, select the type `board`, and select the `jetson` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `board` type, then select the `jetson` model.
+Enter a name for your board and click **Create**.
![An example configuration for a jetson board in the Viam app Config Builder.](/components/board/jetson-ui-config.png)
diff --git a/docs/components/board/numato.md b/docs/components/board/numato.md
index d462093661..3115f58e65 100644
--- a/docs/components/board/numato.md
+++ b/docs/components/board/numato.md
@@ -16,10 +16,9 @@ Configure a `numato` board to integrate [Numato GPIO Peripheral Modules](https:/
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your board, select the type `board`, and select the `numato` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `board` type, then select the `numato` model.
+Enter a name for your board and click **Create**.
![An example configuration for a numato board in the Viam app Config Builder.](/components/board/numato-ui-config.png)
diff --git a/docs/components/board/pca9685.md b/docs/components/board/pca9685.md
index 9054bd548e..ceec51ee79 100644
--- a/docs/components/board/pca9685.md
+++ b/docs/components/board/pca9685.md
@@ -15,10 +15,9 @@ Configure a `pca9685` board to integrate a [PCA9685 Arduino I2C Inter
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your board, select the type `board`, and select the `pca9685` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `board` type, then select the `pca9685` model.
+Enter a name for your board and click **Create**.
![An example configuration for a pca9685 board in the Viam app Config Builder.](/components/board/pca9685-ui-config.png)
diff --git a/docs/components/board/pi.md b/docs/components/board/pi.md
index 4ee3344f86..aeecf522fe 100644
--- a/docs/components/board/pi.md
+++ b/docs/components/board/pi.md
@@ -21,10 +21,9 @@ Configure a `pi` board to integrate a [Raspberry Pi 4](https://www.raspberrypi.c
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your board, select the type `board`, and select the `pi` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `board` type, then select the `pi` model.
+Enter a name for your board and click **Create**.
![An example board configuration in the app builder UI. The name (local), type (board) and model (pi) are shown. No other attributes are configured.](/tutorials/scuttlebot/board-empty-json.png)
diff --git a/docs/components/board/ti.md b/docs/components/board/ti.md
index 342f81ffb8..27b0901b18 100644
--- a/docs/components/board/ti.md
+++ b/docs/components/board/ti.md
@@ -21,10 +21,9 @@ Configure a `ti` board to integrate a [Texas Instruments TDA4VM](https://devices
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your board, select the type `board`, and select the `ti` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `board` type, then select the `ti` model.
+Enter a name for your board and click **Create**.
![An example configuration for a ti board in the Viam app Config Builder.](/components/board/ti-ui-config.png)
diff --git a/docs/components/board/upboard.md b/docs/components/board/upboard.md
index 25d2f65b65..86100d6d00 100644
--- a/docs/components/board/upboard.md
+++ b/docs/components/board/upboard.md
@@ -23,20 +23,19 @@ Follow [these instructions](https://ubuntu.com/tutorials/install-ubuntu-server)
Follow [these instructions](https://github.com/up-division/pinctrl-upboard) to do so.
This driver stabilizes the [GPIO pin mapping definition](https://github.com/up-board/up-community/wiki/Pinout) on the board to make it identical to that of a [Raspberry Pi](/components/board/pi/).
-
-{{< tabs name="Configure an upboard Board" >}}
+{{% /tab %}}
{{% tab name="JSON Template" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
diff --git a/docs/components/camera/_index.md b/docs/components/camera/_index.md
index 341718727e..90dafc6e33 100644
--- a/docs/components/camera/_index.md
+++ b/docs/components/camera/_index.md
@@ -51,6 +51,13 @@ For configuration information, click on one of the following models:
| [`join_pointclouds`](join-pointclouds/) | Combines the point clouds from multiple camera sources and projects them to be from the point of view of target_frame. |
| [`transform`](transform/) | A pipeline for applying transformations to an input image source. |
+Viam also provides the following camera models as [modular resources](/extend/modular-resources/):
+
+| Model | Description |
+| ----- | ----------- |
+| [`viam:lidar:rplidar`](/extend/modular-resources/examples/rplidar/) | A LIDAR scanning device like the [RPlidar A1](https://www.slamtec.com/en/Lidar/A1). |
+| [`viam:camera:csi`](/extend/modular-resources/examples/csi/) | Camera Serial Interface (CSI) cameras, like [these cameras from E-con Systems](https://www.e-consystems.com/nvidia-jetson-agx-orin-cameras.asp) or [this camera from Seed Technologies](https://www.digikey.com/en/products/detail/seeed-technology-co.,-ltd/114992263/12396924). |
+
## Control your camera with Viam's client SDK libraries
To get started using Viam's SDKs to connect to and control your robot, go to your robot's page on [the Viam app](https://app.viam.com), navigate to the **Code sample** tab, select your preferred programming language, and copy the sample code generated.
diff --git a/docs/components/camera/align-color-depth-extrinsics.md b/docs/components/camera/align-color-depth-extrinsics.md
index 4adda5bc3d..01051ab917 100644
--- a/docs/components/camera/align-color-depth-extrinsics.md
+++ b/docs/components/camera/align-color-depth-extrinsics.md
@@ -15,10 +15,9 @@ Use the intrinsics of the color and depth camera, as well as the extrinsic pose
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your camera, select the type `camera`, and select the `align_color_depth_extrinsics` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `camera` type, then select the `align_color_depth_extrinsics` model.
+Enter a name for your camera and click **Create**.
![Configuration of an align color depth extrinsics view in the Viam app config builder.](/components/camera/configure-align-color-depth-extrinsics.png)
diff --git a/docs/components/camera/align-color-depth-homography.md b/docs/components/camera/align-color-depth-homography.md
index 753f442d8a..a1f7ac9a87 100644
--- a/docs/components/camera/align-color-depth-homography.md
+++ b/docs/components/camera/align-color-depth-homography.md
@@ -15,10 +15,9 @@ When you have a depth image and you need it to overlay on top of a color image e
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your camera, select the type `camera`, and select the `align_color_depth_homography` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `camera` type, then select the `align_color_depth_homography` model.
+Enter a name for your camera and click **Create**.
![Configuration of an align color depth homography view in the Viam app config builder.](/components/camera/configure-align-color-depth-homography.png)
diff --git a/docs/components/camera/dual-stream.md b/docs/components/camera/dual-stream.md
index 8a3527eed9..ae8519ff89 100644
--- a/docs/components/camera/dual-stream.md
+++ b/docs/components/camera/dual-stream.md
@@ -16,10 +16,9 @@ One camera server streams a color stream and the other camera server streams a d
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your camera, select the type `camera`, and select the `dual_stream` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `camera` type, then select the `dual_stream` model.
+Enter a name for your camera and click **Create**.
![Configuration of a dual stream camera in the Viam app config builder.](/components/camera/configure-dual-stream.png)
diff --git a/docs/components/camera/fake.md b/docs/components/camera/fake.md
index e3770b4240..546600c48f 100644
--- a/docs/components/camera/fake.md
+++ b/docs/components/camera/fake.md
@@ -19,10 +19,9 @@ You can optionally specify a height and width.
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your camera, select the type `camera`, and select the `fake` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `camera` type, then select the `fake` model.
+Enter a name for your camera and click **Create**.
![Configuration of a fake camera in the Viam app config builder.](/components/camera/configure-fake.png)
diff --git a/docs/components/camera/ffmpeg.md b/docs/components/camera/ffmpeg.md
index a43463467b..a0ceb8d208 100644
--- a/docs/components/camera/ffmpeg.md
+++ b/docs/components/camera/ffmpeg.md
@@ -15,10 +15,9 @@ A `ffmpeg` camera uses a camera, a video file, or a stream as a camera.
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your camera, select the type `camera`, and select the `ffmpeg` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `camera` type, then select the `ffmpeg` model.
+Enter a name for your camera and click **Create**.
![Configuration of a ffmpeg camera in the Viam app config builder.](/components/camera/configure-ffmpeg.png)
diff --git a/docs/components/camera/image-file.md b/docs/components/camera/image-file.md
index 8c8c136e7f..e555a82b72 100644
--- a/docs/components/camera/image-file.md
+++ b/docs/components/camera/image-file.md
@@ -15,10 +15,9 @@ An `image_file` camera gets color and depth image frames or point clouds from a
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your camera, select the type `camera`, and select the `image_file` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `camera` type, then select the `image_file` model.
+Enter a name for your camera and click **Create**.
![Configuration of an image file camera in the Viam app config builder.](/components/camera/configure-image-file.png)
diff --git a/docs/components/camera/join-color-depth.md b/docs/components/camera/join-color-depth.md
index f421776c04..5bd6d3a0ef 100644
--- a/docs/components/camera/join-color-depth.md
+++ b/docs/components/camera/join-color-depth.md
@@ -18,10 +18,9 @@ If you need to adjust the alignment between the depth and color frames, use the
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your camera, select the type `camera`, and select the `join_color_depth` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `camera` type, then select the `join_color_depth` model.
+Enter a name for your camera and click **Create**.
![Configuration of a join color depth view in the Viam app config builder.](/components/camera/configure-join-color-depth.png)
diff --git a/docs/components/camera/join-pointclouds.md b/docs/components/camera/join-pointclouds.md
index c530c26315..3e640a785f 100644
--- a/docs/components/camera/join-pointclouds.md
+++ b/docs/components/camera/join-pointclouds.md
@@ -15,10 +15,9 @@ Combine the point clouds from multiple camera sources and project them to be fro
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your camera, select the type `camera`, and select the `join_pointclouds` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `camera` type, then select the `join_pointclouds` model.
+Enter a name for your camera and click **Create**.
![Configuration of a Join Point Clouds view in the Viam App config builder.](/components/camera/configure-join-pointclouds.png)
diff --git a/docs/components/camera/rtsp.md b/docs/components/camera/rtsp.md
index 057232b494..4da43932a8 100644
--- a/docs/components/camera/rtsp.md
+++ b/docs/components/camera/rtsp.md
@@ -16,10 +16,9 @@ The model doesn’t support streaming cameras with H264/MP4 tracks.
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your camera, select the type `camera`, and select the `rtsp` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `camera` type, then select the `rtsp` model.
+Enter a name for your camera and click **Create**.
![Configuration of a rtsp camera in the Viam app config builder.](/components/camera/configure-rtsp.png)
diff --git a/docs/components/camera/single-stream.md b/docs/components/camera/single-stream.md
index 1bc5c752de..c734ec25de 100644
--- a/docs/components/camera/single-stream.md
+++ b/docs/components/camera/single-stream.md
@@ -25,10 +25,9 @@ Your `single_stream` camera can output:
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your camera, select the type `camera`, and select the `single_stream` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `camera` type, then select the `single_stream` model.
+Enter a name for your camera and click **Create**.
![Configuration of a single stream camera in the Viam App config builder.](/components/camera/configure-single-stream.png)
diff --git a/docs/components/camera/transform.md b/docs/components/camera/transform.md
index edad6e2dca..55999a2686 100644
--- a/docs/components/camera/transform.md
+++ b/docs/components/camera/transform.md
@@ -16,10 +16,9 @@ The transformations are applied in the order they are written in the `pipeline`.
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your camera, select the type `camera`, and select the `transform` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `camera` type, then select the `transform` model.
+Enter a name for your camera and click **Create**.
![Configuration of an transform view in the Viam app config builder.](/components/camera/configure-transform.png)
diff --git a/docs/components/camera/velodyne.md b/docs/components/camera/velodyne.md
index 6c14473e79..671153b4be 100644
--- a/docs/components/camera/velodyne.md
+++ b/docs/components/camera/velodyne.md
@@ -16,10 +16,9 @@ The velodyne must be running locally at address `127.0.0.1`.
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your camera, select the type `camera`, and select the `velodyne` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `camera` type, then select the `velodyne` model.
+Enter a name for your camera and click **Create**.
{{< imgproc src="/components/camera/configure-velodyne.png" alt="Configuration of a velodyne camera in the Viam app config builder." resize="600x" >}}
diff --git a/docs/components/camera/webcam.md b/docs/components/camera/webcam.md
index cb4e49b03e..9a414b842f 100644
--- a/docs/components/camera/webcam.md
+++ b/docs/components/camera/webcam.md
@@ -16,10 +16,9 @@ If the camera drivers are among those in [this mediadevices repository](https://
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your camera, select the type `camera`, and select the `webcam` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `camera` type, then select the `webcam` model.
+Enter a name for your camera and click **Create**.
{{< imgproc src="/components/camera/configure-webcam.png" alt="Configuration of a webcam camera in the Viam app config builder." resize="600x" >}}
diff --git a/docs/components/component/model1.md b/docs/components/component/model1.md
index df53db7386..5dd335d92a 100644
--- a/docs/components/component/model1.md
+++ b/docs/components/component/model1.md
@@ -21,9 +21,13 @@ Click on the **Components** subtab and navigate to the **Create component** menu
Enter a name for your arm, select the `arm` type, and select the `model1` model.
+Click on the **Components** subtab and click **Create component**.
+Select the `arm` type, then select the `model1` model.
+Enter a name for your arm and click **Create**.
+
{{< imgproc src="/components/component/model1-builder.png" alt="Creation of a `model1` arm in the Viam app config builder." resize="600x" >}}
-Click **Create component** and then fill in the attributes for your model.
+Edit and fill in the attributes as applicable.
{{% /tab %}}
{{% tab name="JSON Template" %}}
diff --git a/docs/components/encoder/AMS-AS5048.md b/docs/components/encoder/AMS-AS5048.md
index d6b2cdd9c8..97419b3044 100644
--- a/docs/components/encoder/AMS-AS5048.md
+++ b/docs/components/encoder/AMS-AS5048.md
@@ -21,10 +21,9 @@ To configure the encoder, you must first [configure an I2C bus](/comp
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your encoder, select the type `encoder`, and select the `AMS-AS5048` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `encoder` type, then select the `AMS-AS5048` model.
+Enter a name for your encoder and click **Create**.
![Configuration of an AS5048 encoder in the Viam app config builder.](/components/encoder/configure-am5.png)
diff --git a/docs/components/encoder/arduino.md b/docs/components/encoder/arduino.md
index 8308ca6ca5..306357a852 100644
--- a/docs/components/encoder/arduino.md
+++ b/docs/components/encoder/arduino.md
@@ -13,10 +13,9 @@ draft: true
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your encoder, select the type `encoder`, and select the `arduino` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `encoder` type, then select the `arduino` model.
+Enter a name for your encoder and click **Create**.
![Configuration of an Arduino encoder in the Viam app config builder.](/components/encoder/configure-arduino.png)
diff --git a/docs/components/encoder/fake.md b/docs/components/encoder/fake.md
index b5c7151777..1584625031 100644
--- a/docs/components/encoder/fake.md
+++ b/docs/components/encoder/fake.md
@@ -15,10 +15,9 @@ The `fake` encoder is an encoder model for testing code without any hardware.
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your encoder, select the type `encoder`, and select the `fake` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `encoder` type, then select the `fake` model.
+Enter a name for your encoder and click **Create**.
![Configuration of a fake encoder in the Viam app config builder.](/components/encoder/configure-fake.png)
diff --git a/docs/components/encoder/incremental.md b/docs/components/encoder/incremental.md
index 44842f0f1e..9d14f9b714 100644
--- a/docs/components/encoder/incremental.md
+++ b/docs/components/encoder/incremental.md
@@ -17,10 +17,9 @@ These two pins provide the phase outputs used to measure the speed and direction
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your encoder, select the type `encoder`, and select the `incremental` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `encoder` type, then select the `incremental` model.
+Enter a name for your encoder and click **Create**.
![Configuration of an incremental encoder in the Viam app config builder.](/components/encoder/configure-incremental.png)
diff --git a/docs/components/encoder/single.md b/docs/components/encoder/single.md
index 71a433fd93..7f948420a1 100644
--- a/docs/components/encoder/single.md
+++ b/docs/components/encoder/single.md
@@ -15,10 +15,9 @@ The direction of spin is dictated by the [motor](/components/motor/) that has th
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your encoder, select the type `encoder`, and select the `single` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `encoder` type, then select the `single` model.
+Enter a name for your encoder and click **Create**.
![Configuration of a single encoder in the Viam app config builder.](/components/encoder/configure-single.png)
diff --git a/docs/components/gantry/fake.md b/docs/components/gantry/fake.md
index 5e31f2ef71..cba4e5939a 100644
--- a/docs/components/gantry/fake.md
+++ b/docs/components/gantry/fake.md
@@ -18,10 +18,9 @@ Configure a `fake` gantry as follows:
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your gantry, select the type `gantry`, and select the `fake` model.
-
-Click **Create component**:
+Click on the **Components** subtab and click **Create component**.
+Select the `gantry` type, then select the `fake` model.
+Enter a name for your gantry and click **Create**.
![An example configuration for a fake gantry in the Viam app Config Builder.](/components/gantry/fake-gantry-ui-config.png)
diff --git a/docs/components/gantry/multi-axis.md b/docs/components/gantry/multi-axis.md
index b194da7359..46cfcaaf1e 100644
--- a/docs/components/gantry/multi-axis.md
+++ b/docs/components/gantry/multi-axis.md
@@ -17,10 +17,9 @@ Configure a `multi-axis` gantry to integrate a multi-axis gantry into your robot
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your gantry, select the type `gantry`, and select the `multi-axis` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `gantry` type, then select the `multi-axis` model.
+Enter a name for your gantry and click **Create**.
![Creation of a multi-axis gantry component in the Viam app config builder.](/components/gantry/multi-axis-ui-config.png)
diff --git a/docs/components/gantry/single-axis.md b/docs/components/gantry/single-axis.md
index 1b4bceec6e..2dcfcc51d0 100644
--- a/docs/components/gantry/single-axis.md
+++ b/docs/components/gantry/single-axis.md
@@ -17,10 +17,9 @@ Configure a `single-axis` gantry to integrate a single-axis gantry into your rob
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your sensor, select the type `gantry`, and select the `single-axis` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `gantry` type, then select the `single-axis` model.
+Enter a name for your sensor and click **Create**.
![Creation of a single-axis gantry component in the Viam app config builder.](/components/gantry/single-axis-ui-config.png)
diff --git a/docs/components/gripper/fake.md b/docs/components/gripper/fake.md
index 639e7c62fd..0a7274d000 100644
--- a/docs/components/gripper/fake.md
+++ b/docs/components/gripper/fake.md
@@ -18,10 +18,9 @@ Configure a `fake` gripper as follows:
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your gripper, select the type `gripper`, and select the `fake` model.
-
-Click **Create component**:
+Click on the **Components** subtab and click **Create component**.
+Select the `gripper` type, then select the `fake` model.
+Enter a name for your gripper and click **Create**.
![An example configuration for a fake gripper in the Viam app Config Builder.](/components/gripper/fake-gripper-ui-config.png)
diff --git a/docs/components/gripper/softrobotics.md b/docs/components/gripper/softrobotics.md
index d2658a075c..3107f8d4e8 100644
--- a/docs/components/gripper/softrobotics.md
+++ b/docs/components/gripper/softrobotics.md
@@ -13,10 +13,9 @@ The `softrobotics` model supports the [Soft Robotics *m*Grip](https://www.softro
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your gripper, select the type `gripper`, and select the `softrobotics` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `gripper` type, then select the `softrobotics` model.
+Enter a name for your gripper and click **Create**.
![Creation of a softrobotics gripper component in the Viam app config builder.](/components/gripper/softrobotics-ui-config.png)
diff --git a/docs/components/input-controller/fake.md b/docs/components/input-controller/fake.md
index 0eef9a29b0..acd0561f7a 100644
--- a/docs/components/input-controller/fake.md
+++ b/docs/components/input-controller/fake.md
@@ -22,9 +22,9 @@ Refer to the following example configuration for an input controller of model `f
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your input controller, select the type `input_controller`, and select the `fake` model.
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `input_controller` type, then select the `fake` model.
+Enter a name for your input controller and click **Create**.
![An example configuration for a fake input controller component in the Viam App config builder.](/components/input-controller/fake-input-controller-ui-config.png)
diff --git a/docs/components/input-controller/gamepad.md b/docs/components/input-controller/gamepad.md
index 651a697cdf..c9ccad182e 100644
--- a/docs/components/input-controller/gamepad.md
+++ b/docs/components/input-controller/gamepad.md
@@ -20,10 +20,9 @@ Refer to the following example configuration for an input controller of model `g
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your input controller, select the type `input_controller`, and select the `gamepad` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `input_controller` type, then select the `gamepad` model.
+Enter a name for your input controller and click **Create**.
![An example configuration for a linux-based gamepad input controller component in the Viam App config builder](/components/input-controller/gamepad-input-controller-ui-config.png)
diff --git a/docs/components/input-controller/gpio.md b/docs/components/input-controller/gpio.md
index aa15424717..8d93d79270 100644
--- a/docs/components/input-controller/gpio.md
+++ b/docs/components/input-controller/gpio.md
@@ -21,10 +21,9 @@ Be aware that complete configuration is not visible in the "Config Builder" tab:
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your input controller, select the type `input_controller`, and select the `gpio` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `input_controller` type, then select the `gpio` model.
+Enter a name for your input controller and click **Create**.
![An example configuration for a GPIO input controller component in the Viam App config builder](/components/input-controller/gpio-input-controller-ui-config.png)
diff --git a/docs/components/input-controller/mux.md b/docs/components/input-controller/mux.md
index 27ec518874..582f1db147 100644
--- a/docs/components/input-controller/mux.md
+++ b/docs/components/input-controller/mux.md
@@ -25,10 +25,9 @@ The following example configuration combines a `gamepad` and a `webgamepad` cont
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your input controller, select the type `input_controller`, and select the `mux` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `input_controller` type, then select the `mux` model.
+Enter a name for your input controller and click **Create**.
![An example configuration for a multiplexed input controller component in the Viam App config builder](/components/input-controller/mux-input-controller-ui-config.png)
diff --git a/docs/components/input-controller/webgamepad.md b/docs/components/input-controller/webgamepad.md
index 4037f3b557..01ddb8c1b0 100644
--- a/docs/components/input-controller/webgamepad.md
+++ b/docs/components/input-controller/webgamepad.md
@@ -24,10 +24,9 @@ Use the following configuration for an input controller of model `webgamepad`:
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter the `WebGamepad` name for your input controller, select the type `input_controller`, and select the `webgamepad` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `input_controller` type, then select the `webgamepad` model.
+Enter the name `WebGamepad` and click **Create**.
![An example configuration for a web-based gamepad input controller component in the Viam App config builder](/components/input-controller/webgamepad-input-controller-ui-config.png)
diff --git a/docs/components/motor/28byj48.md b/docs/components/motor/28byj48.md
index 22b46b8e38..01ce9702fe 100644
--- a/docs/components/motor/28byj48.md
+++ b/docs/components/motor/28byj48.md
@@ -25,10 +25,9 @@ Then, add the motor:
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your motor, select the type `motor`, and select the `28byj48` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `motor` type, then select the `28byj48` model.
+Enter a name for your motor and click **Create**.
![A 28byj48 motor config.](/components/motor/28byj48-config-ui.png)
diff --git a/docs/components/motor/dmc4000.md b/docs/components/motor/dmc4000.md
index 01aae207fd..c910367a28 100644
--- a/docs/components/motor/dmc4000.md
+++ b/docs/components/motor/dmc4000.md
@@ -20,10 +20,9 @@ You can drive other types of motors with Viam and the DMC-40x0 controller by [cr
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your motor, select the type `motor`, and select the `DMC4000` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `motor` type, then select the `DMC4000` model.
+Enter a name for your motor and click **Create**.
![A DMC4000 motor config with the attributes configured per the Raw JSON on the next tab in this doc.](/components/motor/dmc4000-config-ui.png)
diff --git a/docs/components/motor/fake.md b/docs/components/motor/fake.md
index 2cfcb73183..35955cafb9 100644
--- a/docs/components/motor/fake.md
+++ b/docs/components/motor/fake.md
@@ -15,10 +15,9 @@ For example, you can use a `fake` component as a placeholder while waiting on a
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your motor, select the type `motor`, and select the `fake` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `motor` type, then select the `fake` model.
+Enter a name for your motor and click **Create**.
![A fake motor config.](/components/motor/fake-config-ui.png)
diff --git a/docs/components/motor/gpio/_index.md b/docs/components/motor/gpio/_index.md
index a79ed786d5..e3dedd9e17 100644
--- a/docs/components/motor/gpio/_index.md
+++ b/docs/components/motor/gpio/_index.md
@@ -20,10 +20,9 @@ Then add your motor:
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your motor, select the type `motor`, and select the `gpio` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `motor` type, then select the `gpio` model.
+Enter a name for your motor and click **Create**.
![G P I O motor config in the builder UI with the In1 and In2 pins configured and the PWM pin field left blank.](/components/motor/gpio-config-ui.png)
diff --git a/docs/components/motor/gpiostepper.md b/docs/components/motor/gpiostepper.md
index bbef05d009..39ff50161d 100644
--- a/docs/components/motor/gpiostepper.md
+++ b/docs/components/motor/gpiostepper.md
@@ -21,10 +21,9 @@ Then, add the motor:
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your motor, select the type `motor`, and select the `gpiostepper` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `motor` type, then select the `gpiostepper` model.
+Enter a name for your motor and click **Create**.
![Screenshot of a gpiostepper motor config with the step and dir pins configured to pins 13 and 15.](/components/motor/gpiostepper-config-ui.png)
diff --git a/docs/components/motor/roboclaw.md b/docs/components/motor/roboclaw.md
index 411b09e160..9b828be133 100644
--- a/docs/components/motor/roboclaw.md
+++ b/docs/components/motor/roboclaw.md
@@ -25,10 +25,9 @@ To configure a `roboclaw` motor as a component of your robot:
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your motor, select the type `motor`, and select the `roboclaw` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `motor` type, then select the `roboclaw` model.
+Enter a name for your motor and click **Create**.
![A roboclaw motor config.](/components/motor/roboclaw-ui-config.png)
diff --git a/docs/components/motor/tmc5072.md b/docs/components/motor/tmc5072.md
index 5a83c360ea..f6e3432c14 100644
--- a/docs/components/motor/tmc5072.md
+++ b/docs/components/motor/tmc5072.md
@@ -19,10 +19,9 @@ Then, add the motor:
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your motor, select the type `motor`, and select the `TMC5072` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `motor` type, then select the `TMC5072` model.
+Enter a name for your motor and click **Create**.
![Config panel for a TMC5072 motor with attributes filled in according to the Raw JSON tab.](/components/motor/tmc5072-config-ui.png)
diff --git a/docs/components/movement-sensor/_index.md b/docs/components/movement-sensor/_index.md
index e86223619d..30afb17e20 100644
--- a/docs/components/movement-sensor/_index.md
+++ b/docs/components/movement-sensor/_index.md
@@ -36,8 +36,10 @@ Model | Description
[`imu-wit`](./imu/imu-wit/) | IMUs manufactured by [WitMotion](https://witmotion-sensor.com/)
[`imu-vectornav`](./imu/imu-wit/) | IMUs manufactured by [VectorNav](https://www.vectornav.com/products)
[`accel-adxl345`](./adxl345/) | The [Analog Devices ADXL345](https://www.analog.com/en/products/adxl345.html) digital accelerometer
+[`viam_visual_odometry`](./viam-visual-odometry/) | A [modular resource](/extend/modular-resources/) that derives movement data from a [camera](/components/camera/) stream
[`gyro-mpu6050`](./mpu6050/) | A gyroscope/accelerometer manufactured by TDK InvenSense
[`merged`](./merged/) | A model that allows you to aggregate the API methods supported by multiple sensors into a singular sensor client, effectively merging the models of the individual resources
+[`wheeled-odometry`](./wheeled-odometry/) | A model that uses [encoders](/components/encoder/) to get an odometry estimate from a wheeled base
[`fake`](./fake/) | Used to test code without hardware
## Control your movement sensor with Viam's client SDK libraries
diff --git a/docs/components/movement-sensor/cameramono.md b/docs/components/movement-sensor/cameramono.md
index 884036698f..173f931f69 100644
--- a/docs/components/movement-sensor/cameramono.md
+++ b/docs/components/movement-sensor/cameramono.md
@@ -24,10 +24,9 @@ The `camera_mono` model can use any single [camera](/components/camera/) within
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your movement sensor, select the `movement-sensor` type, and select the `camera_mono` model.
-
-Click **Create Component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `movement-sensor` type, then select the `camera_mono` model.
+Enter a name for your movement sensor and click **Create**.
{{< imgproc src="/components/movement-sensor/camera-mono-builder.png" alt="Creation of an `camera_mono` movement sensor in the Viam app config builder." resize="600x" >}}
diff --git a/docs/components/movement-sensor/fake.md b/docs/components/movement-sensor/fake.md
index 17f3ed50ee..d5797fc432 100644
--- a/docs/components/movement-sensor/fake.md
+++ b/docs/components/movement-sensor/fake.md
@@ -17,10 +17,9 @@ Note that this model does not get any actual readings, so it supports these meth
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your movement sensor, select the `movement-sensor` type, and select the `fake` model.
-
-Click **Create Component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `movement-sensor` type, then select the `fake` model.
+Enter a name for your movement sensor and click **Create**.
{{< imgproc src="/components/movement-sensor/fake-builder.png" alt="Creation of an `fake` movement sensor in the Viam app config builder." resize="600x" >}}
diff --git a/docs/components/movement-sensor/gps/gps-nmea-rtk-pmtk.md b/docs/components/movement-sensor/gps/gps-nmea-rtk-pmtk.md
index dd536e1a39..812953a3df 100644
--- a/docs/components/movement-sensor/gps/gps-nmea-rtk-pmtk.md
+++ b/docs/components/movement-sensor/gps/gps-nmea-rtk-pmtk.md
@@ -35,10 +35,9 @@ If your movement sensor uses serial communication instead of I
2C, use
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your movement sensor, select the `movement-sensor` type, and select the `gps-nmea-rtk-pmtk` model.
-
-Click **Create Component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `movement-sensor` type, then select the `gps-nmea-rtk-pmtk` model.
+Enter a name for your movement sensor and click **Create**.
{{< imgproc src="/components/movement-sensor/gps-nmea-rtk-pmtk-builder.png" alt="Creation of a `gps-nmea-rtk-pmtk` movement sensor in the Viam app config builder." resize="600x" >}}
diff --git a/docs/components/movement-sensor/gps/gps-nmea-rtk-serial.md b/docs/components/movement-sensor/gps/gps-nmea-rtk-serial.md
index fe89be6498..b194c52f56 100644
--- a/docs/components/movement-sensor/gps/gps-nmea-rtk-serial.md
+++ b/docs/components/movement-sensor/gps/gps-nmea-rtk-serial.md
@@ -38,10 +38,9 @@ If your movement sensor uses I
2C communication instead of serial, use
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your movement sensor, select the `movement-sensor` type, and select the `gps-nmea-rtk-serial` model.
-
-Click **Create Component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `movement-sensor` type, then select the `gps-nmea-rtk-serial` model.
+Enter a name for your movement sensor and click **Create**.
{{< imgproc src="/components/movement-sensor/gps-nmea-rtk-serial-builder.png" alt="Creation of a `gps-nmea-rtk-serial` movement sensor in the Viam app config builder." resize="600x" >}}
diff --git a/docs/components/movement-sensor/gps/gps-nmea.md b/docs/components/movement-sensor/gps/gps-nmea.md
index d9b3257c38..dd4496668e 100644
--- a/docs/components/movement-sensor/gps/gps-nmea.md
+++ b/docs/components/movement-sensor/gps/gps-nmea.md
@@ -21,10 +21,9 @@ The `gps-nmea` model can be connected using USB and send data through a serial c
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your movement sensor, select the `movement-sensor` type, and select the `gps-nmea` model.
-
-Click **Create Component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `movement-sensor` type, then select the `gps-nmea` model.
+Enter a name for your movement sensor and click **Create**.
{{< imgproc src="/components/movement-sensor/gps-nmea-builder.png" alt="Creation of a `gps-nmea` movement sensor in the Viam app config builder." resize="600x" >}}
@@ -127,13 +126,14 @@ You can use either serial communication (over USB) or I
2C communicati
Use `connection_type` to specify `"serial"` or `"I2C"` connection in the main `attributes` config.
Then create a struct within `attributes` for either `serial_attributes` or `i2c_attributes`, respectively.
+See examples of this struct in the example tabs above.
{{< tabs >}}
{{% tab name="Serial" %}}
### Serial Config Attributes
-For a movement sensor communicating over serial, you'll need to include a `serial_attributes` field containing:
+For a movement sensor communicating over serial, you'll need to include a `serial_attributes` struct containing:
Name | Type | Inclusion | Description
---- | ---- | --------- | -----------
@@ -145,7 +145,7 @@ Name | Type | Inclusion | Description
### I2C Config Attributes
-For a movement sensor communicating over I
2C, you'll need a `i2c_attributes` field containing:
+For a movement sensor communicating over I
2C, you'll need a `i2c_attributes` struct containing:
Name | Type | Inclusion | Description
---- | ---- | --------- | -----------
diff --git a/docs/components/movement-sensor/imu/imu-vectornav.md b/docs/components/movement-sensor/imu/imu-vectornav.md
index ea69508c40..500b46af55 100644
--- a/docs/components/movement-sensor/imu/imu-vectornav.md
+++ b/docs/components/movement-sensor/imu/imu-vectornav.md
@@ -17,10 +17,9 @@ The `imu-vectornav` movement sensor model supports IMUs manufactured by [VectorN
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your movement sensor, select the `movement-sensor` type, and select the `imu-vectornav` model.
-
-Click **Create Component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `movement-sensor` type, then select the `imu-vectornav` model.
+Enter a name for your movement sensor and click **Create**.
{{< imgproc src="/components/movement-sensor/imu-vectornav-builder.png" alt="Creation of an `imu-vectornav` movement sensor in the Viam app config builder." resize="600x" >}}
diff --git a/docs/components/movement-sensor/imu/imu-wit.md b/docs/components/movement-sensor/imu/imu-wit.md
index 2aeb3eb357..d7525d8c51 100644
--- a/docs/components/movement-sensor/imu/imu-wit.md
+++ b/docs/components/movement-sensor/imu/imu-wit.md
@@ -27,10 +27,9 @@ Other WitMotion IMUs that communicate over serial may also work with this model
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your movement sensor, select the `movement-sensor` type, and select the `imu-wit` model.
-
-Click **Create Component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `movement-sensor` type, then select the `imu-wit` model.
+Enter a name for your movement sensor and click **Create**.
{{< imgproc src="/components/movement-sensor/imu-wit-builder.png" alt="Creation of an `imu-wit` movement sensor in the Viam app config builder." resize="600x" >}}
diff --git a/docs/components/movement-sensor/merged.md b/docs/components/movement-sensor/merged.md
index fdf6f27267..496d5f67e9 100644
--- a/docs/components/movement-sensor/merged.md
+++ b/docs/components/movement-sensor/merged.md
@@ -24,10 +24,9 @@ Reference the `name` you configure for each individual component in the `merged`
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your movement sensor, select the `movement-sensor` type, and select the `merged` model.
-
-Click **Create Component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `movement-sensor` type, then select the `merged` model.
+Enter a name for your movement sensor and click **Create**.
{{< imgproc src="/components/movement-sensor/merged-config-builder.png" alt="Creation of an `merged` movement sensor in the Viam app config builder." resize="600x" >}}
diff --git a/docs/components/movement-sensor/mpu6050.md b/docs/components/movement-sensor/mpu6050.md
index 2c17a9d727..83122827fc 100644
--- a/docs/components/movement-sensor/mpu6050.md
+++ b/docs/components/movement-sensor/mpu6050.md
@@ -14,10 +14,9 @@ The `gyro-mpu6050` movement sensor model supports a combination [gyroscope and a
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your movement sensor, select the `movement-sensor` type, and select the `gyro-mpu6050` model.
-
-Click **Create Component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `movement-sensor` type, then select the `gyro-mpu6050` model.
+Enter a name for your movement sensor and click **Create**.
{{< imgproc src="/components/movement-sensor/mpu6050-builder.png" alt="Creation of an `gyro-mpu6050` movement sensor in the Viam app config builder." resize="600x" >}}
diff --git a/docs/components/movement-sensor/viam-visual-odometry.md b/docs/components/movement-sensor/viam-visual-odometry.md
new file mode 100644
index 0000000000..13295a7a29
--- /dev/null
+++ b/docs/components/movement-sensor/viam-visual-odometry.md
@@ -0,0 +1,253 @@
+---
+title: "Configure Visual Odometry"
+linkTitle: "viam-visual-odometry"
+weight: 40
+type: "docs"
+description: "Configure viam-visual-odometry, a modular resource that derives movement data from a camera."
+images: ["/icons/components/imu.svg"]
+katex: true
+# SMEs: Robin In
+---
+
+Viam provides a `viam-visual-odometry` [modular resource](/extend/modular-resources/) which uses monocular [visual odometry](https://en.wikipedia.org/wiki/Visual_odometry) to enable any [calibrated camera](/components/camera/calibrate/) to function as a movement sensor.
+In this way, you can add basic movement sensing to your camera-equipped robot without needing a dedicated hardware [movement sensor](/components/movement-sensor/).
+
+
+{{
+
+The `viam-visual-odometry` module implements the following two methods of the [movement sensor API](/components/movement-sensor/#api):
+
+* [`GetLinearVelocity()`](/components/movement-sensor/#getlinearvelocity)
+* [`GetAngularVelocity()`](/components/movement-sensor/#getangularvelocity)
+
+Note that `GetLinearVelocity()` returns an estimation of the instantaneous linear velocity **without scale factor**.
+Therefore, you should not consider returned unit measurements trustworthy: instead, `GetLinearVelocity()` should serve as a direction estimation only.
+
+While `viam-visual-odometry` enables you to add movement sensing abilities to your robot without needing specialized hardware, a dedicated [movement sensor](/components/movement-sensor/) will generally provide more accurate readings.
+If your robot requires precise awareness of its location and its movement, you should consider using a dedicated movement sensor in addition to the `viam-visual-odometry` module.
+
+The `viam-visual-odometry` module is available [from the Viam Registry](https://app.viam.com/module/viam/monocular-visual-odometry).
+See [Modular resources](/extend/modular-resources/#the-viam-registry) for instructions on using a module from the Viam Registry on your robot.
+
+The source code for this module is available on the [`viam-visual-odometry` GitHub repository](https://github.com/viamrobotics/viam-visual-odometry).
+
+## Requirements
+
+Follow the instructions below to download and set up the `viam-visual-odometry` module on your robot:
+
+1. Clone the [`viam-visual-odometry`](https://github.com/viamrobotics/viam-visual-odometry) to your system:
+
+ ```sh {class="command-line" data-prompt="$"}
+ git clone git@github.com:viamrobotics/viam-visual-odometry.git
+ cd viam-visual-odometry
+ ```
+
+1. Install the necessary Python dependencies:
+
+ ```sh {class="command-line" data-prompt="$"}
+ pip install -r requirements.txt
+ ```
+
+1. If you haven't already, [install `viam-server`](/installation/) on your robot.
+
+## Configuration
+
+To configure the `viam-visual-odometry` module on your robot, follow the instructions below:
+
+{{< tabs >}}
+{{% tab name="Config Builder" %}}
+
+1. Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
+1. Click on the **Components** subtab and find the **Create component** pane.
+1. Enter a name for your camera, select the `camera` type, and select the `webcam` model.
+1. Click **Create Component**.
+1. In the resulting `camera` component configuration pane, select a **Video path** for your camera.
+ If your robot is live, the drop-down menu auto-populates any identified camera stream paths.
+1. Switch to the **Modules** subtab and find the **Add module** pane.
+1. Enter a name for your visual odometry module, and provide the full path to the `run.sh` file in the **Executable path** field, then click **Add module**.
+1. Switch back to the **Components** subtab and find the **Create component** pane.
+1. Enter a name for your odometry movement sensor, select the `movement_sensor` type, and enter `viam:visual_odometry:opencv_orb` for `model`, then click **Create component**.
+1. In the resulting `movement_sensor` component configuration pane, paste the following configuration into the **Attributes** text window:
+
+ ```json {class="line-numbers linkable-line-numbers"}
+ {
+ "camera_name": "
",
+ "time_between_frames_s": ,
+ "lowe_ratio_threshold":
+ }
+ ```
+
+ Provide the same camera name as you used in step 3.
+ See the [Attributes](#attributes) section for more information on the other attributes.
+
+1. Click **Save config** at the bottom of the page.
+
+{{% /tab %}}
+{{% tab name="JSON Template" %}}
+
+```json {class="line-numbers linkable-line-numbers"}
+{
+ "modules": [
+ {
+ "name": "",
+ "executable_path": "",
+ "type": "local"
+ }
+ ],
+ "components": [
+ {
+ "name": "",
+ "type": "camera",
+ "model": "webcam",
+ "attributes": {
+ "video_path": "",
+ "height_px": ,
+ "width_px": ,
+ "intrinsic_parameters": {
+ "ppx": ,
+ "ppy": ,
+ "fx": ,
+ "fy":
+ },
+ "distortion_parameters": {
+ "rk3": ,
+ "tp1": ,
+ "tp2": ,
+ "rk1": ,
+ "rk2":
+ }
+ },
+ "depends_on": []
+ },
+ {
+ "name": "",
+ "type": "movement_sensor",
+ "namespace": "rdk",
+ "model": "viam:visual_odometry:opencv_orb",
+ "attributes": {
+ "camera_name": "",
+ "time_between_frames_s": ,
+ "lowe_ratio_threshold":
+ },
+ "depends_on": []
+ }
+ ]
+}
+```
+
+{{% /tab %}}
+{{% tab name="JSON Example" %}}
+
+```json {class="line-numbers linkable-line-numbers"}
+{
+ "modules": [
+ {
+ "name": "my-odometry-module",
+ "executable_path": "/path/to/run.sh",
+ "type": "local"
+ }
+ ],
+ "components": [
+ {
+ "name": "my-camera",
+ "type": "camera",
+ "model": "webcam",
+ "attributes": {
+ "video_path": "FDF90FEB-59E5-4FCF-AABD-DA03C4E19BFB",
+ "height_px": 720,
+ "width_px": 1280,
+ "intrinsic_parameters": {
+ "ppx": 446,
+ "ppy": 585,
+ "fx": 1055,
+ "fy": 1209
+ },
+ "distortion_parameters": {
+ "rk3": -0.03443,
+ "tp1": 0.01364798,
+ "tp2": -0.0107569,
+ "rk1": -0.1621,
+ "rk2": 0.13632
+ }
+ },
+ "depends_on": []
+ },
+ {
+ "name": "my_movement_sensor",
+ "type": "movement_sensor",
+ "namespace": "rdk",
+ "model": "viam:visual_odometry:opencv_orb",
+ "attributes": {
+ "camera_name": "my-camera",
+ "time_between_frames_s": 0.2,
+ "lowe_ratio_threshold": 0.75
+ },
+ "depends_on": []
+ }
+ ]
+}
+```
+
+{{% /tab %}}
+{{< /tabs >}}
+
+## Camera calibration
+
+Once you have configured a `camera` component, you need to calibrate it.
+Because the `viam-visual-odometry` module performs visual odometry calculations, its visual data source (the camera) must be as well defined as possible.
+These calibration steps ensure that the video stream data that reaches the module is as uniform as possible when calculating measurements.
+
+1. Follow the [Calibrate a camera](/components/camera/calibrate/) procedure to generate the required intrinsic parameters specific to your camera.
+1. Copy the resulting intrinsics data into your robot configuration, either in the **Config builder** or in the **Raw JSON**.
+ See the JSON Example tab above for an example intrinsics configuration.
+
+Camera calibration results should look similar to the following example, with readings specific to your camera:
+
+Example output:
+
+```json {class="line-numbers linkable-line-numbers"}
+"intrinsic_parameters": {
+ "fy": 940.2928257873841,
+ "height_px": 480,
+ "ppx": 320.6075282958033,
+ "ppy": 239.14408757087756,
+ "width_px": 640,
+ "fx": 939.2693584627577
+},
+"distortion_parameters": {
+ "rk2": 0.8002516496932317,
+ "rk3": -5.408034254951954,
+ "tp1": -0.000008996658362365533,
+ "tp2": -0.002828504714921335,
+ "rk1": 0.046535971648456166
+}
+```
+
+{{% alert title="Copy calibration data" color="note" %}}
+When you copy the calibration results into your `camera` component configuration, be sure to provide these values to the correct attributes in the target `camera` configuration.
+Specifically, note that the `height_px` and `width_px` attributes are not contained within the `intrinsic_parameters` array in the `camera` configuration, but are located outside of it.
+{{% /alert %}}
+
+## Attributes
+
+The following attributes are available to configure the `viam-visual-odometry` module:
+
+| Name | Type | Inclusion | Default | Description |
+| ---- | ---- | --------- | --------| ------------ |
+| `camera_name` | string | **Required** | | Camera name to be used for inferring the motion. |
+| `time_between_frames_s` | float | Optional | `0.1` | Target time between two successive frames, in seconds. Depending on the inference time and the time to get an image, the sleeping time after each inference will be auto-tuned to reach this target. Additionally, if the time between two successive frame is 5x larger than `time_between_frames_s`, another frame will be requested. This value depends on the speed of your system.|
+|`orb_n_features`| int | Optional | `10000` | Maximum number of features to retain. |
+|`orb_edge_threshold`| int | Optional | `31` | Size of the border where the features are not detected. It should roughly match the `orb_patch_size` attribute. |
+|`orb_patch_size`| int | Optional | `31` | Size of the patch used by the oriented BRIEF descriptor.|
+|`orb_n_levels`| int | Optional | `8` |Number of pyramid levels.|
+|`orb_first_level`| int | Optional | `0` |Level of pyramid to put source image into.|
+|`orb_fast_threshold`| int | Optional | `20` | Fast threshold. |
+|`orb_scale_factor`| float | Optional | `1.2` | Pyramid decimation ratio, greater than 1. |
+|`orb_WTA_K`| int | Optional | `2` | Number of points that produce each element of the oriented BRIEF descriptor. |
+|`matcher`| string | Optional | `"flann"` | Either `"flann"` for [FLANN based matcher](https://docs.opencv.org/3.4/d5/d6f/tutorial_feature_flann_matcher.html) or `"BF"` for brute force matcher. The FLANN matcher will look for the two best matches using the KNN method so Lowe's ratio test can be performed afterward. The [brute force matcher](https://docs.opencv.org/4.x/dc/dc3/tutorial_py_matcher.html) uses Hamming norm. |
+|`lowe_ratio_threshold`| float | Optional | `0.8` | Threshold value to check if the best match is significantly better than the second best match. This value will not be used if brute force matcher is chosen. |
+| `ransac_prob` | float | Optional | `0.99` | Probability to find a subset without outliers in it. Defines the number of iterations to filter the outliers. The number of iterations is roughly given by `$k = \frac{\log(1-p)}{\log(1-w^n)}$`, where `$n$` is the number of points and `$w$` is the ratio of inliers to total points.|
+| `ransac_threshold_px` | float | Optional | `0.5` | Maximum error to be classified as an inlier.|
+
+See the [ORB openCV documentation](https://docs.opencv.org/3.4/db/d95/classcv_1_1ORB.html) for more details.
diff --git a/docs/components/movement-sensor/wheeled-odometry.md b/docs/components/movement-sensor/wheeled-odometry.md
new file mode 100644
index 0000000000..0e7d40f571
--- /dev/null
+++ b/docs/components/movement-sensor/wheeled-odometry.md
@@ -0,0 +1,64 @@
+---
+title: "Configure a wheeled-odometry movement sensor"
+linkTitle: "wheeled-odometry"
+type: "docs"
+description: "Configure a wheeled-odometry movement sensor."
+images: ["/icons/components/imu.svg"]
+tags: ["movement sensor", "components", "encoder", "motor", "base", "wheeled", "odometry"]
+# SMEs: Rand, Martha
+---
+
+Configure a `wheeled-odometry` movement sensor to implement _wheeled odometry_ on your robot.
+
+_Wheeled odometry_ is the estimation of the rate of change of position, orientation, linear velocity, and angular velocity using the dimensions of a base, calculated by measuring the movement of the motors through encoders.
+Because of this method of estimation, you don't have to have a specific piece of movement sensor hardware to implement `wheeled-odometry` on your robot.
+This model uses [encoders](/components/encoder/) from [position reporting motors](/components/motor/) to get an odometry estimate of a wheeled base as it moves.
+
+With a configured `wheeled-odometry` movement sensor, your robot calculates an estimation of the position, orientation, linear velocity, and angular velocity of the wheeled base each time `time_interval_msec` elapses during a [session](/program/apis/sessions/).
+You can access these readings through the [movement sensor API](/components/movement-sensor/#api).
+For the best accuracy with odometry calculations, it is recommended you configure a time interval of less than `1000` milliseconds.
+
+After configuring a `wheeled-odometry` movement sensor, you can operate your base with Viam's built-in services like the [navigation service](/services/navigation/).
+
+## Set-up requirements
+
+To prepare your robot, attach [encoders](/components/encoder/) to each of the position-reporting motors on your base to measure their rotation.
+
+- Select motors that can report their own position, like an encoded [`roboclaw`](/components/motor/roboclaw/) or [`gpio` motors](/components/motor/gpio/) with [encoders](/components/encoder/#configuration), or the [`odrive`](/extend/modular-resources/examples/odrive/) module.
+You can access this property of a configured motor through the [motor API's `GetProperties()`](/components/motor/#getproperties).
+- Configure your rover as a [wheeled base component](/components/base/wheeled/).
+Make sure to configure the base width and circumference, as these measurements as a property of the base are vital for accurate odometry estimations by your movement sensor. This movement sensor accesses these values through the base's `GetProperties()` API method.
+- Configure each of the position-reporting motors [as motor components](/components/motor/).
+- Then, proceed to [configure](#configuration) a `wheeled-odometry` movement sensor with the name of each of the motor components.
+
+## Configuration
+
+Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
+Click on the **Components** subtab and navigate to the **Create component** menu.
+Select **Raw JSON** mode.
+Copy and paste the following:
+
+```json {class="line-numbers linkable-line-numbers"}
+"name" : "",
+"type" : "movement_sensor",
+"model" : "wheeled-odometry",
+"attributes" : {
+ "base" : "",
+ "left_motors" : ["", ""],
+ "right_motors" : [""],
+ "time-interval-msec":
+}
+```
+
+Fill in and edit the attributes as applicable.
+
+## Attributes
+
+The following attributes are available for `wheeled-odometry` movement sensors:
+
+| Name | Type | Inclusion | Description |
+| ---- | ---- | --------- | ----------- |
+| `base` | string | **Required** | The `name` of the [base](/components/base/) to which the encoders making up this movement sensor are wired. |
+| `left_motors` | object | **Required** | A list containing the name of each of the bases' left [position-reporting motors](/components/motor/gpio/). |
+| `right_motors` | object | **Required** | A list containing the name of each of the bases' right [position-reporting motors](/components/motor/gpio/). |
+| `time_interval_msec` | number | Optional | The time in milliseconds between each wheeled odometry calculation.
Default: `500.0` |
diff --git a/docs/components/sensor/bme280.md b/docs/components/sensor/bme280.md
index a0a25ba0e2..cea9299084 100644
--- a/docs/components/sensor/bme280.md
+++ b/docs/components/sensor/bme280.md
@@ -16,10 +16,9 @@ Configure a `bme280` sensor to integrate a [BME280 environmental sensor](https:/
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your sensor, select the type `sensor`, and select the `bme280` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `sensor` type, then select the `bme280` model.
+Enter a name for your sensor and click **Create**.
![Creation of a bme280 sensor in the Viam app config builder.](/components/sensor/bme280-sensor-ui-config.png)
diff --git a/docs/components/sensor/ds18b20.md b/docs/components/sensor/ds18b20.md
index 49a42abd0a..da6bc7dffe 100644
--- a/docs/components/sensor/ds18b20.md
+++ b/docs/components/sensor/ds18b20.md
@@ -16,10 +16,9 @@ Configure a `ds18b20` sensor to integrate a [DallasTemperature DS18B20 1-wire di
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your sensor, select the type `sensor`, and select the `ds18b20` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `sensor` type, then select the `ds18b20` model.
+Enter a name for your sensor and click **Create**.
![Creation of a ds18b20 sensor in the Viam app config builder.](/components/sensor/ds18b20-sensor-ui-config.png)
diff --git a/docs/components/sensor/fake.md b/docs/components/sensor/fake.md
index 8bba8ce805..fdba3cec96 100644
--- a/docs/components/sensor/fake.md
+++ b/docs/components/sensor/fake.md
@@ -18,9 +18,9 @@ Configure a `fake` sensor as follows:
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your sensor, select the type `sensor`, and select the `fake` model.
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `sensor` type, then select the `fake` model.
+Enter a name for your sensor and click **Create**.
![An example configuration for a fake sensor in the Viam app Config Builder. Attributes are left blank.](/components/sensor/fake-sensor-ui-config.png)
diff --git a/docs/components/sensor/power_ina219.md b/docs/components/sensor/power_ina219.md
index 697dc73f4f..58a7e13ba7 100644
--- a/docs/components/sensor/power_ina219.md
+++ b/docs/components/sensor/power_ina219.md
@@ -17,10 +17,9 @@ Configure a `power_ina219` sensor to integrate a [INA219 current sensor](https:/
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your sensor, select the type `sensor`, and select the `power_ina219` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `sensor` type, then select the `power_ina219` model.
+Enter a name for your sensor and click **Create**.
![Creation of a power_ina219 sensor in the Viam app config builder.](/components/sensor/power-ina219-sensor-ui-config.png)
diff --git a/docs/components/sensor/renogy.md b/docs/components/sensor/renogy.md
index a251db6a8c..1abf644c18 100644
--- a/docs/components/sensor/renogy.md
+++ b/docs/components/sensor/renogy.md
@@ -16,10 +16,9 @@ Configure a `renogy` sensor to integrate a [Renogy battery temperature sensor](h
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your sensor, select the type `sensor`, and select the `renogy` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `sensor` type, then select the `renogy` model.
+Enter a name for your sensor and click **Create**.
![Creation of a renogy sensor in the Viam app config builder.](/components/sensor/renogy-sensor-ui-config.png)
diff --git a/docs/components/sensor/sensirion-sht3xd.md b/docs/components/sensor/sensirion-sht3xd.md
index e3cb514e5b..0a721bca96 100644
--- a/docs/components/sensor/sensirion-sht3xd.md
+++ b/docs/components/sensor/sensirion-sht3xd.md
@@ -16,10 +16,9 @@ Configure a `sensirion-sht3xd` sensor to integrate a [Sensirion SHT3x-DIS temper
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your sensor, select the type `sensor`, and select the `sensirion-sht3xd` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `sensor` type, then select the `sensirion-sht3xd` model.
+Enter a name for your sensor and click **Create**.
![Creation of a sensirion-sht3xd sensor in the Viam app config builder.](/components/sensor/sensirion-sht3xd-sensor-ui-config.png)
diff --git a/docs/components/sensor/ultrasonic.md b/docs/components/sensor/ultrasonic.md
index 4bd377b64f..f5a8f183ce 100644
--- a/docs/components/sensor/ultrasonic.md
+++ b/docs/components/sensor/ultrasonic.md
@@ -16,10 +16,9 @@ Configure an `ultrasonic` sensor to integrate an [HC-S204 ultrasonic distance se
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your sensor, select the type `sensor`, and select the `ultrasonic` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `sensor` type, then select the `ultrasonic` model.
+Enter a name for your sensor and click **Create**.
![Creation of a ultrasonic sensor in the Viam app config builder.](/components/sensor/ultrasonic-sensor-ui-config.png)
diff --git a/docs/components/servo/fake.md b/docs/components/servo/fake.md
index 75d49f8c8f..124b717d96 100644
--- a/docs/components/servo/fake.md
+++ b/docs/components/servo/fake.md
@@ -17,10 +17,9 @@ Configure a `fake` servo as follows:
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your servo, select the type `servo`, and select the `fake` model.
-
-Click **Create component**:
+Click on the **Components** subtab and click **Create component**.
+Select the `servo` type, then select the `fake` model.
+Enter a name for your servo and click **Create**.
![An example configuration for a fake servo in the Viam app Config Builder.](/components/servo/fake-servo-ui-config.png)
diff --git a/docs/components/servo/gpio.md b/docs/components/servo/gpio.md
index 57a096e214..9a43d765a9 100644
--- a/docs/components/servo/gpio.md
+++ b/docs/components/servo/gpio.md
@@ -15,10 +15,9 @@ Configure a `gpio` servo to integrate a hobby servo controlled by general-purpos
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your servo, select the type `servo`, and select the `gpio` model.
-
-Click **Create component**:
+Click on the **Components** subtab and click **Create component**.
+Select the `servo` type, then select the `gpio` model.
+Enter a name for your servo and click **Create**.
![An example configuration for a gpio servo in the Viam app Config Builder.](/components/servo/gpio-servo-ui-config.png)
diff --git a/docs/components/servo/pi.md b/docs/components/servo/pi.md
index 8d7221e04a..6e15b6d8c1 100644
--- a/docs/components/servo/pi.md
+++ b/docs/components/servo/pi.md
@@ -21,10 +21,9 @@ Configure a `pi` servo to integrate a hobby servo controlled by general-purpose
{{% tab name="Config Builder" %}}
Navigate to the **config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your servo, select the type `servo`, and select the `pi` model.
-
-Click **Create component**:
+Click on the **Components** subtab and click **Create component**.
+Select the `servo` type, then select the `pi` model.
+Enter a name for your servo and click **Create**.
{{< imgproc src="/components/servo/pi-servo-ui-config.png" alt="An example configuration for a pi servo in the Viam app Config Builder." resize="600x" >}}
diff --git a/docs/extend/_index.md b/docs/extend/_index.md
index 2e68bdc505..d5c618c8ab 100644
--- a/docs/extend/_index.md
+++ b/docs/extend/_index.md
@@ -1,26 +1,24 @@
---
-title: "Extend Viam with custom resources"
+title: "Extend Viam with modular resources"
linkTitle: "Extend Viam"
weight: 63
simple_list: true
no_list: true
type: docs
tags: ["server", "rdk", "extending viam", "modular resources", "components", "services"]
-description: "Use the SDKs to extend Viam with custom components and services."
+description: "Extend Viam with modular resources from the Viam Registry."
aliases:
- "/program/extend/"
---
Viam's [Robot Development Kit (RDK)](/internals/rdk/) provides built-in support for a variety of {{< glossary_tooltip term_id="resource" text="resources" >}}:
-- Various types and models of hardware [components](/components/).
+- Various types of hardware [components](/components/).
- High-level functionality exposed as [services](/services/).
-However, you may want to use a hardware component to build your robot that is not built-in to the RDK.
-Alternatively, you might want to add new functionality to an existing model of component or create a custom service for your robot to use.
-You can extend Viam in these and other ways by creating and using custom resources.
+However, if you want to work with a new hardware component that is not already supported by Viam, or want to introduce a new software service or service model to support additional functionality on your robot, you can extend Viam by adding a {{< glossary_tooltip term_id="module" text="modular resource" >}} to your robot.
-Click on the cards below for instructions on implementing custom resources through {{< glossary_tooltip term_id="module" text="modules" >}} or {{< glossary_tooltip term_id="remote" text="remotes" >}}:
+Click on the cards below for instructions on implementing modular resources through {{< glossary_tooltip term_id="module" text="modules" >}} or {{< glossary_tooltip term_id="remote" text="remotes" >}}:
{{< cards >}}
{{% card link="/extend/modular-resources" %}}
diff --git a/docs/extend/modular-resources/_index.md b/docs/extend/modular-resources/_index.md
index 4c02378e0c..97e28d9249 100644
--- a/docs/extend/modular-resources/_index.md
+++ b/docs/extend/modular-resources/_index.md
@@ -4,31 +4,70 @@ linkTitle: "Modular Resources"
weight: 10
type: "docs"
tags: ["server", "rdk", "extending viam", "modular resources", "components", "services"]
-description: "Use the Viam module system to implement custom resources that can be included in any Viam-powered robot."
+description: "Use the Viam module system to implement modular resources that can be included in any Viam-powered robot."
no_list: true
aliases:
- "/program/extend/modular-resources/"
---
-The Viam module system allows you to integrate custom {{< glossary_tooltip term_id="resource" text="resources" >}} into any robot running on Viam.
-`viam-server` [manages](/extend/modular-resources/key-concepts/) modular resources and built-in resources in the same way.
+At Viam, a robot is configured with one or more {{< glossary_tooltip term_id="resource" text="resources" >}} ([components](/components/) or [services](/services/)) which are each defined by a [public API](/extend/modular-resources/key-concepts/#valid-apis-to-implement-in-your-model).
+While Viam offers a number of built-in implementations against these APIs, such as the [wheeled base](/components/base/wheeled/), you may also write your own implementations in order to extend the capabilities of your robot.
-Modular resources can be:
+For example, you can:
-1. New models of built-in [components](/components/) or [services](/services/) that implement the built-in resource {{< glossary_tooltip term_id="subtype" text="subtype" >}}'s API through Viam's [client SDKs](/program/apis/).
-2. Brand new types of resources that define their own API in [protocol buffers](https://developers.google.com/protocol-buffers).
+- **Implement a custom component:** If your robot has specialty hardware, such as an unsupported [motor](/components/motor/), and you want to control it using Viam, you can write a driver to support your hardware by implementing the corresponding component API.
+
+- **Implement a custom service:** If your robot makes use of a specialty algorithm or data model when working with services such as [SLAM](/services/slam/), [Vision](/services/vision/), or [Motion planning](/services/motion/), you can implement your own algorithm or model against the corresponding service API.
+
+- **Implement fully custom logic:** If your robot runs specialty or proprietary logic, and you want to use Viam to manage and control that logic, such as when managing a software development lifecyle, you can implement your own custom logic by wrapping the generic API.
+
+These custom implementations are called {{< glossary_tooltip term_id="module" text="modular resources" >}}, and are made available for use on a robot through [modules](/extend/modular-resources/key-concepts/#modules).
+A module can provide one or more modular resources, and can be added to your robot from the Viam Registry.
+
+## The Viam Registry
+
+The [Viam Registry](https://app.viam.com/registry) allows hardware and software engineers to collaborate on their robotics projects by writing and sharing custom modules with each other.
+You can add a module from the Viam Registry directly from your robot's **Configuration** tab in [the Viam app](https://app.viam.com/), using the **+ Create component** button.
+
+The code behind any modular resource can be packaged as a [module](/extend/modular-resources/key-concepts/#modules) and uploaded to the Viam Registry.
+Once the module has been uploaded to the Registry, you can [deploy the module](/extend/modular-resources/configure/) to any robot in your organization from [the Viam app](https://app.viam.com/).
+
+### Uploading to Viam Registry
+
+After you finish programming your module, you can [upload your module to the Viam Registry](/extend/modular-resources/upload/) to make it available for deployment to robots.
+As part of the upload process, you decide whether your module is *public* (visible to all users) or *private* (visible only to other members of your [organization](/manage/fleet/organizations/)).
+
+You can see details about each module in [the Viam Registry](https://app.viam.com/registry) on its module details page.
+See the [Odrive module](https://app.viam.com/module/viam/odrive) for an example.
+Public modules also display the number of times a module has been deployed to a robot.
+
+When you make changes to your module, you can [uploaded the newer version](/extend/modular-resources/upload/#update-an-existing-module) with a new version number, and the Viam Registry will track each version that you upload.
+
+### Deploying to a Robot
+
+Once you [upload a module to the Viam Registry](/extend/modular-resources/upload/), you can [deploy the module](/extend/modular-resources/configure/) to any robot in your organization from [the Viam app](https://app.viam.com/).
+Navigate to your robot's **Configuration** tab, click the **+ Create component** button, then start typing the name of the module you would like to deploy.
+If you uploaded your module and set its visibility to private, the module will only appear for users within your [organization](/manage/fleet/organizations/).
+
+When you deploy a module to your robot, you can [choose how to update that module](/extend/modular-resources/configure/#configure-version-update-management-for-a-registry-module) when new versions become available.
## Get Started
-To get started adding custom resources to your robot, learn the [key concepts](/extend/modular-resources/key-concepts/) behind Viam's resource APIs that make the module system possible.
+To get started working with modular resources:
+
+- Learn the [key concepts](/extend/modular-resources/key-concepts/) behind Viam's modular resources that make the module system possible.
+
+- [Create your own module](/extend/modular-resources/create/) implementing at least one modular resource.
+
+- [Upload your module to the Viam Registry](/extend/modular-resources/upload/) to share with the community, or just to your own organization.
-- To create your own module and modular resources, follow [these instructions](/extend/modular-resources/create/).
+- Browse [the Viam Registry](https://app.viam.com/registry) to see modules uploaded by other users.
-- To download modules and add modular resources that other users have built to your robot, follow one of Viam's [module setup guides](/extend/modular-resources/examples/).
+- [Deploy a module](/extend/modular-resources/configure/) to your robot from the Registry.
-- To configure a module and modular resource, follow [these instructions](/extend/modular-resources/configure/).
+- Browse the [modular resources tutorials](/extend/modular-resources/examples/) for examples of deploying and using custom modular resources on your robot.
-Once you have configured a modular resource, you can test the custom resource using the [Control tab](/manage/fleet/#remote-control) and [program](/program/) it with Viam's Go or Python SDKs.
+Once you have deployed a modular resource, you can test the custom resource using the [Control tab](/manage/fleet/#remote-control) and [program](/program/) it with Viam's Go or Python SDKs.
## Related tutorials
diff --git a/docs/extend/modular-resources/configure.md b/docs/extend/modular-resources/configure.md
index c3975ec043..4ead43ea07 100644
--- a/docs/extend/modular-resources/configure.md
+++ b/docs/extend/modular-resources/configure.md
@@ -1,30 +1,170 @@
---
-title: "Configure your module and modular resource"
+title: "Configure a module on your robot"
linkTitle: "Configure"
weight: 30
type: "docs"
tags: ["server", "rdk", "extending viam", "modular resources", "components", "services"]
-description: "Use the Viam module system to implement custom resources that can be included in any Viam-powered robot."
+description: "Add and configure a module from the Viam Registry on your robot."
no_list: true
---
-Configure a module on your robot to make one or more modular resources available for configuration.
+You can extend Viam by adding a module on your robot to make one or more modular resources available for configuration.
+You can [add a module from the Viam Registry](#add-a-module-from-the-viam-registry), or you can [code your own module and add it to your robot locally](#add-a-local-module-to-your-robot).
-If you are developing your own modular resource, you must first follow [these steps](/extend/modular-resources/create/) to code your own module and generate an executable.
-If you are using a pre-built modular resource, make sure you install the module and determine the filename of [the module's executable](/extend/modular-resources/create/#compile-the-module-into-an-executable).
+A *module* makes one or more *modular resources* available for configuration.
+See [Key Concepts of Modular Resource APIs](/extend/modular-resources/key-concepts/) for more information.
-Follow these steps to configure the module and modular resource:
+## Add a module from the Viam Registry
-1. [Save the executable](#make-sure-viam-server-can-access-your-executable) in a location your `viam-server` instance can access.
-2. [Add a **module**](#configure-your-module) referencing this executable to the configuration of your robot.
-3. [Add a new component or service](#configure-your-modular-resource) referencing the custom resource provided by the configured **module** to the configuration of your robot.
+The Viam Registry is a central repository of modules from both Viam and the robotics community that allows you to easily extend Viam's capabilities on your robot.
+
+To add a module from the Viam Registry to your robot:
+
+1. Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
+1. Click on the **Components** subtab and click the **Create component** button.
+1. Enter the name of the module you would like to add to your robot.
+ To find the name of a module you're interested in, you can:
+
+ - Start typing to search for modules by name.
+ Modules available from the Viam Registry will be listed under the `From Registry` section of the search results.
+ - [Browse the Viam Registry](https://app.viam.com/modules) directly to search available modules.
+
+ {{}}
+
+1. After entering the name of the module that you would like to add to your robot, select the matching module in the search results and click the **Add module** button.
+
+When you add a module from the Viam Registry, the custom modular component it provides appears under the **Components** subtab like any other component.
+You can also find [the module itself](#configure-a-module-from-the-viam-registry) listed as **Deployed** under the **Modules** subtab.
+
+{{}}
+
+If the module requires you to configure specific **Atrributes**, click the **URL** link in the module's configuration pane to view the specific documentation on the module's GitHub page.
+
+To delete a module added from the Viam Registry, click the trash can icon in the upper-right corner of the module configuration pane in the **Components** tab.
+
+### Configure a module from the Viam Registry
-{{% alert title="Modules vs. modular resources" color="tip" %}}
+Once you have added a module from the Viam Registry, you can view and configure the module from the **Modules** subtab:
-A configured *module* can make one or more *modular resources* available for configuration.
+1. Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
+1. Click on the **Modules** subtab.
+ All modules you have added to your robot appear under the **Deployed** section.
+This pane lists the models provided by the module, any [components](/components/) on your robot that are currently using those models, and allows you to configure [how the module updates](#configure-version-update-management-for-a-registry-module) when a new version is available from the Viam Registry.
+
+{{}}
+
+#### Configure version update management for a Registry module
+
+When you add a module to your robot, you can also configure how that module updates itself when a newer version becomes available from the Viam Registry.
+By default, a newly-added module is set to pin to the specific patch release (**Patch (X.Y.Z)**) of the version you added, meaning that the module will *never automatically update itself*.
+
+If you wish to allow automatic module updates when a new version of the module becomes available in the Viam Registry, you can set the **Version type** for your module in the **Modules** subtab.
+Updating to a newer version of a module brings new functionality and bug fixes, but requires restarting the module to apply the update.
+The following update options are available:
+
+- **Patch (X.Y.Z)**: Do not update to any other version.
+ This is the default.
+- **Minor (X.Y.*)**: Only update to newer patch releases of the same minor release branch.
+ The module will automatically restart and update itself whenever new updates within the same minor release are available in the Viam Registry.
+ For example, use this option to permit a module with version `1.2.3` to update to version `1.2.4` or `1.2.5` but not `1.3.0` or `2.0.0`.
+- **Major (X.*)**: Only update to newer minor releases of the same major release branch.
+ The module will automatically restart and update itself whenever new updates within the same major release are available in the Viam Registry.
+ For example, use this option to permit a module with version `1.2.3` to update to version `1.2.4` or `1.3.0` but not `2.0.0` or `3.0.0`.
+- **Latest**: Always update to the latest version of this module available from the Viam Registry as soon as a new version becomes available.
+
+When using the **Patch (X.Y.Z)** version type, you may select any patch version of the module from the **Version** drop down menu, including past versions if desired.
+
+The current deployed version of your module and the latest version of that module available from the Viam Registry are shown on this pane for your reference.
+
+{{% alert title="Caution" color="caution" %}}
+For any version type other than **Patch (X.Y.Z)**, the module will upgrade as soon as an update that matches that specified version type is available, which will **restart the module**.
+If, for example, the module provides a motor component, and the motor is running, it will stop while the module upgrades.
{{% /alert %}}
+### Configure a modular resource from a Registry module
+
+Once you have configured a module from the Viam Registry, you can add any number of the resources that the module makes available to your robot by adding new components or services configured with your modular resources' [model](/extend/modular-resources/key-concepts/#models).
+
+The following properties are available for modular resources:
+
+| Name | Type | Inclusion | Description |
+| ---- | ---- | --------- | ----------- |
+| `namespace` | string | **Required** | The namespace of the API (the first part of the {{< glossary_tooltip term_id="api-namespace-triplet" text="API namespace triplet">}}). See [Valid APIs to implement in your model](/extend/modular-resources/key-concepts/#valid-apis-to-implement-in-your-model) |
+| `type` | string | **Required** | The {{< glossary_tooltip term_id="subtype" text="subtype">}} of the API (the third part of the {{< glossary_tooltip term_id="api-namespace-triplet" text="API namespace triplet">}}). See [Valid APIs to implement in your model](/extend/modular-resources/key-concepts/#valid-apis-to-implement-in-your-model). |
+| `name` | string | **Required** | What you want to name this instance of your modular resource. |
+| `model` | string | **Required** | The full {{< glossary_tooltip term_id="model-namespace-triplet" text="model namespace triplet">}} of the modular resource's [model](/extend/modular-resources/key-concepts/#models). |
+| `depends_on` | array | Optional | The `name` of components you want to confirm are available on your robot alongside your modular resource. Often a [board](/components/board/). Unnecessary if you coded [implicit dependencies](/extend/modular-resources/key-concepts/#dependency-management). |
+
+All standard properties for configuration, such as `attributes` and `depends_on`, are also supported for modular resources.
+The `attributes` available vary depending on your implementation.
+
+{{< tabs >}}
+{{% tab name="JSON Template" %}}
+
+```json {class="line-numbers linkable-line-numbers"}
+{
+ "components": [
+ {
+ "namespace": "",
+ "type": "",
+ "model": "::",
+ "name": "",
+ "depends_on": [],
+ }
+ ],
+ "modules": [ ... ] // < INSERT YOUR MODULE CONFIGURATION >
+}
+```
+
+{{% /tab %}}
+{{% tab name="JSON Example" %}}
+
+The following is an example configuration for a base modular resource implementation.
+The configuration adds `acme:demo:mybase` as a modular resource from the module `my_base`.
+The custom model is configured as a component with the name "my-custom-base-1".
+You can send commands to the base according to the Viam [base API](/components/base/#api):
+
+```json {class="line-numbers linkable-line-numbers"}
+{
+ "components": [
+ {
+ "type": "board",
+ "name": "main-board",
+ "model": "pi"
+ },
+ {
+ "type": "base",
+ "name": "my-custom-base-1",
+ "model": "acme:demo:mybase",
+ "namespace": "rdk",
+ "attributes": {},
+ "depends_on": [ "main-board" ]
+ }
+ ],
+ "modules": [
+ {
+ "name": "my-custom-base",
+ "executable_path": "/home/my_username/my_base/run.sh"
+ }
+ ]
+}
+```
+
+{{% /tab %}}
+{{% /tabs %}}
+
+## Add a local module to your robot
+
+If you are developing your own modular resource, and intend to deploy it to your robot locally, first follow [these steps](/extend/modular-resources/create/) to code your own module and generate an executable.
+If you are using a pre-built modular resource, make sure you install the module and determine the filename of [the module's executable](/extend/modular-resources/create/#compile-the-module-into-an-executable).
+
+Follow these steps to configure a module and its modular resources locally:
+
+1. [Save the executable](#make-sure-viam-server-can-access-your-executable) in a location your `viam-server` instance can access.
+2. [Add a **module**](#configure-your-module) referencing this executable to the configuration of your robot.
+3. [Add a new component or service](#configure-your-modular-resource) referencing the modular resource provided by the configured **module** to the configuration of your robot.
+
### Make sure `viam-server` can access your executable
Ensure that your module executable is saved where the instance of `viam-server` behind your robot can read and execute it.
@@ -74,15 +214,15 @@ Add these properties to your module's configuration:
### Configure your modular resource
-Once you have configured a module as part of your robot configuration, you can add any number of the resources that module makes available to your robot by adding new components or services configured with your modular resources' new subtype or [model](/extend/modular-resources/key-concepts/#models).
+Once you have configured a module as part of your robot configuration, you can add any number of the resources that the module makes available to your robot by adding new components or services configured with your modular resources' [model](/extend/modular-resources/key-concepts/#models).
The following properties are available for modular resources:
| Name | Type | Inclusion | Description |
| ---- | ---- | --------- | ----------- |
-| `namespace` | string | **Required** | The namespace of the [API](/extend/modular-resources/key-concepts/#apis) (the first part of the {{< glossary_tooltip term_id="api-namespace-triplet" text="API namespace triplet">}}). |
-| `type` | string | **Required** | The {{< glossary_tooltip term_id="subtype" text="subtype">}} of the [API](/extend/modular-resources/key-concepts/#apis) (the third part of the {{< glossary_tooltip term_id="api-namespace-triplet" text="API namespace triplet">}}). |
-| `name` | string | **Required** | What you want to name this instance of your modular resource. |
+| `namespace` | string | **Required** | The namespace of the API (the first part of the {{< glossary_tooltip term_id="api-namespace-triplet" text="API namespace triplet">}}). See [Valid APIs to implement in your model](/extend/modular-resources/key-concepts/#valid-apis-to-implement-in-your-model). |
+| `type` | string | **Required** | The {{< glossary_tooltip term_id="subtype" text="subtype">}} of the API (the third part of the {{< glossary_tooltip term_id="api-namespace-triplet" text="API namespace triplet">}}). See [Valid APIs to implement in your model](/extend/modular-resources/key-concepts/#valid-apis-to-implement-in-your-model). |
+| `name` | string | **Required** | A custom name for this instance of your modular resource. |
| `model` | string | **Required** | The full {{< glossary_tooltip term_id="model-namespace-triplet" text="model namespace triplet">}} of the modular resource's [model](/extend/modular-resources/key-concepts/#models). |
| `depends_on` | array | Optional | The `name` of components you want to confirm are available on your robot alongside your modular resource. Often a [board](/components/board/). Unnecessary if you coded [implicit dependencies](/extend/modular-resources/key-concepts/#dependency-management). |
@@ -117,22 +257,22 @@ You can send commands to the base according to the Viam [base API](/components/b
```json {class="line-numbers linkable-line-numbers"}
{
- "components": [
- {
- "type": "board",
- "name": "main-board",
- "model": "pi"
- },
- {
- "type": "base",
- "name": "my-custom-base-1",
- "model": "acme:demo:mybase",
- "namespace": "rdk",
- "attributes": {},
- "depends_on": [ "main-board" ]
- }
- ],
- "modules": [
+ "components": [
+ {
+ "type": "board",
+ "name": "main-board",
+ "model": "pi"
+ },
+ {
+ "type": "base",
+ "name": "my-custom-base-1",
+ "model": "acme:demo:mybase",
+ "namespace": "rdk",
+ "attributes": {},
+ "depends_on": [ "main-board" ]
+ }
+ ],
+ "modules": [
{
"name": "my-custom-base",
"executable_path": "/home/my_username/my_base/run.sh"
diff --git a/docs/extend/modular-resources/create/_index.md b/docs/extend/modular-resources/create/_index.md
index 77c04db62b..cebdbf2d43 100644
--- a/docs/extend/modular-resources/create/_index.md
+++ b/docs/extend/modular-resources/create/_index.md
@@ -1,37 +1,27 @@
---
-title: "Code your own modules to create custom resources"
+title: "Code your own modules to create modular resources"
linkTitle: "Create"
weight: 20
type: "docs"
tags: ["server", "rdk", "extending viam", "modular resources", "components", "services"]
-description: "Use the Viam module system to implement custom resources that can be included in any Viam-powered robot."
+description: "Use the Viam module system to implement modular resources that can be included in any Viam-powered robot."
no_list: true
---
-The Viam module system allows you to integrate custom {{< glossary_tooltip term_id="resource" text="resources" >}} ([components](/components/) and [services](/services/)) into any robot running on Viam.
+You can extend Viam by creating a custom [module](/extend/modular-resources/key-concepts/#modules) that provides one or more modular {{< glossary_tooltip term_id="resource" text="resources" >}} ([components](/components/) and [services](/services/)), and can be added to any robot running on Viam.
A common use case for modular resources is to create a new model that implements an existing Viam API.
-However, you can also create and expose new APIs with modular resources.
-{{% alert title="Modules vs. modular resources" color="tip" %}}
-
-A configured *module* can make one or more *modular resources* available for configuration.
-
-{{% /alert %}}
-
-Once you have created your custom resource, you can use the [Viam CLI](/manage/cli/) to [upload your custom resource](/extend/modular-resources/upload/) to the Viam Registry, to share it with other Viam users or just to other users in your organization.
+Once you have created your modular resource, you can use the [Viam CLI](/manage/cli/) to [upload your modular resource](/extend/modular-resources/upload/) to the Viam Registry, to share it with other Viam users or just to other users in your organization.
Alternatively, you can add your module locally to your robot without uploading to the Viam Registry.
-## Create a custom modular resource
-
-To create your own modular resource, code a module in Go or Python using the module support libraries provided by [Viam's SDKs](/program/apis/) that implements at least one new {{< glossary_tooltip term_id="model" text="model" >}} or {{< glossary_tooltip term_id="subtype" text="subtype" >}} of {{< glossary_tooltip term_id="resource" text="resource" >}}:
+## Create a custom module
-{{< tabs >}}
-{{% tab name="New Model" %}}
-Define a new model of a built-in resource subtype:
+To create a custom module, follow the steps below.
+A custom module can implement one or more [models](/extend/modular-resources/key-concepts/#models).
-1. [Code a new resource model](#code-a-new-resource-model) server implementing all methods the Viam RDK requires in `viam-servers`'s built-in API client of its subtype (ex. `rdk:component:base`).
+1. [Code a new resource model](#code-a-new-resource-model) server implementing all methods the Viam RDK requires in `viam-server`'s built-in API client of its subtype (ex. `rdk:component:base`).
Provide this as a file inside of your module, my_modular_resource.go or my_modular_resource.py.
Follow these instructions to find the appropriate source code before you start the process.
@@ -44,14 +34,17 @@ Provide this as a file inside of your module, my_modular_resource.go/client.go` or `/client.py` on [Viam's GitHub](https://github.com/viamrobotics/rdk/blob/main/).
+ See [Valid APIs to implement in your model](/extend/modular-resources/key-concepts/#valid-apis-to-implement-in-your-model) for more information.
- For example, the base client is defined in [rdk/components/base/client.go](https://github.com/viamrobotics/rdk/blob/main/components/base/client.go).
- Base your edits to my_modular_resource.go or my_modular_resource.py on this first file.
+ - Name your model according to the namespace of the built-in API you are implementing.
+ For more information see [Naming your model](/extend/modular-resources/key-concepts/#naming-your-model).
**To prepare to import your custom model and your chosen resource subtype's API into your main program and register them with your chosen SDK:**
- Find the subtype API as defined in the relevant `/.go` file in the RDK on Viam's GitHub.
- For example, the base subtype is defined in [rdk/components/base/base.go](https://github.com/viamrobotics/rdk/blob/fdff22e90b8976061c318b2d1ca3b1034edc19c9/components/base/base.go#L37).
- - Base your edits to main.go or main.py on this second file.
+ - Base your edits to main.go or main.py on this second file.
2. [Code a main program](#code-a-main-entry-point-program), main.go or main.py, that starts the module after adding your desired resources from the registry.
Import your custom model and API into the main program and register them with your chosen SDK.
@@ -59,28 +52,10 @@ This main program is the "entry point" to your module.
3. [Compile or package](#compile-the-module-into-an-executable) the module into a single executable that can receive a socket argument from Viam, open the socket, and start the module at the entry point.
-{{% /tab %}}
-{{% tab name="New Type" %}}
-Define a new {{< glossary_tooltip term_id="api-namespace-triplet" text="type or subtype" >}} of resource:
-
-1. Define the methods and messages of the new API in [protobuf](https://github.com/protocolbuffers/protobuf) and in Python or Go, then use a protobuf compiler to [generate the rest of the required protobuf files](https://grpc.io/docs/languages/python/generated-code/) based on that Python or Go code.
-Find detailed instructions in [Define a New Resource Subtype](create-subtype/).
-
-1. [Code at least one model](#code-a-new-resource-model) of this new resource.
-Make sure to implement every method required in your API definition.
-Import your custom models and APIs into the main program and register them with your chosen SDK.
-
-1. [Code a main program](#code-a-main-entry-point-program) that starts the module after adding your desired resources from the registry.
-This main program is the "entry point" to your module.
-
-1. [Compile or package](#compile-the-module-into-an-executable) the module into a single executable that can receive a socket argument from Viam, open the socket, and start the module at the entry point.
-
-{{% /tab %}}
-{{% /tabs %}}
-
### Code a new resource model
-The following example module registers a modular resource implementing Viam's built-in [Base API](/components/base/#api) [(rdk:service:base)](/extend/modular-resources/key-concepts/#models) as a new model, `"mybase"`:
+The following example module registers a modular resource implementing Viam's built-in [Base API](/components/base/#api) [(rdk:service:base)](/extend/modular-resources/key-concepts/#models) as a new model, `"mybase"`, using the model family `acme:demo:mybase`.
+For more information see [Naming your model](/extend/modular-resources/key-concepts/#naming-your-model).
The Go code for the custom model (mybase.go) and module entry point file (main.go) is adapted from the full demo modules available on the [Viam GitHub](https://github.com/viamrobotics/rdk/blob/main/examples/customresources).
@@ -390,7 +365,7 @@ func init() {
{{% tab name="Python"%}}
main.py is the Python module's entry point file.
-When executed, it registers the mybase custom model and API helper functions with the Python SDK and creates and starts the new module.
+When executed, it registers the `mybase` custom model and API helper functions with the Python SDK and creates and starts the new module.
Click to view sample code from main.py
diff --git a/docs/extend/modular-resources/examples/_index.md b/docs/extend/modular-resources/examples/_index.md
index ed582a4168..5aeb8e4fd4 100644
--- a/docs/extend/modular-resources/examples/_index.md
+++ b/docs/extend/modular-resources/examples/_index.md
@@ -15,13 +15,15 @@ aliases:
---
To familiarize yourself with creating and using modular resources, follow one of these example [tutorials](#tutorials) or clone one of these example [repositories](#repositories).
-Once you have created a modular resource, you can test your custom resource using the [Control tab](/manage/fleet/#remote-control) and program it using the [Viam SDKs](/program/apis/).
+Once you have created a modular resource, you can test your modular resource using the [Control tab](/manage/fleet/#remote-control) and program it using the [Viam SDKs](/program/apis/).
## Tutorials
{{< cards >}}
{{% card link="/extend/modular-resources/examples/rplidar/" customTitle="Add an RPlidar camera as a Modular Resource" %}}
{{% card link="/extend/modular-resources/examples/odrive/" customTitle="Add an ODrive motor as a Modular Resource" %}}
+ {{% card link="/extend/modular-resources/examples/csi/" customTitle="Add a CSI Camera as a Modular Resource" %}}
+ {{% card link="/components/movement-sensor/viam-visual-odometry/" customTitle="Add a Visual Odometry sensor as a Modular Resource" %}}
{{% card link="/extend/modular-resources/examples/custom-arm/" %}}
{{% card link="/extend/modular-resources/examples/tflite-module/" customTitle="Add a TensorFlow Lite Modular Service" %}}
{{% card link="/tutorials/custom/custom-base-dog/" %}}
diff --git a/docs/extend/modular-resources/examples/csi.md b/docs/extend/modular-resources/examples/csi.md
new file mode 100644
index 0000000000..c0e15f8cec
--- /dev/null
+++ b/docs/extend/modular-resources/examples/csi.md
@@ -0,0 +1,116 @@
+---
+title: "Add a CSI Camera as a Modular Resource"
+linkTitle: "CSI Camera"
+weight: 40
+type: "docs"
+description: "Use the viam:camera:csi model to add a CSI Camera to your robot."
+tags: ["board", "csi", "jetson", "serial", "module", "modular resources", "Python", "python SDK", "nvidia", "jetson orin", "jetson orin nano", "nano", "camera"]
+# SMEs: Sean
+---
+
+
+Many boards, like the Jetson Orin Nano, come with the option to use Camera Serial Interface (CSI) cameras, like [these cameras from E-con Systems](https://www.e-consystems.com/nvidia-jetson-agx-orin-cameras.asp) or [this camera from Seed Technologies](https://www.digikey.com/en/products/detail/seeed-technology-co.,-ltd/114992263/12396924).
+These cameras are excellent for utilizing embedded vision systems like Viam's [vision service](/services/vision/).
+Not all CSI cameras are supported by the [webcam camera model](/components/camera/webcam/).
+Instead, Viam supports CSI cameras by providing a [modular resource](/extend/modular-resources/) for your CSI camera: `viam:camera:csi`.
+
+This module includes a simple wrapper around `GStreamer` and a control interface for the **control** tab of the [Viam app](https://app.viam.com) so you can utilize the hardware accelerated GST plugins and use the embedded CSI cameras on your `jetson` boards with Viam.
+
+The module is open-sourced and available on [GitHub](https://github.com/seanavery/viam-csi).
+
+To use the CSI camera module, follow the [installation](#installation) and [configuration](#configuration) steps.
+
+## Installation
+
+On your robot's computer, download [the `viam:camera:csi` appimage](https://github.com/viamrobotics/odrive) and make it executable:
+
+``` {class="command-line" data-prompt="$"}
+sudo wget https://github.com/seanavery/viam-csi/releases/download/v0.0.2/viam-csi-0.0.2-aarch64.AppImage -O /usr/local/bin/viam-csi
+sudo chmod 755 /usr/local/bin/viam-csi
+```
+
+## Configuration
+
+{{< tabs name="Connect your CSI Module and Modular Resource">}}
+{{% tab name="JSON Template" %}}
+
+Go to your robot's page on the [Viam app](https://app.viam.com/).
+Navigate to the **Config** tab on your robot's page and select **Raw JSON** mode.
+
+Copy and paste the JSON object for the module into the modules array to add Viam's `csi-mr` module:
+
+```json {class="line-numbers linkable-line-numbers"}
+{
+ "modules": [
+ {
+ "executable_path": "",
+ "name": ""
+ }
+ ]
+}
+```
+
+Next, add the following JSON object to your components array to configure a `csi` [camera](/components/camera/) component with the name `my_test_csi_cam`:
+
+```json {class="line-numbers linkable-line-numbers"}
+ {
+ "model": "viam:camera:csi",
+ "attributes": {
+ "width_px": ,
+ "height_px": ,
+ "frame_rate": ,
+ "debug": ""
+ },
+ "depends_on": [],
+ "name": "",
+ "namespace": "rdk",
+ "type": "camera"
+ }
+```
+
+{{% /tab %}}
+{{% tab name="JSON Example" %}}
+
+```json {class="line-numbers linkable-line-numbers"}
+{
+ "modules": [
+ {
+ "executable_path": "/usr/bin/csi-mr",
+ "name": "csi_cam_module"
+ }
+ ],
+ "components": [
+ {
+ "model": "viam:camera:csi",
+ "attributes": {
+ "width_px": 1920,
+ "height_px": 1080,
+ "frame_rate": 30,
+ "debug": true
+ },
+ "depends_on": [],
+ "name": "my_test_csi_cam",
+ "namespace": "rdk",
+ "type": "camera"
+ }
+ ]
+}
+```
+
+{{% /tab %}}
+{{< /tabs >}}
+
+Save the config.
+Edit and fill in the attributes as applicable.
+
+Check the [**Logs** tab](/program/debug/) of your robot in the Viam app to make sure your camera has connected and no errors are being raised.
+
+The following attributes are available for the `viam:camera:csi` model:
+
+| Name | Type | Inclusion | Description |
+| ---- | ---- | --------- | ----------- |
+| `width_px` | int | Optional | Width of the image this camera captures in pixels.
Default: `1920` |
+| `height_px` | int | Optional | Height of the image this camera captures in pixels.
Default: `1080` |
+| `frame_rate` | int | Optional | The image capture frame rate this camera should use.
Default: `30` |
+| `video_path` | string | Optional | The filepath to the input sensor of this camera on your board. If none is given, your robot will attempt to detect the video path automatically.
Default: `"0"` |
+| `debug` | boolean | Optional | Whether or not you want debug input from this camera in your robot's logs.
Default: `false` |
diff --git a/docs/extend/modular-resources/examples/tflite-module.md b/docs/extend/modular-resources/examples/tflite-module.md
index 639b45cf74..d2b97dbb4d 100644
--- a/docs/extend/modular-resources/examples/tflite-module.md
+++ b/docs/extend/modular-resources/examples/tflite-module.md
@@ -18,7 +18,7 @@ This code is for instructional purposes only, and is not intended for production
You can find the example files in the [Viam C++ SDK](https://github.com/viamrobotics/viam-cpp-sdk):
-- [`example_mlmodelservice_tflite.cpp`](https://github.com/viamrobotics/viam-cpp-sdk/blob/main/src/viam/examples/modules/example_mlmodelservice_tflite.cpp) - an example module which provides the `MLModelService` modular resource capable of running any TensorFlow Lite model.
+- [`example_mlmodelservice_tflite.cpp`](https://github.com/viamrobotics/viam-cpp-sdk/blob/main/src/viam/examples/modules/tflite/main.cpp) - an example module which provides the `MLModelService` modular resource capable of running any TensorFlow Lite model.
- [`example_audio_classification_client.cpp`](https://github.com/viamrobotics/viam-cpp-sdk/blob/main/src/viam/examples/mlmodel/example_audio_classification_client.cpp) - an example inference client which generates audio samples and invokes the `example_mlmodelservice_tflite` module to classify those samples using the [`yamnet/classification` TensorFlow Lite model](https://tfhub.dev/google/lite-model/yamnet/classification/tflite/1).
## Build the C++ SDK
diff --git a/docs/extend/modular-resources/key-concepts.md b/docs/extend/modular-resources/key-concepts.md
index 89fe2cae8f..375b4c162f 100644
--- a/docs/extend/modular-resources/key-concepts.md
+++ b/docs/extend/modular-resources/key-concepts.md
@@ -8,56 +8,113 @@ description: "The key concepts behind how Viam's resource APIs and models are un
no_list: true
---
-`viam-server` [manages](#management) modular {{< glossary_tooltip term_id="resource" text="resources" >}} configured on your robot the same way it manages resources that are already built into the Robot Development Kit [(RDK)](/internals/rdk/).
-Two key concepts exist across all Viam resources, both built-in and modular, that make this flexible management possible: uniquely namespaced resource [*APIs*](#apis) and [*models*](#models).
+You can extend the features of an existing {{< glossary_tooltip term_id="resource" text="resource" >}} API by [creating a custom module](/extend/modular-resources/create/) to define a new [model](#models) that implements that API.
+A custom module can provide one or more modular resource models.
-If you create your [own module](/extend/modular-resources/create/), you must register any new APIs and models you define in your model with Viam's model registry in the appropriate namespaces to [configure](/extend/modular-resources/configure/) the modular resource on your robot.
+## Modules
-## APIs
+A *module* provides one or more [*modular resources*](#resources), and is a flexible way to extend the functionality of your Viam robot.
+Modules run alongside `viam-server` as a separate process, communicating with `viam-server` over a UNIX socket.
+A module provides definitions for one or more pairs of [APIs](#valid-apis-to-implement-in-your-model) and [models](#models).
-{{% alert title="Modules vs. modular resources" color="tip" %}}
+When the module initializes, it registers those pairs on your robot, making the functionality defined by that pair available for use.
-A configured *module* can make one or more *modular resources* available for configuration.
+You can [upload your own modules to the Viam Registry](/extend/modular-resources/upload/) or can [add existing modules from the Registry](/extend/modular-resources/configure/).
-{{% /alert %}}
+See [Creating a custom module](/extend/modular-resources/create/) for more information.
-Every Viam {{< glossary_tooltip term_id="resource" text="resource" >}} subtype exposes an [application programming interface (API)](https://en.wikipedia.org/wiki/API).
-This can be understood as a description of how you can interact with that resource.
-Each API is described through [protocol buffers](https://developers.google.com/protocol-buffers).
-Viam SDKs [expose these APIs](/internals/robot-to-robot-comms/).
+## Resources
-### Namespace
+A resource is a [component](/components/) or [service](/services/).
+Each component or service is typed by a proto API, such as the [component proto definitions](https://github.com/viamrobotics/api/tree/main/proto/viam/component).
-Each Viam resource's API is uniquely namespaced as a colon-delimited-triplet in the form of `namespace:type:subtype`.
+Any resource on your robot needs to implement either one of these [existing Viam APIs](#valid-apis-to-implement-in-your-model), or a custom interface.
-For example:
+A *modular resource* is a resource that is provided by a [module](#modules), and not built-in to the RDK.
+A modular resource runs in the module process. This differs from built-in resources, which run as part of `viam-server`.
-- The API of built-in component [camera](/components/camera/) is `rdk:component:camera`, which exposes methods such as `GetImage()`.
-- The API of built-in service [vision](/services/vision/) is `rdk:service:vision`, which exposes methods such as `GetDetectionsFromCamera()`.
+## Models
-{{% alert title="Tip" color="tip" %}}
-You can see built-in Viam resource APIs in the [Viam GitHub](https://github.com/viamrobotics/api).
-{{% /alert %}}
+A *model* describes a specific implementation of a [resource](#resources) that implements (speaks) its API.
+Models allow you to control different instances of resource with a consistent interface, even if the underlying implementation differs.
-## Models
+For example, some DC motors communicate using [GPIO](/components/board/), while other DC motors use serial protocols like the [SPI bus](/components/board/#spis).
+Regardless, you can power any motor model that implements the `rdk:component:motor` API with the `SetPower()` method.
-A *model* describes a specific implementation of a resource that implements (speaks) its API.
-Models allow you to control different instances of resource {{< glossary_tooltip term_id="api-namespace-triplet" text="subtypes" >}} with a consistent interface.
+Models are uniquely namespaced as colon-delimited-triplets in the form `namespace:family:name`.
+See [Naming your model](/extend/modular-resources/key-concepts/#naming-your-model) for more information.
-For example:
+Models are either:
-Some DC motors use just [GPIO](/components/board/), while other DC motors use serial protocols like [SPI bus](/components/board/#spis).
-Regardless, you can power any motor model that implements the `rdk:component:motor` API with the `SetPower()` method.
+- Built into the RDK, and included when you [install `viam-server`](/installation/) or when you use one of the [Viam SDKs](/program/apis/).
+- Provided in custom modules available for download from [the Viam Registry](https://app.viam.com/module), and are written by either Viam or community users.
-### Namespace
+### Built-in models
-Models are also uniquely namespaced as colon-delimited-triplets in the form of `namespace:family:name`.
+Viam provides many built-in models that implement API capabilities, each using `rdk` as the `namespace`, and `builtin` as the `family`.
+These models run within `viam-server`.
For example:
- The `rdk:builtin:gpio` model of the `rdk:component:motor` API provides RDK support for [GPIO-controlled DC motors](/components/motor/gpio/).
- The `rdk:builtin:DMC4000` model of the same `rdk:component:motor` API provides RDK support for the [DMC4000](/components/motor/dmc4000/) motor.
+### Custom models
+
+The [Viam Registry](https://app.viam.com/registry) makes available both Viam-provided and community-written modules for download and use on your robot.
+These models run outside `viam-server` as a separate process.
+
+#### Valid APIs to implement in your model
+
+When implementing a custom model of an existing [component](/components/), valid [APIs](/program/apis/) are always:
+
+- `namespace`: `rdk`
+- `type`: `component`
+- `subtype`: any one of [these component proto files](https://github.com/viamrobotics/api/tree/main/proto/viam/component).
+
+When implementing a custom model of an existing [service](/services/), valid [APIs](/program/apis/) are always
+
+- `namespace`: `rdk`
+- `type`: `service`
+- `subtype`: any one of [these service proto files](https://github.com/viamrobotics/api/tree/main/proto/viam/service).
+
+#### Naming your model
+
+If you are [creating a custom module](/extend/modular-resources/create/) and [uploading that module](/extend/modular-resources/upload/) to the Viam Registry, ensure your model name meets the following requirements:
+
+- The namespace of your model **must** match the [namespace of your organization](/manage/fleet/organizations/#create-a-namespace-for-your-organization).
+ For example, if your organization uses the `acme` namespace, your models must all begin with `acme`, like `acme:demo:mybase`.
+- Your model triplet must be all-lowercase.
+- Your model triplet may only use alphanumeric (`a-z` and `0-9`), hyphen (`-`), and underscore (`_`) characters.
+
+In addition, you should chose a name for the `family` of your model based on the whether your module implements a single model, or multiple models:
+
+- If your module provides a single model, the `family` should match the `subtype` of whichever API your model implements.
+ For example, the Intel Realsense module `realsense`, available from [the Viam Registry](https://app.viam.com/module/viam/realsense), implements the `camera` component API, so it is named as follows:
+
+ ```json {class="line-numbers linkable-line-numbers"}
+ {
+ "api": "rdk:component:camera",
+ "model": "viam:camera:realsense"
+ }
+ ```
+
+- If your module provides multiple models, the `family` should describe the common functionality provided across all the models of that module.
+ For example, the ODrive module `odrive`, available from [the Viam Registry](https://app.viam.com/module/viam/odrive), implements several `motor` component APIs, so it is named as follows:
+
+ ```json {class="line-numbers linkable-line-numbers"}
+ {
+ "api": "rdk:component:motor",
+ "model": "viam:odrive:serial"
+ },
+ {
+ "api": "rdk:component:motor",
+ "model": "viam:odrive:canbus"
+ }
+ ```
+
+A model with the `viam` namespace is always Viam-provided.
+
## Management
The Robot Development Kit (RDK) `viam-server` provides automatically manages modular resources to function like built-in resources:
diff --git a/docs/extend/modular-resources/upload/_index.md b/docs/extend/modular-resources/upload/_index.md
index 4bf3f6ed77..e885205da0 100644
--- a/docs/extend/modular-resources/upload/_index.md
+++ b/docs/extend/modular-resources/upload/_index.md
@@ -106,7 +106,7 @@ To upload your custom module to the Viam Registry, either as a public or private
```
{{% alert title="Important" color="note" %}}
- If you are publishing a public module (`visibility: "public"`), the [namespace of your model](/extend/modular-resources/key-concepts/#namespace-1) must match the [namespace of your organization](/manage/fleet/organizations/#create-a-namespace-for-your-organization).
+ If you are publishing a public module (`visibility: "public"`), the [namespace of your model](/extend/modular-resources/key-concepts/#naming-your-model) must match the [namespace of your organization](/manage/fleet/organizations/#create-a-namespace-for-your-organization).
In the example above, the model namespace is set to `acme` to match the owning organization's namespace.
If the two namespaces do not match, the command will return an error.
{{% /alert %}}
diff --git a/docs/installation/_index.md b/docs/installation/_index.md
index 6cdbc4ad51..d85f4b8c3a 100644
--- a/docs/installation/_index.md
+++ b/docs/installation/_index.md
@@ -40,11 +40,17 @@ If you are using one of the following boards, you can follow our guide for that
{{% card link="/installation/prepare/sk-tda4vm/" class="small" %}}
{{% card link="/installation/prepare/jetson-nano-setup/" class="small" %}}
{{% card link="/installation/prepare/jetson-agx-orin-setup/" class="small" %}}
-{{% card link="/installation/prepare/microcontrollers" class="small" %}}
{{< /cards >}}
+Viam also provides a lightweight version of `viam-server` which can run on resource-limited embedded systems that cannot run the fully-featured Robot Development Kit (RDK).
+If you are using a microcontroller, prepare your board using the following guide:
+
+{{< cards >}}
+{{% card link="/installation/prepare/microcontrollers" class="small" %}}
+{{< /cards >}}
+
Other SBCs such as the [RockPi S](https://wiki.radxa.com/RockpiS) and [Orange Pi Zero 2](https://orangepi.com/index.php?route=product/product&path=237&product_id=849) can run Viam with an experimental [periph.io](https://periph.io/) based [modular component](https://github.com/viam-labs/periph_board).
### Install `viam-server`
diff --git a/docs/installation/prepare/jetson-agx-orin-setup.md b/docs/installation/prepare/jetson-agx-orin-setup.md
index dae5d93ac6..cc8644cf25 100644
--- a/docs/installation/prepare/jetson-agx-orin-setup.md
+++ b/docs/installation/prepare/jetson-agx-orin-setup.md
@@ -33,7 +33,7 @@ You need the following hardware, tools, and software to install `viam-server` on
**Initial Setup with Display Attached:**
-1. A [Jetson AGX Orin Developer Kit](https://www.arrow.com/en/products/945-13730-0000-000/nvidia)
+1. A [Jetson AGX Orin Developer Kit](https://developer.nvidia.com/embedded/learn/get-started-jetson-agx-orin-devkit)
2. A PC monitor (HDMI or DisplayPort)
3. USB keyboard and mouse
4. A DisplayPort to HDMI adapter/cable, to connect the Orin to the monitor
@@ -42,7 +42,7 @@ You need the following hardware, tools, and software to install `viam-server` on
**Initial Setup in Headless Mode:**
-1. A [Jetson AGX Orin Developer Kit](https://www.arrow.com/en/products/945-13730-0000-000/nvidia)
+1. A [Jetson AGX Orin Developer Kit](https://developer.nvidia.com/embedded/learn/get-started-jetson-agx-orin-devkit)
2. An internet-connected Windows, Linux, or macOS computer
3. A way to connect the computer to the Orin (for example, the USB Type-A to USB Type-C Cable included with the AGX Orin Developer Kit)
diff --git a/docs/installation/prepare/jetson-nano-setup.md b/docs/installation/prepare/jetson-nano-setup.md
index 19db3c3808..fa28be4785 100644
--- a/docs/installation/prepare/jetson-nano-setup.md
+++ b/docs/installation/prepare/jetson-nano-setup.md
@@ -19,13 +19,6 @@ Follow this guide to set up the [Jetson Nano Developer Kit](https://developer.nv
{{}}
-{{% alert title="Stability Notice" color="note" %}}
-
-Support for this board is experimental.
-Stability is not guaranteed.
-
-{{% /alert %}}
-
{{% alert title="Important" color="note" %}}
This guide assumes that you have a Jetson Nano Developer Kit or a Jetson Orin Nano Developer Kit with a Jetson module and reference carrier board.
diff --git a/docs/installation/prepare/microcontrollers/_index.md b/docs/installation/prepare/microcontrollers/_index.md
index 282f00e09a..65334d10fe 100644
--- a/docs/installation/prepare/microcontrollers/_index.md
+++ b/docs/installation/prepare/microcontrollers/_index.md
@@ -244,12 +244,11 @@ The`esp32` [board](/components/board/) model is not currently provided for you a
TODO: UNCOMMENT WHEN AVAILABLE IN APP UI, AND MOVE THIS CHUNK TO BOARD PAGE (SG)
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your board, select the type `board`, and select the `numato` model.
+Click on the **Components** subtab and click **Create component**.
+Select the `board` type, then select the `numato` model.
+Enter a name for your board and click **Create**.
-Click **Create component**.
-
- ![An example configuration for an esp21 board in the Viam app Config Builder.](/components/board/esp32-ui-config.png)
+ ![An example configuration for an esp32 board in the Viam app Config Builder.](/components/board/esp32-ui-config.png)
Edit and fill in the attributes as applicable.
-->
diff --git a/docs/manage/CLI.md b/docs/manage/CLI.md
index 25c5d5ab5e..a19dcf4ffd 100644
--- a/docs/manage/CLI.md
+++ b/docs/manage/CLI.md
@@ -99,23 +99,64 @@ To later update the Viam CLI tool, you can use the steps above to reinstall the
## Authenticate
-Once you have successfully installed the Viam CLI, you need to authenticate your device for CLI usage with your Viam app account before you can control your robots with the CLI.
-Do this by issuing the command:
+Once you have [installed the Viam CLI](#install), you must authenticate your CLI session with Viam in order to run CLI commands.
-```sh {class="command-line" data-prompt="$"}
-viam login
-```
+You can authenticate your CLI session using either a personal access token or an organization API key.
+To use an organization API key to authenticate, you must first [create an organization API key](#create-an-organization-api-key).
+
+* To authenticate your CLI session using a personal access token:
+
+ ```sh {class="command-line" data-prompt="$"}
+ viam login
+ ```
+
+ This will open a new browser window with a prompt to start the authentication process.
+ If a browser window does not open, the CLI will present a URL for you to manually open in your browser.
+ Follow the instructions to complete the authentication process.
-This will open a new browser window with a prompt to start the authentication process.
-If a browser window does not open, the CLI will present a URL for you to manually open in your browser.
-Follow the instructions to complete the authentication process.
+* To authenticate your CLI session using an organization API key:
+
+ ```sh {class="command-line" data-prompt="$"}
+ viam login api-key --key-id --key
+ ```
+
+ If you haven't already, [create an organization API key](#create-an-organization-api-key) to use this authentication method.
-{{% alert title="Info" color="info" %}}
An authenticated session is valid for 24 hours, unless you explicitly [log out](#logout).
After the session expires or you log out, you must re-authenticate to use the CLI again.
+
+### Create an organization API key
+
+To use an organization API key to authenticate your CLI session, you must first create one:
+
+1. First, [authenticate](#authenticate) your CLI session.
+ If your organization does not already have an organization API key created, authenticate using a personal access token.
+
+1. Then, run the following command to create a new organization API key:
+
+ ```sh {class="command-line" data-prompt="$"}
+ viam organization api-key create --org-id --name
+ ```
+
+ Where:
+
+ * `org-id` is your organization ID. You can find your organization ID by running `viam organizations list` or by visiting your organization's **Settings** page in [the Viam app](https://app.viam.com/).
+ * `key-name` is an optional name for your API key. If omitted, a name will be auto-generated based on your login info and the current time.
+
+The command will return a `key id` and a `key value`.
+You will need both to authenticate using `viam login api-key`.
+
+{{% alert title="Important" color="note" %}}
+Secure these key values safely.
+Authenticating using an organization API key gives the authenticated CLI session full read and write access to all robots within your organization.
{{% /alert %}}
+Once created, you can then use the organization API key to authenticate future CLI sessions.
+To switch to using an organization API key for authentication right away, [logout](#logout) then log back in using `viam login api-key`.
+
+An organization can have multiple API keys.
+
## Manage your robots with the Viam CLI
With the Viam CLI [installed](#install) and [authenticated](#authenticate), you can use it to issue commands to your robot fleet or manage custom modules.
@@ -226,19 +267,31 @@ The `login` command helps you authorize your device for CLI usage. See [Authenti
```sh {class="command-line" data-prompt="$"}
viam login
+viam login api-key --key-id --key
viam login print-access-token
```
+Use `viam login` to authenticate using a personal access token, or `viam login api-key` to authenticate using an organization API key.
+If you haven't already, you must [create an organization API key](#create-an-organization-api-key) first in order to authenticate using one.
+
#### Command options
| command option | description | positional arguments
| ----------- | ----------- | ----------- |
-| `print-access-token` | prints the access token the CLI uses during an authenticated CLI session | - |
-| `help` | return help | - |
+| `api-key` | authenticate to Viam using an organization API key | - |
+| `print-access-token` | prints the access token used to authenticate the current CLI session | - |
+| `--help` | return help | - |
+
+##### Named arguments
+
+| argument | description | applicable commands | required
+| ----------- | ----------- | ----------- | ----------- |
+| `--key-id` | the `key id` (UUID) of the organization API key | `api-key` | true |
+| `--key` | the `key value` of the organization API key | `api-key` | true |
### `logout`
-The `logout` command ends an authenticated CLI session
+The `logout` command ends an authenticated CLI session.
```sh {class="command-line" data-prompt="$"}
viam logout
@@ -415,13 +468,37 @@ For example, the following represents the configuration of an example `my-module
```
{{% alert title="Important" color="note" %}}
-If you are publishing a public module (`visibility: "public"`), the [namespace of your model](/extend/modular-resources/key-concepts/#namespace-1) must match the [namespace of your organization](/manage/fleet/organizations/#create-a-namespace-for-your-organization).
+If you are publishing a public module (`visibility: "public"`), the [namespace of your model](/extend/modular-resources/key-concepts/#naming-your-model) must match the [namespace of your organization](/manage/fleet/organizations/#create-a-namespace-for-your-organization).
In the example above, the model namespace is set to `acme` to match the owning organization's namespace.
If the two namespaces do not match, the command will return an error.
{{% /alert %}}
See [Upload a custom module](/extend/modular-resources/upload/#upload-a-custom-module) and [Update an existing module](/extend/modular-resources/upload/#update-an-existing-module) for a detailed walkthrough of the `viam module` commands.
+### organization
+
+The *organization* command allows you to create a new organization API key.
+
+```sh {class="command-line" data-prompt="$"}
+viam organization api-key create --org-id [--name ]
+```
+
+See [create an organization API key](#create-an-organization-api-key) for more information.
+
+#### Command options
+
+| command option | description | positional arguments
+| ----------- | ----------- | ----------- |
+| `api-key` | create a new organization API key | - |
+| `--help` | return help | - |
+
+##### Named arguments
+
+| argument | description | applicable commands | required
+| ----------- | ----------- | ----------- | ----------- |
+| `--org-id` | your organization ID |`api-key`|true |
+| `--name` | optional name for the organization API key. If omitted, a name will be auto-generated based on your login info and the current time |`api-key`| false |
+
### organizations
The *organizations* command lists all organizations that the authenticated session belongs to.
diff --git a/docs/program/apis/_index.md b/docs/program/apis/_index.md
index 34e02c5eab..579027bebd 100644
--- a/docs/program/apis/_index.md
+++ b/docs/program/apis/_index.md
@@ -8,6 +8,7 @@ icon: "/services/icons/sdk.svg"
tags: ["client", "sdk", "viam-server", "networking", "apis", "robot api"]
aliases:
- "/program/sdks/"
+no_list: true
---
Every Viam {{< glossary_tooltip term_id="resource" text="resource" >}} exposes an [Application Programming Interface (API)](https://en.wikipedia.org/wiki/API) described through [protocol buffers](https://developers.google.com/protocol-buffers).
@@ -342,400 +343,16 @@ In addition to the [board API](#board), the [board component](/components/board/
{{< readfile "/static/include/components/apis/digitalinterrupt.md" >}}
-## Robot API
+## Robot Management APIs
-The Robot API is the designated interface for a robot, the root of all robotic parts.
-To interact with the Robot API with Viam's SDKs, instantiate a `RobotClient` ([gRPC](https://grpc.io/) client) and use that class for all interactions.
+### Robot API
-### DiscoverComponents
+All robots support the following methods through the [robot API](/program/apis/robot/):
-Get a list of discovered component configurations.
+{{< readfile "/static/include/services/apis/robot.md" >}}
-{{< tabs >}}
-{{% tab name="Python" %}}
-
-**Parameters:**
-
-- `queries` [(List [viam.proto.robot.DiscoveryQuery])](https://python.viam.dev/autoapi/viam/proto/robot/index.html#viam.proto.robot.DiscoveryQuery): A list of [tuples of API and model](https://python.viam.dev/autoapi/viam/proto/robot/index.html#viam.proto.robot.DiscoveryQuery) that you want to retrieve the component configurations corresponding to.
-
-**Returns:**
-
-- [(List[viam.proto.robot.Discovery])](https://python.viam.dev/autoapi/viam/proto/robot/index.html#viam.proto.robot.Discovery): The list of discovered component configurations corresponding to `queries`.
-
-``` python
-# Define a new discovery query.
-q = robot.DiscoveryQuery(subtype=acme.API, model="some model")
-
-# Define a list of discovery queries.
-qs = [q]
-
-# Get component configurations with these queries.
-component_configs = await robot.discover_components(qs)
-```
-
-For more information, see the [Python SDK Docs](https://python.viam.dev/autoapi/viam/robot/client/index.html#viam.robot.client.RobotClient.discover_components)
-
-{{% /tab %}}
-{{% tab name="Go" %}}
-
-**Parameters:**
-
-- `ctx` [(Context)](https://pkg.go.dev/context): A Context carries a deadline, a cancellation signal, and other values across API boundaries.
-- `qs` [([]resource.DiscoveryQuery)](https://pkg.go.dev/go.viam.com/rdk/resource#DiscoveryQuery): A list of [tuples of API and model](https://pkg.go.dev/go.viam.com/rdk/resource#DiscoveryQuery) that you want to retrieve the component configurations corresponding to.
-
-**Returns:**
-
-- [([]resource.Discovery)](https://pkg.go.dev/go.viam.com/rdk/resource#Discovery): The search query `qs` and the corresponding list of discovered component configurations as an interface called `Results`.
-`Results` may be comprised of primitives, a list of primitives, maps with string keys (or at least can be decomposed into one), or lists of the forementioned type of maps.
-- [(error)](https://pkg.go.dev/builtin#error): An error, if one occurred.
-
-```go
-// Define a new discovery query.
-q := resource.NewDiscoveryQuery(acme.API, resource.Model{Name: "some model"})
-
-// Define a list of discovery queries.
-qs := []resource.DiscoverQuery{q}
-
-// Get component configurations with these queries.
-component_configs, err := robot.DiscoverComponents(ctx.Background(), qs)
-```
-
-For more information, see the [Go SDK Docs](https://pkg.go.dev/go.viam.com/rdk/robot#Robot).
-
-{{% /tab %}}
-{{% tab name="TypeScript" %}}
-
-**Parameters:**
-
-- `queries` [(DiscoveryQuery[])](https://ts.viam.dev/classes/robotApi.DiscoveryQuery.html): An array of [tuples of API and model](https://ts.viam.dev/classes/robotApi.DiscoveryQuery.html#constructor) that you want to retrieve the component configurations corresponding to.
-
-**Returns:**
-
-- [(Discovery[])](https://ts.viam.dev/classes/robotApi.Discovery.html): List of discovered component configurations.
-
-```typescript
-// Define a new discovery query.
-const q = new proto.DiscoveryQuery(acme.API, resource.Model{Name: "some model"})
-
-// Define an array of discovery queries.
-let qs: proto.DiscoveryQuery[] = [q]
-
-// Get the array of discovered component configurations.
-const componentConfigs = await robot.discoverComponents(queries);
-```
-
-For more information, see the [Typescript SDK Docs](https://ts.viam.dev/classes/RobotClient.html).
-
-{{% /tab %}}
-{{< /tabs >}}
-
-### FrameSystemConfig
-
-Get the configuration of the frame system of a given robot.
-
-{{< tabs >}}
-{{% tab name="Python" %}}
-
-**Parameters:**
-
-- `additional_transforms` [(Optional[List[viam.proto.common.Transform]])](https://python.viam.dev/autoapi/viam/proto/common/index.html#viam.proto.common.Transform): A optional list of [additional transforms](/services/frame-system/#additional-transforms).
-
-**Returns:**
-
-- `frame_system` [(List[FrameSystemConfig])](https://python.viam.dev/autoapi/viam/proto/robot/index.html#viam.proto.robot.FrameSystemConfig): The configuration of a given robot’s frame system.
-
-```python {class="line-numbers linkable-line-numbers"}
-# Get a list of each of the reference frames configured on the robot.
-frame_system = await robot.get_frame_system_config()
-print(f"frame system donfiguration: {frame_system}")
-```
-
-For more information, see the [Python SDK Docs](https://python.viam.dev/autoapi/viam/robot/client/index.html#viam.robot.client.RobotClient.get_frame_system_config).
-
-{{% /tab %}}
-{{% tab name="Go" %}}
-
-**Parameters:**
+### Cloud API
-- `ctx` [(Context)](https://pkg.go.dev/context): A Context carries a deadline, a cancellation signal, and other values across API boundaries.
-
-**Returns:**
-
-- [(error)](https://pkg.go.dev/builtin#error): An error, if one occurred.
-- [(framesystem.Config)](https://pkg.go.dev/go.viam.com/rdk/robot/framesystem#Config): The configuration of the given robot’s frame system.
-
-For more information, see the [Go SDK Docs](https://pkg.go.dev/go.viam.com/rdk/robot#Robot).
-
-```go {class="line-numbers linkable-line-numbers"}
-// Print the frame system configuration
-frameSystem, err := robot.FrameSystemConfig(context.Background(), nil)
-fmt.Println(frameSystem)
-```
-
-{{% /tab %}}
-{{% tab name="TypeScript" %}}
-
-**Parameters:**
-
-- `transforms` [(Transform[])](https://ts.viam.dev/classes/commonApi.Transform.html): An optional array of [additional transforms](/services/frame-system/#additional-transforms).
-
-**Returns:**
-
-- [(FrameSystemConfig[])](https://ts.viam.dev/classes/robotApi.FrameSystemConfig.html): An array of individual parts that make up a robot's frame system.
-
-For more information, see the [TypeScript SDK Docs](https://ts.viam.dev/classes/RobotClient.html#frameSystemConfig).
-
-```typescript {class="line-numbers linkable-line-numbers"}
-// Get the frame system configuration.
-console.log('FrameSytemConfig:', await robot.frameSystemConfig());
-```
-
-{{% /tab %}}
-{{< /tabs >}}
-
-### Status
-
-Get the status of the resources on the robot.
-You can provide a list of ResourceNames for which you want statuses.
-If no names are passed in, the status of every resource configured on the robot is returned.
-
-{{< tabs >}}
-{{% tab name="Python" %}}
-
-**Parameters:**
-
-- `resourceNames` [(Optional[List[viam.proto.common.ResourceName]])](https://docs.python.org/library/typing.html#typing.Optional): An optional list of ResourceNames for components you want the status of.
-If no names are passed in, all resource statuses are returned.
-
-**Returns:**
-
-- [(List[str])](https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str): A list containing the status of each resource.
+The [cloud API](/program/apis/cloud/) supports the following methods (among [others](https://python.viam.dev/autoapi/viam/app/app_client/index.html#viam.app.app_client.AppClient)):
-For more information, see the [Python SDK Docs](https://python.viam.dev/autoapi/viam/robot/client/index.html#viam.robot.client.RobotClient.get_status).
-
-```python {class="line-numbers linkable-line-numbers"}
-# Get the status of the resources on the robot.
-statuses = await robot.get_status()
-```
-
-{{% /tab %}}
-{{% tab name="Go" %}}
-
-**Parameters:**
-
-- `ctx` [(Context)](https://pkg.go.dev/context): A Context carries a deadline, a cancellation signal, and other values across API boundaries.
-- `resourceNames` [([]resource.Name)](https://pkg.go.dev/go.viam.com/rdk/resource#Name): An optional list of ResourceNames for components you want the status of.
-If no names are passed in, all resource statuses are returned.
-
-**Returns:**
-
-- [([]Status)](https://pkg.go.dev/go.viam.com/rdk/robot#Status): Status of each resource.
-- [(error)](https://pkg.go.dev/builtin#error): An error, if one occurred.
-
-For more information, see the [Go SDK Docs](https://pkg.go.dev/go.viam.com/rdk/robot#Robot).
-
-```go {class="line-numbers linkable-line-numbers"}
-// Get the status of the resources on the robot.
-status, err = robot.Status(ctx.Background())
-```
-
-{{% /tab %}}
-{{% tab name="TypeScript" %}}
-
-**Parameters:**
-
-- `resourceNames` [(commonApi.ResourceName[])](https://ts.viam.dev/classes/commonApi.ResourceName.html): An optional array of ResourceNames for components you want the status of.
-If no names are passed in, all resource statuses are returned.
-
-**Returns:**
-
-- [(robotApi.Status[])](https://ts.viam.dev/classes/robotApi.Status.html): An array containing the status of each resource.
-
-For more information, see the [TypeScript SDK Docs](https://ts.viam.dev/classes/RobotClient.html#transformPCD).
-
-```typescript {class="line-numbers linkable-line-numbers"}
-// Get the status of the resources on the robot.
-const status = await robot.getStatus();
-```
-
-{{% /tab %}}
-{{< /tabs >}}
-
-### Close
-
-Close the underlying connections and stop any periodic tasks across all constituent parts of the robot.
-{{< tabs >}}
-{{% tab name="Python" %}}
-
-**Parameters:**
-
-- None
-
-**Returns:**
-
-- None
-
-For more information, see the [Python SDK Docs](https://python.viam.dev/autoapi/viam/robot/client/index.html#viam.robot.client.RobotClient.close).
-
-```python {class="line-numbers linkable-line-numbers"}
-# Cleanly close the underlying connections and stop any periodic tasks.
-await robot.close()
-```
-
-{{% /tab %}}
-{{% tab name="Go" %}}
-
-**Parameters:**
-
-- `ctx` [(Context)](https://pkg.go.dev/context): A Context carries a deadline, a cancellation signal, and other values across API boundaries.
-
-**Returns:**
-
-- [(error)](https://pkg.go.dev/builtin#error): An error, if one occurred.
-
-For more information, see the [Go SDK Docs](https://pkg.go.dev/go.viam.com/rdk/robot#Robot).
-
-```go {class="line-numbers linkable-line-numbers"}
-// Cleanly close the underlying connections and stop any periodic tasks,
-err := robot.Close(ctx.Background())
-```
-
-{{% /tab %}}
-{{% tab name="TypeScript" %}}
-
-**Parameters:**
-
-- None
-
-**Returns:**
-
-- None
-
-For more information, see the [TypeScript SDK Docs](https://ts.viam.dev/classes/RobotClient.html#disconnect).
-
-```typescript {class="line-numbers linkable-line-numbers"}
-// Cleanly close the underlying connections and stop any periodic tasks
-await robot.disconnect();
-```
-
-{{% /tab %}}
-{{< /tabs >}}
-
-### StopAll
-
-Cancel all current and outstanding operations for the robot and stop all actuators and movement.
-
-{{< tabs >}}
-{{% tab name="Python" %}}
-
-**Parameters:**
-
-- `extra` [(Dict[viam.proto.common.ResourceName, Dict[str, Any]])](https://python.viam.dev/autoapi/viam/proto/common/index.html#viam.proto.common.ResourceName): Any extra parameters to pass to the resources’ stop methods, keyed on each resource’s [`ResourceName`](https://python.viam.dev/autoapi/viam/proto/common/index.html#viam.proto.common.ResourceName).
-
-**Returns:**
-
-- None
-
-For more information, see the [Python SDK Docs](https://python.viam.dev/autoapi/viam/robot/client/index.html#viam.robot.client.RobotClient.stop_all).
-
-```python {class="line-numbers linkable-line-numbers"}
-# Cancel all current and outstanding operations for the robot and stop all actuators and movement.
-await robot.stop_all()
-```
-
-{{% /tab %}}
-{{% tab name="Go" %}}
-
-**Parameters:**
-
-- `ctx` [(Context)](https://pkg.go.dev/context): A Context carries a deadline, a cancellation signal, and other values across API boundaries.
-- `extra` [(map[resource.Name]map[string]interface{})](https://pkg.go.dev/go.viam.com/rdk/resource#Name): Any extra parameters to pass to the resources’ stop methods, keyed on each resource’s [`Name`](https://pkg.go.dev/go.viam.com/rdk/resource#Name).
-
-**Returns:**
-
-- [(error)](https://pkg.go.dev/builtin#error): An error, if one occurred.
-
-For more information, see the [Go SDK Docs](https://pkg.go.dev/go.viam.com/rdk/robot#Robot).
-
-```go {class="line-numbers linkable-line-numbers"}
-// Cancel all current and outstanding operations for the robot and stop all actuators and movement.
-err := robot.StopAll(ctx.Background())
-```
-
-{{% /tab %}}
-{{% tab name="TypeScript" %}}
-
-**Parameters:**
-
-- None
-
-**Returns:**
-
-- None
-
-For more information, see the [TypeScript SDK Docs](https://ts.viam.dev/classes/RobotClient.html#stopAll).
-
-```typescript {class="line-numbers linkable-line-numbers"}
-// Cancel all current and outstanding operations for the robot and stop all actuators and movement.
-await robot.stopAll();
-```
-
-{{% /tab %}}
-{{< /tabs >}}
-
-### ResourceNames
-
-Get a list of all known resource names connected to this robot.
-
-{{< tabs >}}
-{{% tab name="Python" %}}
-
-**Parameters:**
-
-- None
-
-**Returns:**
-
-- [(List[viam.proto.common.ResourceName])](https://python.viam.dev/autoapi/viam/proto/common/index.html#viam.proto.common.ResourceName): List of all known resource names. A property of a [RobotClient](https://python.viam.dev/autoapi/viam/robot/client/index.html)
-
-``` python
-resource_names = robot.resource_names
-```
-
-{{% /tab %}}
-{{% tab name="Go" %}}
-
-**Parameters:**
-
-- None
-
-**Returns:**
-
-- [([]resource.Name)](https://pkg.go.dev/go.viam.com/rdk/resource#Name): List of all known resource names.
-
-```go
-resource_names := robot.ResourceNames()
-```
-
-For more information, see the [Go SDK Docs](https://pkg.go.dev/go.viam.com/rdk/robot#Robot).
-
-{{% /tab %}}
-{{% tab name="TypeScript" %}}
-
-**Parameters:**
-
-- None
-
-**Returns:**
-
-- [(ResourceName.AsObject[])](https://ts.viam.dev/modules/commonApi.ResourceName-1.html): List of all known resource names.
-
-```typescript
-// Get a list of all resources on the robot.
-const resource_names = await robot.resourceNames();
-```
-
-For more information, see the [Typescript SDK Docs](https://ts.viam.dev/classes/RobotClient.html).
-
-{{% /tab %}}
-{{< /tabs >}}
+{{< readfile "/static/include/services/apis/cloud.md" >}}
diff --git a/docs/program/apis/cloud.md b/docs/program/apis/cloud.md
new file mode 100644
index 0000000000..459edc7203
--- /dev/null
+++ b/docs/program/apis/cloud.md
@@ -0,0 +1,219 @@
+---
+title: "Manage Your Fleet with Viam's Cloud API"
+linkTitle: "Cloud Management"
+weight: 20
+type: "docs"
+description: "Use the cloud app API with Viam's client SDKs to manage your robot fleet with code."
+tags: ["cloud", "sdk", "viam-server", "networking", "apis", "robot api", "cloud management"]
+---
+
+The cloud app API allows you to [manage your robot fleet](/manage/fleet/) with code instead of with the graphical interface of the [Viam app](https://app.viam.com/).
+With it you can
+
+- create and manage organizations, locations, and individual robots
+- manage permissions and authorization
+- create and manage fragments
+
+{{% alert title="Support Notice" color="note" %}}
+
+Cloud app API methods are only available in the Python SDK.
+
+{{% /alert %}}
+
+## Establish a connection
+
+To use the Viam cloud app API, you first need to instantiate a [`ViamClient`](https://python.viam.dev/autoapi/viam/app/viam_client/index.html#viam.app.viam_client.ViamClient) and then instantiate an [`AppClient`](https://python.viam.dev/autoapi/viam/app/app_client/index.html#viam.app.app_client.AppClient).
+See the following example for reference.
+To find the location secret, go to [Viam app](https://app.viam.com/), and go to the [**Code sample**](https://docs.viam.com/manage/fleet/robots/#code-sample) tab of any of the robots in the location.
+Toggle **Include secret** on and copy the `payload`.
+For the URL, use the address of any of the robots in the location (also found on the **Code sample** tab).
+
+```python {class="line-numbers linkable-line-numbers"}
+import asyncio
+
+from viam.rpc.dial import DialOptions, Credentials
+from viam.app.viam_client import ViamClient
+
+async def connect() -> ViamClient:
+ dial_options = DialOptions(
+ auth_entity='mrroboto.this_is_just_an_example.viam.cloud', # The URL of a robot in the location.
+ credentials=Credentials(
+ type='robot-location-secret',
+ payload='YOUR LOCATION SECRET' # The location secret
+ )
+ )
+ return await ViamClient.create_from_dial_options(dial_options)
+
+async def main():
+
+ # Make a ViamClient
+ viam_client = await connect()
+ # Instantiate an AppClient called "cloud" to run the cloud app API methods on
+ cloud = viam_client.app_client
+
+ viam_client.close()
+
+if __name__ == '__main__':
+ asyncio.run(main())
+```
+
+Once you have instantiated an `AppClient`, you can run the following [API methods](#api) against the `AppClient` object (named `cloud` in the examples).
+
+## API
+
+The cloud API supports the following methods (among [others](https://python.viam.dev/autoapi/viam/app/app_client/index.html#viam.app.app_client.AppClient)):
+
+{{< readfile "/static/include/services/apis/cloud.md" >}}
+
+### ListOrganizations
+
+List the organizations the user is an authorized user of.
+
+{{< tabs >}}
+{{% tab name="Python" %}}
+
+**Parameters:**
+
+- None
+
+**Returns:**
+
+- [(List[viam.proto.app.Organization])](https://python.viam.dev/autoapi/viam/proto/app/index.html#viam.proto.app.Organization): A list of the organization or organizations of which the user is an authorized owner.
+
+```python {class="line-numbers linkable-line-numbers"}
+org_list = await cloud.list_organizations()
+```
+
+For more information, see the [Python SDK Docs](https://python.viam.dev/autoapi/viam/app/app_client/index.html#viam.app.app_client.AppClient.list_organizations).
+
+{{% /tab %}}
+{{< /tabs >}}
+
+### ListOrganizationMembers
+
+List the members and invites of the organization that you are currently authenticated to.
+
+{{< tabs >}}
+{{% tab name="Python" %}}
+
+**Parameters:**
+
+- None
+
+**Returns:**
+
+- (Tuple[List[[viam.proto.app.OrganizationMember]](https://python.viam.dev/autoapi/viam/proto/app/index.html#viam.proto.app.OrganizationMember)], List[[viam.proto.app.OrganizationInvite]](https://python.viam.dev/autoapi/viam/proto/app/index.html#viam.proto.app.OrganizationInvite)): A tuple containing two lists:
+ - The first (`[0]`) is a list of organization members.
+ - The second (`[1]`) is a list of organization invites.
+
+```python {class="line-numbers linkable-line-numbers"}
+member_list, invite_list = await cloud.list_organization_members()
+```
+
+For more information, see the [Python SDK Docs](https://python.viam.dev/autoapi/viam/app/app_client/index.html#viam.app.app_client.AppClient.list_organization_members).
+
+{{% /tab %}}
+{{< /tabs >}}
+
+### GetOrganizationNamespaceAvailability
+
+Check the availability of an organization namespace.
+
+{{< tabs >}}
+{{% tab name="Python" %}}
+
+**Parameters:**
+
+- `public_namespace` [(string)](https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str): The organization namespace to check.
+Namespaces can only contain lowercase alphanumeric and dash characters.
+
+**Raises:**
+
+- `GRPCError`: This error is raised if an invalid namespace (for example, `""`) is provided.
+
+**Returns:**
+
+- [(bool)](https://docs.python.org/3/library/stdtypes.html#bltin-boolean-values): `True` if the provided namespace is available.
+
+```python {class="line-numbers linkable-line-numbers"}
+available = await cloud.get_organization_namespace_availability(public_namespace="my-cool-organization")
+```
+
+For more information, see the [Python SDK Docs](https://python.viam.dev/autoapi/viam/app/app_client/index.html#viam.app.app_client.AppClient.get_organization_namespace_availability).
+
+{{% /tab %}}
+{{< /tabs >}}
+
+### UpdateOrganizationInviteAuthorizations
+
+Update (add or remove) the authorizations attached to an organization invite that has already been created.
+If an invitation has only one authorization and you want to remove it, delete the invitation instead of using this method.
+
+{{< tabs >}}
+{{% tab name="Python" %}}
+
+**Parameters:**
+
+- `email` [(string)](https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str): Email of the user the invite was sent to.
+- `add_authorizations` [(Optional[List[viam.proto.app.Authorization]])](https://python.viam.dev/autoapi/viam/proto/app/index.html#viam.proto.app.Authorization): Optional list of authorizations to add to the invite.
+- `remove_authorizations` [(Optional[List[viam.proto.app.Authorization]])](https://python.viam.dev/autoapi/viam/proto/app/index.html#viam.proto.app.Authorization): Optional list of authorizations to remove from the invite.
+
+**Raises:**
+
+- `GRPCError`: This error is raised if no authorizations are passed or if an invalid combination of authorizations is passed (for example, an authorization to remove when the invite only contains one authorization).
+
+**Returns:**
+
+- [(OrganizationInvite)](https://python.viam.dev/autoapi/viam/proto/app/index.html#viam.proto.app.OrganizationInvite): The updated invitation.
+
+```python {class="line-numbers linkable-line-numbers"}
+from viam.proto.app import Authorization
+authorization_to_add=Authorization(
+ authorization_type="some type of auth",
+ authorization_id="identifier",
+ resource_type="abc",
+ resource_id="resource-identifier123",
+ identity_id="id12345",
+ organization_id="org_id_123"
+)
+
+update_invite = await cloud.update_organization_invite_authorizations(
+ email="notarealemail@viam.com",
+ remove_authorizations=[authorization_to_add]
+)
+```
+
+For more information, see the [Python SDK Docs](https://python.viam.dev/autoapi/viam/app/app_client/index.html#viam.app.app_client.AppClient.update_organization_invite_authorizations).
+
+{{% /tab %}}
+{{< /tabs >}}
+
+### NewRobot
+
+Create a new robot.
+
+{{< tabs >}}
+{{% tab name="Python" %}}
+
+**Parameters:**
+
+- `name` [(string)](https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str): Name of the new robot.
+- `location_id` [(Optional[string])](https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str): ID of the location to create the new robot in.
+ Defaults to the current authorized location.
+
+**Raises:**
+
+- `GRPCError`: This error is raised if an invalid location ID is passed, or if one isn't passed and no location ID was provided at `AppClient` instantiation.
+
+**Returns:**
+
+- [(string)](https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str): The new robot's ID.
+
+```python {class="line-numbers linkable-line-numbers"}
+new_robot_id = await cloud.new_robot(name="beepboop")
+```
+
+For more information, see the [Python SDK Docs](https://python.viam.dev/autoapi/viam/app/app_client/index.html#viam.app.app_client.AppClient.get_organization_namespace_availability).
+
+{{% /tab %}}
+{{< /tabs >}}
diff --git a/docs/program/apis/robot.md b/docs/program/apis/robot.md
new file mode 100644
index 0000000000..d7c743c7fe
--- /dev/null
+++ b/docs/program/apis/robot.md
@@ -0,0 +1,409 @@
+---
+title: "Manage Robots with Viam's Robot API"
+linkTitle: "Robot Management"
+weight: 20
+type: "docs"
+description: "How to use the Robot API to monitor and manage your robots."
+tags: ["robot state", "sdk", "apis", "robot api"]
+---
+
+The *robot API* is the application programming interface that manages each of your robots running `viam-server`.
+It is the API for high level operations of each robot {{< glossary_tooltip term_id="part" text="part" >}}.
+To interact with the robot API with Viam's SDKs, instantiate a `RobotClient` ([gRPC](https://grpc.io/) client) and use that class for all interactions.
+
+These are some of the supported robot API methods. For a full list [see GitHub](https://python.viam.dev/autoapi/viam/proto/robot/index.html#module-viam.proto.robot).
+
+{{< readfile "/static/include/services/apis/robot.md" >}}
+
+### DiscoverComponents
+
+Get a list of discovered component configurations.
+
+{{< tabs >}}
+{{% tab name="Python" %}}
+
+**Parameters:**
+
+- `queries` [(List [viam.proto.robot.DiscoveryQuery])](https://python.viam.dev/autoapi/viam/proto/robot/index.html#viam.proto.robot.DiscoveryQuery): A list of [tuples of API and model](https://python.viam.dev/autoapi/viam/proto/robot/index.html#viam.proto.robot.DiscoveryQuery) that you want to retrieve the component configurations corresponding to.
+
+**Returns:**
+
+- [(List[viam.proto.robot.Discovery])](https://python.viam.dev/autoapi/viam/proto/robot/index.html#viam.proto.robot.Discovery): The list of discovered component configurations corresponding to `queries`.
+
+``` python
+# Define a new discovery query.
+q = robot.DiscoveryQuery(subtype=acme.API, model="some model")
+
+# Define a list of discovery queries.
+qs = [q]
+
+# Get component configurations with these queries.
+component_configs = await robot.discover_components(qs)
+```
+
+For more information, see the [Python SDK Docs](https://python.viam.dev/autoapi/viam/robot/client/index.html#viam.robot.client.RobotClient.discover_components)
+
+{{% /tab %}}
+{{% tab name="Go" %}}
+
+**Parameters:**
+
+- `ctx` [(Context)](https://pkg.go.dev/context): A Context carries a deadline, a cancellation signal, and other values across API boundaries.
+- `qs` [([]resource.DiscoveryQuery)](https://pkg.go.dev/go.viam.com/rdk/resource#DiscoveryQuery): A list of [tuples of API and model](https://pkg.go.dev/go.viam.com/rdk/resource#DiscoveryQuery) that you want to retrieve the component configurations corresponding to.
+
+**Returns:**
+
+- [([]resource.Discovery)](https://pkg.go.dev/go.viam.com/rdk/resource#Discovery): The search query `qs` and the corresponding list of discovered component configurations as an interface called `Results`.
+`Results` may be comprised of primitives, a list of primitives, maps with string keys (or at least can be decomposed into one), or lists of the forementioned type of maps.
+- [(error)](https://pkg.go.dev/builtin#error): An error, if one occurred.
+
+```go
+// Define a new discovery query.
+q := resource.NewDiscoveryQuery(acme.API, resource.Model{Name: "some model"})
+
+// Define a list of discovery queries.
+qs := []resource.DiscoverQuery{q}
+
+// Get component configurations with these queries.
+component_configs, err := robot.DiscoverComponents(ctx.Background(), qs)
+```
+
+For more information, see the [Go SDK Docs](https://pkg.go.dev/go.viam.com/rdk/robot#Robot).
+
+{{% /tab %}}
+{{% tab name="TypeScript" %}}
+
+**Parameters:**
+
+- `queries` [(DiscoveryQuery[])](https://ts.viam.dev/classes/robotApi.DiscoveryQuery.html): An array of [tuples of API and model](https://ts.viam.dev/classes/robotApi.DiscoveryQuery.html#constructor) that you want to retrieve the component configurations corresponding to.
+
+**Returns:**
+
+- [(Discovery[])](https://ts.viam.dev/classes/robotApi.Discovery.html): List of discovered component configurations.
+
+```typescript
+// Define a new discovery query.
+const q = new proto.DiscoveryQuery(acme.API, resource.Model{Name: "some model"})
+
+// Define an array of discovery queries.
+let qs: proto.DiscoveryQuery[] = [q]
+
+// Get the array of discovered component configurations.
+const componentConfigs = await robot.discoverComponents(queries);
+```
+
+For more information, see the [Typescript SDK Docs](https://ts.viam.dev/classes/RobotClient.html).
+
+{{% /tab %}}
+{{< /tabs >}}
+
+### FrameSystemConfig
+
+Get the configuration of the frame system of a given robot.
+
+{{< tabs >}}
+{{% tab name="Python" %}}
+
+**Parameters:**
+
+- `additional_transforms` [(Optional[List[viam.proto.common.Transform]])](https://python.viam.dev/autoapi/viam/proto/common/index.html#viam.proto.common.Transform): A optional list of [additional transforms](/services/frame-system/#additional-transforms).
+
+**Returns:**
+
+- `frame_system` [(List[FrameSystemConfig])](https://python.viam.dev/autoapi/viam/proto/robot/index.html#viam.proto.robot.FrameSystemConfig): The configuration of a given robot’s frame system.
+
+```python {class="line-numbers linkable-line-numbers"}
+# Get a list of each of the reference frames configured on the robot.
+frame_system = await robot.get_frame_system_config()
+print(f"frame system donfiguration: {frame_system}")
+```
+
+For more information, see the [Python SDK Docs](https://python.viam.dev/autoapi/viam/robot/client/index.html#viam.robot.client.RobotClient.get_frame_system_config).
+
+{{% /tab %}}
+{{% tab name="Go" %}}
+
+**Parameters:**
+
+- `ctx` [(Context)](https://pkg.go.dev/context): A Context carries a deadline, a cancellation signal, and other values across API boundaries.
+
+**Returns:**
+
+- [(error)](https://pkg.go.dev/builtin#error): An error, if one occurred.
+- [(framesystem.Config)](https://pkg.go.dev/go.viam.com/rdk/robot/framesystem#Config): The configuration of the given robot’s frame system.
+
+For more information, see the [Go SDK Docs](https://pkg.go.dev/go.viam.com/rdk/robot#Robot).
+
+```go {class="line-numbers linkable-line-numbers"}
+// Print the frame system configuration
+frameSystem, err := robot.FrameSystemConfig(context.Background(), nil)
+fmt.Println(frameSystem)
+```
+
+{{% /tab %}}
+{{% tab name="TypeScript" %}}
+
+**Parameters:**
+
+- `transforms` [(Transform[])](https://ts.viam.dev/classes/commonApi.Transform.html): An optional array of [additional transforms](/services/frame-system/#additional-transforms).
+
+**Returns:**
+
+- [(FrameSystemConfig[])](https://ts.viam.dev/classes/robotApi.FrameSystemConfig.html): An array of individual parts that make up a robot's frame system.
+
+For more information, see the [TypeScript SDK Docs](https://ts.viam.dev/classes/RobotClient.html#frameSystemConfig).
+
+```typescript {class="line-numbers linkable-line-numbers"}
+// Get the frame system configuration.
+console.log('FrameSytemConfig:', await robot.frameSystemConfig());
+```
+
+{{% /tab %}}
+{{< /tabs >}}
+
+### Status
+
+Get the status of the resources on the robot.
+You can provide a list of ResourceNames for which you want statuses.
+If no names are passed in, the status of every resource configured on the robot is returned.
+
+{{< tabs >}}
+{{% tab name="Python" %}}
+
+**Parameters:**
+
+- `resourceNames` [(Optional[List[viam.proto.common.ResourceName]])](https://docs.python.org/library/typing.html#typing.Optional): An optional list of ResourceNames for components you want the status of.
+If no names are passed in, all resource statuses are returned.
+
+**Returns:**
+
+- [(List[str])](https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str): A list containing the status of each resource.
+
+For more information, see the [Python SDK Docs](https://python.viam.dev/autoapi/viam/robot/client/index.html#viam.robot.client.RobotClient.get_status).
+
+```python {class="line-numbers linkable-line-numbers"}
+# Get the status of the resources on the robot.
+statuses = await robot.get_status()
+```
+
+{{% /tab %}}
+{{% tab name="Go" %}}
+
+**Parameters:**
+
+- `ctx` [(Context)](https://pkg.go.dev/context): A Context carries a deadline, a cancellation signal, and other values across API boundaries.
+- `resourceNames` [([]resource.Name)](https://pkg.go.dev/go.viam.com/rdk/resource#Name): An optional list of ResourceNames for components you want the status of.
+If no names are passed in, all resource statuses are returned.
+
+**Returns:**
+
+- [([]Status)](https://pkg.go.dev/go.viam.com/rdk/robot#Status): Status of each resource.
+- [(error)](https://pkg.go.dev/builtin#error): An error, if one occurred.
+
+For more information, see the [Go SDK Docs](https://pkg.go.dev/go.viam.com/rdk/robot#Robot).
+
+```go {class="line-numbers linkable-line-numbers"}
+// Get the status of the resources on the robot.
+status, err = robot.Status(ctx.Background())
+```
+
+{{% /tab %}}
+{{% tab name="TypeScript" %}}
+
+**Parameters:**
+
+- `resourceNames` [(commonApi.ResourceName[])](https://ts.viam.dev/classes/commonApi.ResourceName.html): An optional array of ResourceNames for components you want the status of.
+If no names are passed in, all resource statuses are returned.
+
+**Returns:**
+
+- [(robotApi.Status[])](https://ts.viam.dev/classes/robotApi.Status.html): An array containing the status of each resource.
+
+For more information, see the [TypeScript SDK Docs](https://ts.viam.dev/classes/RobotClient.html#transformPCD).
+
+```typescript {class="line-numbers linkable-line-numbers"}
+// Get the status of the resources on the robot.
+const status = await robot.getStatus();
+```
+
+{{% /tab %}}
+{{< /tabs >}}
+
+### Close
+
+Close the underlying connections and stop any periodic tasks across all constituent parts of the robot.
+{{< tabs >}}
+{{% tab name="Python" %}}
+
+**Parameters:**
+
+- None
+
+**Returns:**
+
+- None
+
+For more information, see the [Python SDK Docs](https://python.viam.dev/autoapi/viam/robot/client/index.html#viam.robot.client.RobotClient.close).
+
+```python {class="line-numbers linkable-line-numbers"}
+# Cleanly close the underlying connections and stop any periodic tasks.
+await robot.close()
+```
+
+{{% /tab %}}
+{{% tab name="Go" %}}
+
+**Parameters:**
+
+- `ctx` [(Context)](https://pkg.go.dev/context): A Context carries a deadline, a cancellation signal, and other values across API boundaries.
+
+**Returns:**
+
+- [(error)](https://pkg.go.dev/builtin#error): An error, if one occurred.
+
+For more information, see the [Go SDK Docs](https://pkg.go.dev/go.viam.com/rdk/robot#Robot).
+
+```go {class="line-numbers linkable-line-numbers"}
+// Cleanly close the underlying connections and stop any periodic tasks,
+err := robot.Close(ctx.Background())
+```
+
+{{% /tab %}}
+{{% tab name="TypeScript" %}}
+
+**Parameters:**
+
+- None
+
+**Returns:**
+
+- None
+
+For more information, see the [TypeScript SDK Docs](https://ts.viam.dev/classes/RobotClient.html#disconnect).
+
+```typescript {class="line-numbers linkable-line-numbers"}
+// Cleanly close the underlying connections and stop any periodic tasks
+await robot.disconnect();
+```
+
+{{% /tab %}}
+{{< /tabs >}}
+
+### StopAll
+
+Cancel all current and outstanding operations for the robot and stop all actuators and movement.
+
+{{< tabs >}}
+{{% tab name="Python" %}}
+
+**Parameters:**
+
+- `extra` [(Dict[viam.proto.common.ResourceName, Dict[str, Any]])](https://python.viam.dev/autoapi/viam/proto/common/index.html#viam.proto.common.ResourceName): Any extra parameters to pass to the resources’ stop methods, keyed on each resource’s [`ResourceName`](https://python.viam.dev/autoapi/viam/proto/common/index.html#viam.proto.common.ResourceName).
+
+**Returns:**
+
+- None
+
+For more information, see the [Python SDK Docs](https://python.viam.dev/autoapi/viam/robot/client/index.html#viam.robot.client.RobotClient.stop_all).
+
+```python {class="line-numbers linkable-line-numbers"}
+# Cancel all current and outstanding operations for the robot and stop all actuators and movement.
+await robot.stop_all()
+```
+
+{{% /tab %}}
+{{% tab name="Go" %}}
+
+**Parameters:**
+
+- `ctx` [(Context)](https://pkg.go.dev/context): A Context carries a deadline, a cancellation signal, and other values across API boundaries.
+- `extra` [(map[resource.Name]map[string]interface{})](https://pkg.go.dev/go.viam.com/rdk/resource#Name): Any extra parameters to pass to the resources’ stop methods, keyed on each resource’s [`Name`](https://pkg.go.dev/go.viam.com/rdk/resource#Name).
+
+**Returns:**
+
+- [(error)](https://pkg.go.dev/builtin#error): An error, if one occurred.
+
+For more information, see the [Go SDK Docs](https://pkg.go.dev/go.viam.com/rdk/robot#Robot).
+
+```go {class="line-numbers linkable-line-numbers"}
+// Cancel all current and outstanding operations for the robot and stop all actuators and movement.
+err := robot.StopAll(ctx.Background())
+```
+
+{{% /tab %}}
+{{% tab name="TypeScript" %}}
+
+**Parameters:**
+
+- None
+
+**Returns:**
+
+- None
+
+For more information, see the [TypeScript SDK Docs](https://ts.viam.dev/classes/RobotClient.html#stopAll).
+
+```typescript {class="line-numbers linkable-line-numbers"}
+// Cancel all current and outstanding operations for the robot and stop all actuators and movement.
+await robot.stopAll();
+```
+
+{{% /tab %}}
+{{< /tabs >}}
+
+### ResourceNames
+
+Get a list of all known resource names connected to this robot.
+
+{{< tabs >}}
+{{% tab name="Python" %}}
+
+**Parameters:**
+
+- None
+
+**Returns:**
+
+- [(List[viam.proto.common.ResourceName])](https://python.viam.dev/autoapi/viam/proto/common/index.html#viam.proto.common.ResourceName): List of all known resource names. A property of a [RobotClient](https://python.viam.dev/autoapi/viam/robot/client/index.html)
+
+``` python
+resource_names = robot.resource_names
+```
+
+{{% /tab %}}
+{{% tab name="Go" %}}
+
+**Parameters:**
+
+- None
+
+**Returns:**
+
+- [([]resource.Name)](https://pkg.go.dev/go.viam.com/rdk/resource#Name): List of all known resource names.
+
+```go
+resource_names := robot.ResourceNames()
+```
+
+For more information, see the [Go SDK Docs](https://pkg.go.dev/go.viam.com/rdk/robot#Robot).
+
+{{% /tab %}}
+{{% tab name="TypeScript" %}}
+
+**Parameters:**
+
+- None
+
+**Returns:**
+
+- [(ResourceName.AsObject[])](https://ts.viam.dev/modules/commonApi.ResourceName-1.html): List of all known resource names.
+
+```typescript
+// Get a list of all resources on the robot.
+const resource_names = await robot.resourceNames();
+```
+
+For more information, see the [Typescript SDK Docs](https://ts.viam.dev/classes/RobotClient.html).
+
+{{% /tab %}}
+{{< /tabs >}}
diff --git a/docs/program/apis/sessions.md b/docs/program/apis/sessions.md
index a652200508..cf48370682 100644
--- a/docs/program/apis/sessions.md
+++ b/docs/program/apis/sessions.md
@@ -1,6 +1,6 @@
---
title: "Session Management with Viam's Client SDKs"
-linkTitle: "Session Management API"
+linkTitle: "Session Management"
weight: 20
type: "docs"
description: "How to use the session management API with Viam's Client SDKs."
diff --git a/docs/program/connectivity.md b/docs/program/connectivity.md
new file mode 100644
index 0000000000..6098c788f1
--- /dev/null
+++ b/docs/program/connectivity.md
@@ -0,0 +1,27 @@
+---
+title: "Client Sessions and Robot Network Connectivity"
+linkTitle: "Network Connectivity Issues"
+weight: 20
+type: "docs"
+description: "Whan a robot loses its connection to the internet, all client sessions will timeout and end by default."
+tags: ["client", "sdk", "viam-server", "networking", "apis", "robot api", "session"]
+---
+
+What happens when your robot loses its connection to the internet over a LAN or WAN and can no longer communicate with clients through [the Viam app](https://app.viam.com).
+
+## How does `viam-server` work if your robot loses its network connection?
+
+When a robot loses its connection over LAN or WAN, it can no longer communicate with clients through [the Viam app](https://app.viam.com).
+When no heartbeat has been received over a timeout period, `viam-server` will end any current client [*sessions*](/program/apis/sessions/) on this robot.
+
+## What happens to clients connected to the robot when your robot loses its network connection?
+
+When your client cannot connect to your robot's `viam-server` instance, all client operations will timeout automatically and halt.
+Any active commands will be cancelled, stopping any moving parts, and no new commands will be able to reach the robot until the connection is restored.
+
+### How do Viam's client SDKs work if your robot loses its network connection?
+
+As a client of your robot, Viam's SDKs will by default have their session ended when the robot loses its connection to the internet.
+
+To disable the default behavior here and manage resource timeout and reconfiguration over a networking session yourself, follow [these instructions](/program/apis/sessions/).
+[Disable the default behavior](/program/apis/sessions/#disable-default-session-management) of session management, then utilize [Viam's SDKs](/program/) in your code to make calls to [the session management API](https://pkg.go.dev/go.viam.com/rdk/session#hdr-API).
diff --git a/docs/services/robot-service.md b/docs/services/robot-service.md
index 114d2c6f30..e23f1175a7 100644
--- a/docs/services/robot-service.md
+++ b/docs/services/robot-service.md
@@ -8,8 +8,11 @@ weight: 10
tags: ["robot state", "services"]
# SME: Cheuk
---
-Robot Service constitutes a minimal set of APIs that most robots (Viam Server, [Viam Python SDK](https://python.viam.dev/) and various SDKs) should support.
-Users will likely use the Robot Service as an entrypoint to interact with Viam robots and provide a way to get updates from the robot as a whole.
+
+The Robot Service refers to the minimum set of APIs that most robots running `viam-server` support.
+This means that any of the various robot clients in Viam, like the Python SDK, Go Client SDK, or modular resources, should also support methods to interface with these same APIs from the client (instead of server) side.
+If you are implementing your own client, keep this in mind.
+Use the Robot Service as an entrypoint to interact with Viam robots and provide a way to get updates from the robot as a whole.
The below is a current list of interfaces provided by the Robot Service.
diff --git a/docs/services/vision/classification.md b/docs/services/vision/classification.md
index f3ad526cba..598890450a 100644
--- a/docs/services/vision/classification.md
+++ b/docs/services/vision/classification.md
@@ -139,7 +139,7 @@ Do not pass a transform camera that already has the "detections" or "classificat
{{% tab name="Python" %}}
```python {class="line-numbers linkable-line-numbers"}
-from viam.services.vision import VisionClient, VisModelConfig, VisModelType
+from viam.services.vision import VisionClient
robot = await connect()
# Grab camera from the robot
@@ -191,7 +191,7 @@ if len(directClassifications) > 0 {
logger.Info(classifications[0])
}
-// If you need to store the image, get the image first
+// If you need to store the image, get the image first
// and then run classifications on it. This process is slower:
// Get the stream from a camera
@@ -225,7 +225,7 @@ If you would like to test your classifier with existing images, load the images
{{% tab name="Python" %}}
```python {class="line-numbers linkable-line-numbers"}
-from viam.services.vision import VisionClient, VisModelConfig, VisModelType
+from viam.services.vision import VisionClient
from PIL import Image
robot = await connect()
diff --git a/docs/services/vision/detection.md b/docs/services/vision/detection.md
index 4def1ff893..02335d6e5a 100644
--- a/docs/services/vision/detection.md
+++ b/docs/services/vision/detection.md
@@ -267,7 +267,7 @@ If you intend to use the detector with a camera that is part of your robot, you
{{% tab name="Python" %}}
```python {class="line-numbers linkable-line-numbers"}
-from viam.services.vision import VisionClient, VisModelConfig, VisModelType
+from viam.services.vision import VisionClient
robot = await connect()
# Grab camera from the robot
@@ -352,7 +352,7 @@ If you would like to test your detector with existing images, load the images an
{{% tab name="Python" %}}
```python {class="line-numbers linkable-line-numbers"}
-from viam.services.vision import VisionClient, VisModelConfig, VisModelType
+from viam.services.vision import VisionClient
from PIL import Image
robot = await connect()
diff --git a/docs/services/vision/segmentation.md b/docs/services/vision/segmentation.md
index 74452224a0..dc3d893713 100644
--- a/docs/services/vision/segmentation.md
+++ b/docs/services/vision/segmentation.md
@@ -302,7 +302,7 @@ The following code uses the [`GetObjectPointClouds`](/services/vision/#getobject
{{% tab name="Python" %}}
```python {class="line-numbers linkable-line-numbers"}
-from viam.services.vision import VisionClient, VisModelConfig, VisModelType
+from viam.services.vision import VisionClient
robot = await connect()
diff --git a/docs/tutorials/configure/build-a-mock-robot.md b/docs/tutorials/configure/build-a-mock-robot.md
index 893eda72c0..0161a03c96 100644
--- a/docs/tutorials/configure/build-a-mock-robot.md
+++ b/docs/tutorials/configure/build-a-mock-robot.md
@@ -14,7 +14,7 @@ tags: ["mock", "simulation"]
authors: []
languages: [ "python", "go" ]
viamresources: [ "board", "arm", "motor" ]
-level: "Intermediate"
+level: "Beginner"
date: "2022-10-11"
# updated: ""
cost: "0"
diff --git a/docs/tutorials/configure/scuttlebot.md b/docs/tutorials/configure/scuttlebot.md
index 84668c4ca8..1b6fbddaa1 100644
--- a/docs/tutorials/configure/scuttlebot.md
+++ b/docs/tutorials/configure/scuttlebot.md
@@ -3,16 +3,16 @@ title: "Configure a SCUTTLE Robot"
linkTitle: "Configure a SCUTTLE Robot"
type: "docs"
description: "Configure a SCUTTLE robot on the Viam platform."
-image: "/tutorials/scuttlebot/createcomponent.png"
-images: ["/tutorials/scuttlebot/createcomponent.png"]
-imageAlt: "The Viam app UI showing the Config tab of a robot."
+image: "/tutorials/scuttlebot/scuttle-on-floor-cropped.png"
+images: ["/tutorials/scuttlebot/scuttle-on-floor-cropped.png"]
+imageAlt: "A SCUTTLE robot on a carpeted floor."
tags: ["base", "camera", "raspberry pi", "scuttle"]
aliases:
- "/tutorials/scuttlebot"
- "/tutorials/scuttlebot/scuttlebot"
authors: []
languages: [ "python", "go" ]
-viamresources: [ "board", "motor", "camera" ]
+viamresources: [ "board", "motor", "camera", "base", "encoder" ]
level: "Beginner"
date: "2022-08-02"
updated: "2023-08-05"
@@ -32,7 +32,7 @@ cost: 540
1. Create a *robot* and follow the setup instructions until the robot successfully connects to the Viam app.
1. Navigate to the robot's **Config** tab.
- ![The Viam app UI showing the config tab of the robot.](/tutorials/scuttlebot/createcomponent.png)
+![A SCUTTLE robot on a carpeted floor.](/tutorials/scuttlebot/scuttle-on-floor.png)
## Configure the board
@@ -41,10 +41,9 @@ Add your first component, the [board](/components/board/):
{{< tabs name="Configure an pi Board" >}}
{{% tab name="Config Builder" %}}
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter `local` as the name for your board, select the type `board`, and select the `pi` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `board` type, then select the `pi` model.
+Enter `local` as the name for your board and click **Create**.
Click on **Show more** and add `I2C` with **name** `main` and **bus** `1`.
@@ -83,10 +82,9 @@ Next, configure the left and right encoders as follows:
### Left encoder
-Navigate to the **Create component** menu.
-Enter `lenc` as the **name** for your encoder, select the type `encoder`, and select the `AMS-AS5048` model.
-
Click **Create component**.
+Select the `encoder` type, then select the `AMS-AS5048` model.
+Enter `lenc` as the name for your encoder and click **Create**.
Click the **board** drop-down list and select the name of your board, `local`.
@@ -96,10 +94,9 @@ In the **i2c bus** field type `main`, and in the **i2c address** field type `64`
### Right encoder
-Navigate to the **Create component** menu.
-Enter `renc` as the **name** for your encoder, select the type `encoder`, and select the `AMS-AS5048` model.
-
Click **Create component**.
+Select the `encoder` type, then select the `AMS-AS5048` model.
+Enter `renc` as the name for your encoder and click **Create**.
Click the **board** drop-down list and select the name of your board, `local`.
@@ -151,12 +148,11 @@ The next step is to add the motors and make them spin the wheels.
{{< tabs name="gpio-config">}}
{{% tab name="Config Builder" %}}
-**Right Motor:**
-
-Navigate to the **Create component** menu.
-Enter `right` for your motor name, select the type `motor`, and select the `gpio` model.
+### Right motor
Click **Create component**.
+Select the `motor` type, then select the `gpio` model.
+Enter `right` as the name for your encoder and click **Create**.
Then from the **Board** drop-down, select `local`, the Raspberry Pi the motor is wired to.
@@ -171,12 +167,11 @@ Next, describe how the motor is wired to the Pi:
![The motor config panel.](/tutorials/scuttlebot/pi-wheel.png)
-**Left Motor:**
-
-Navigate to the **Create component** menu.
-Enter `left` for your motor name, select the type `motor`, and select the `gpio` model.
+### Left motor
Click **Create component**.
+Select the `motor` type, then select the `gpio` model.
+Enter `left` as the name for your encoder and click **Create**.
Then select `local` from the **Board** drop-down to choose the Raspberry Pi the motor is wired to.
@@ -268,10 +263,9 @@ Configuring a base component also provides you with a nice UI for moving the rov
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your base, select the type `base`, and select the `wheeled` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `base` type, then select the `wheeled` model.
+Enter a name for your base and click **Create**.
{{< imgproc src="/components/base/wheeled-base-ui-config.png" alt="An example configuration for a wheeled base." resize="600x" >}}
@@ -295,8 +289,9 @@ Click **Create component**.
"attributes": {
"board": "local",
"pins": {
- "dir": "16",
- "pwm": "15"
+ "pwm": "",
+ "a": "16",
+ "b": "15",
}
},
"model": "gpio",
@@ -307,8 +302,9 @@ Click **Create component**.
"attributes": {
"board": "local",
"pins": {
- "dir": "13",
- "pwm": "11"
+ "pwm": "",
+ "a": "12",
+ "b": "11",
}
},
"model": "gpio",
@@ -365,10 +361,9 @@ Finally, add a camera to your SCUTTLE robot.
{{% tab name="Config Builder" %}}
Navigate to the **Config** tab of your robot's page in [the Viam app](https://app.viam.com).
-Click on the **Components** subtab and navigate to the **Create component** menu.
-Enter a name for your camera, select the type `camera`, and select the `webcam` model.
-
-Click **Create component**.
+Click on the **Components** subtab and click **Create component**.
+Select the `camera` type, then select the `webcam` model.
+Enter a name for your camera and click **Create**.
{{< imgproc src="/components/camera/configure-webcam.png" alt="Configuration of a webcam camera in the Viam app config builder." resize="600x" >}}
diff --git a/docs/tutorials/control/scuttle-gamepad.md b/docs/tutorials/control/scuttle-gamepad.md
index ce54d8cf14..da14b60fce 100644
--- a/docs/tutorials/control/scuttle-gamepad.md
+++ b/docs/tutorials/control/scuttle-gamepad.md
@@ -54,12 +54,13 @@ Go to your rover's **Config** tab on the [Viam app](https://app.viam.com/).
{{< tabs >}}
{{% tab name="Config Builder" %}}
-In the **Create component** panel, configure a [gamepad](/components/input-controller/gamepad/):
+Configure a [gamepad](/components/input-controller/gamepad/):
-- Enter `my-gamepad` as the component **Name**.
+- Click **Create component**.
- Select `input_controller` for the component **Type**.
- Select `gamepad` for the **Model**.
-- Click **Create component**.
+- Enter `my-gamepad` as the component **Name**.
+- Click **Create**.
![Blank configuration JSON](/tutorials/scuttle-gamepad/gamepad-config.png)
diff --git a/docs/tutorials/custom/_index.md b/docs/tutorials/custom/_index.md
index 51078ec3bd..cbcdb427bc 100644
--- a/docs/tutorials/custom/_index.md
+++ b/docs/tutorials/custom/_index.md
@@ -1,6 +1,6 @@
---
-title: "Custom Resource Tutorials"
-linkTitle: "Custom Resources"
+title: "Modular Resource Tutorials"
+linkTitle: "Modular Resources"
childTitleEndOverwrite: "Tutorial"
weight: 50
type: docs
diff --git a/docs/tutorials/custom/controlling-an-intermode-rover-canbus.md b/docs/tutorials/custom/controlling-an-intermode-rover-canbus.md
index e9e4ef31ce..56cc80c467 100644
--- a/docs/tutorials/custom/controlling-an-intermode-rover-canbus.md
+++ b/docs/tutorials/custom/controlling-an-intermode-rover-canbus.md
@@ -108,7 +108,7 @@ The [base](/components/base/) component exposes an API for controlling a mobile
To use it for the Intermode rover, you must create a new [model](/extend/modular-resources/key-concepts/#models) with its own implementation of each method.
Both the **API** and **model** of any Viam resource are represented as colon-separated triplets where the first element is a namespace.
-Since you will conform to an existing Viam API for [base](/components/base/), the [API](/extend/modular-resources/key-concepts/#apis) you will use is:
+Since you will conform to an existing Viam API for [base](/components/base/), the [API](/extend/modular-resources/key-concepts/#valid-apis-to-implement-in-your-model) you will use is:
**rdk:component:base**
This base model is being created for tutorial purposes only, and will implement only partial functionality for demonstration purposes.
@@ -232,7 +232,7 @@ Now the intermode base can receive and execute *SetPower* commands using the sam
### Leaving some methods unimplemented
-In some cases, you may not want to implement specific methods provided by the resource type's [API](/extend/modular-resources/key-concepts/#apis).
+In some cases, you may not want to implement specific methods provided by the resource type's [API](/extend/modular-resources/key-concepts/#valid-apis-to-implement-in-your-model).
For example, some hardware may not support specific functionality.
When you want to leave a method unimplemented you must still create that method, but return an appropriate error message.
diff --git a/docs/tutorials/get-started/blink-an-led.md b/docs/tutorials/get-started/blink-an-led.md
index 8843ad51b3..356c785055 100644
--- a/docs/tutorials/get-started/blink-an-led.md
+++ b/docs/tutorials/get-started/blink-an-led.md
@@ -129,15 +129,13 @@ First, go to the [Viam app](https://app.viam.com/) on your web browser and navig
{{< tabs >}}
{{% tab name="Config Builder" %}}
-![The Create component field on the Components subtab of the Config tab.](/tutorials/blink-an-led/create-component.png)
-
-Add a [*board component*](/components/board/) to represent your single board computer, which in this case is the Raspberry Pi.
-To create the new component, navigate to the **Create component** panel.
+Add a [*board component*](/components/board/) to represent your single-board computer, which in this case is the Raspberry Pi.
+To create the new component, click **Create component** in the lower left corner of the **Config** tab.
+- Select `board` as the component type.
+- Select `pi` as the model.
- Name the board whatever you like as long as you are consistent when referring to it later; we'll name it `local` since it is the board we will communicate with directly.
-- For the component **Type**, select `board`.
-- For **Model**, select `pi`.
-- Click **Create component**.
+- Click **Create**.
Your board component panel will look like this:
diff --git a/docs/tutorials/projects/send-security-photo.md b/docs/tutorials/projects/send-security-photo.md
index dff9bcf930..1a64059e24 100644
--- a/docs/tutorials/projects/send-security-photo.md
+++ b/docs/tutorials/projects/send-security-photo.md
@@ -236,7 +236,7 @@ import os
from viam.robot.client import RobotClient
from viam.rpc.dial import Credentials, DialOptions
-from viam.services.vision import VisionClient, VisModelConfig, VisModelType, Detection
+from viam.services.vision import VisionClient, Detection
import yagmail
diff --git a/docs/tutorials/services/color-detection-scuttle.md b/docs/tutorials/services/color-detection-scuttle.md
index 16345d38f8..7ce1bef810 100644
--- a/docs/tutorials/services/color-detection-scuttle.md
+++ b/docs/tutorials/services/color-detection-scuttle.md
@@ -324,7 +324,7 @@ import asyncio
from viam.robot.client import RobotClient
from viam.rpc.dial import Credentials, DialOptions
from viam.services.vision import VisionServiceClient
-from viam.services.vision import VisModelConfig, VisModelType, Detection
+from viam.services.vision import Detection
from viam.components.camera import Camera
from viam.components.base import Base
diff --git a/docs/viam/_index.md b/docs/viam/_index.md
index a97cdbf520..230059ffd1 100644
--- a/docs/viam/_index.md
+++ b/docs/viam/_index.md
@@ -29,7 +29,7 @@ You will not need to write a single line of code to integrate them, and swapping
You can make use of computer vision, motion planning, SLAM, data management, machine learning, and more by configuring Viam's built-in {{< glossary_tooltip term_id="service" text="services">}}.
- **Architecture**:
You can build simple robots or multi-part robots that use secure communication channels across local networks and the cloud, all of which can be managed with a uniform API.
-- **Extensibility**: If you need additional functionality, you can leverage community contributed and custom resources to [extend](/extend/) Viam.
+- **Extensibility**: If you need additional functionality, you can leverage community contributed and modular resources to [extend](/extend/) Viam from [the Viam Registry](/extend/modular-resources/).
Join the [**Viam community**](https://discord.gg/viam) to collaborate during planning and beyond.
@@ -132,6 +132,16 @@ With it you can:
- Manage software across your fleet, including deployment of code and machine learning models.
- Keep your robot configuration and capabilities up-to-date.
+## Extensibility
+
+You can also extend Viam to support additional hardware components or software services by deploying a module from the [Viam Registry](https://app.viam.com/registry) to your robot.
+
+The Viam Registry allows hardware and software engineers to collaborate on their robotics projects by writing and sharing custom modules with each other.
+You can add a module from the Viam Registry directly from your robot's **Configuration** tab in [the Viam app](https://app.viam.com/), using the **+ Create component** button.
+You can also [upload your own module to the Viam Registry](/extend/modular-resources/upload/).
+
+See [Modular resources](/extend/modular-resources/) for more information.
+
## Next steps
Start by borrowing one of our robots.
diff --git a/layouts/docs/tutorials.html b/layouts/docs/tutorials.html
index 510d360579..34396c144d 100644
--- a/layouts/docs/tutorials.html
+++ b/layouts/docs/tutorials.html
@@ -80,7 +80,10 @@ Javascript
-
+
+ {{ $jsTutorials := resources.Get "js/tutorials.js" }}
+ {{ $jsTutorials := $jsTutorials | minify }}
+