# Advanced: Workshop

{% hint style="info" %}
In some cases, you'll need to build or change mods in the Workshop, which can be found in the [Extension Console](https://docs.pixiebrix.com/platform-overview/extension-console).  This section shows you how to configure basic YAML files in the Workshop.
{% endhint %}

## YAML

PixieBrix uses YAML, a human-friendly markup language, for defining bricks. To learn the basics of using YAML, view one of the following tutorials:

* [Learn YAML in five minutes!](https://www.codeproject.com/Articles/1214409/Learn-YAML-in-five-minutes)
* [Quoting - Learn YAML](https://www.yaml.info/learn/quote.html)

### Dictionaries/Records

```yaml
exampleProperty:
  hello: 42
  world: "this is a string!"
```

### Lists/Arrays

To create a list, use `-` below the parent entry:

```yaml
exampleProperty:
  - hello
  - world
```

You can also create a list of dictionaries. *Note the indentation!*

```yaml
exampleProperty:
  - propA: hello
    propB: world
  - propA: hello
    propB: world
```

### String Quoting Gotchas

There are several situations where you must surround a value with double quotes (`"`) to ensure it’s interpreted as a string.

#### Namespaced Brick Ids

PixieBrix supports `@user` and `@organization` to namespace bricks. When using a namespaced brick id, you must surround the id in double quotes because `@` is a reserved character in YAML

```yaml
# quotes are required
id: "@pixiebrix/get"
# quotes are not required, because it does not start with an @
id: rapidapi/api
```

#### JQuery Selectors

Certain JQuery selectors must be enclosed in quotes so that they’re interpreted as strings:

* `"#id-selector"`: the id selector `#` is interpreted as starting a comment if not surrounded by quotes
* `"[name='submit']"`: the attribute selector `[` is interpreted as a list if not surrounded by quotes

#### Templates

Templates are described in more detail below. Because they begin with a `{` if you don’t surround them in quotes they’re interpreted as a mapping

* `"{{ myVariable }}"`

The exception is when writing multi-line strings using `|` you do not have to enclose them in quotes:

```yaml
field: !nunjucks |  
  {{ myVariable }}  {{ anotherVariable }}
```

#### Variable references

In PixieBrix, variables and integration configurations  referred to using a `@` before their name. Because they start with a “@” you must enclose them in quotes.

```yaml
service: !var "@nytimes"
prop: !var "@myOutputKey"
```

## Runtime API Version

The `apiVersion` directive controls how PixieBrix's runtime interprets the brick.

Whenever backward incompatible changes are introduced, we increment the apiVersion. If you do not specify the apiVersion, it defaults to v1

```yaml
apiVersion: "v3"
```

* `v1`: our initial release
* `v2`: made data flow between bricks explicit. Bricks had to reference data from previous bricks using the `@outputKey` for that brick
* `v3` (*supported in the runtime, but not yet supported in the Page Editor*). Uses explicit tags for `!var`, `!mustache`, and `!nunjucks`

## Variables

```yaml
prop1: !var "@variable"
listOfVariables:  
  - !var "@variable1"
  - !var "@variable2"
```

You can provide a path, which also supports [optional chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining):

```yaml
# if optionalChild doesn't exist on variable, returns undefined
prop: !var "@variable.optionalChild?.childProp.grandchildProp"
```

Arrays are indexed using a numeric property:

```yaml
# get itemProp from the first element in the array
prop: !var "@myArray.0.itemProp"
```

## Templating

PixieBrix supports a number of templating engines for wiring together bricks.

### Nunjucks / jinja2

[Nunjucks](https://mozilla.github.io/nunjucks/) is a Javascript port of [jinja2](https://jinja.palletsprojects.com/en/2.11.x/) supports logic including conditionals and mathematical expressions.

```yaml
- id: "@pixiebrix/html"
  templateEngine: nunjucks 
   config: 
    html: !nunjucks "{% if person %} {{ person.name }} {% else %}"
```

## Brick Directives

Use the following brick directive when creating components and mods

```yaml
# The id of the brick. Must surround in quotes if the id starts with a @
id: "@pixiebrix/foo"

# (Optional) controls which tab the brick is run in
# - self: the tab where the foundation is located
# - origin: the tab that opened this tab
# - target: the last tab that this tab opened
# - broadcast: runs the brick in all the available tabs, returning the result as 
#   an array
window: self

# (Optional) a property name to store the result of the variable in.
# Can be accessed as @propertyName in subsequent bricks
outputKey: propertyName

# (Optional) condition expression written in template language
# for deciding if the step should be run. If not
# provided, the step is run unconditionally
#
# Truthy: true, "true", "t", "yes", "y", "on", "1", non-zero numbers
# Falsy: values that aren't truthy
if: !nunjucks "{{ myCondition }}"

# (Optional) root JQuery selector for reader. If not provided, 
# the default is used. The default is the document
root: 

# (Optional)
# - inherit (default): inherit the root from the foundation. For triggers/context
# menus, this is the eventTarget
# - document: use the document as the root for the element
rootMode: 

# The configuration to pass to the block. Required. For blank configurations
# pass an empty dictionary {}
config: {}
```

## Package Browser Extension Range

To set a minimum browser extension version, or allowed range, set the `extensionVersion` directive in the package metadata.

The `extensionVersion` directive supports a [semantic version (SemVer) range](https://docs.npmjs.com/cli/v6/using-npm/semver#ranges):

```
metadata:
  id: "@docs/my-modern-mod"
  name: Mod with minimum version number
  description: Blueprint exported from PixieBrix
  extensionVersion: ">=2.2.1"
```

When used with Mod Deployments, if the user's browser version does not meet the extension range, PixieBrix will prompt the user to update their extension. See [deploying-mods](https://docs.pixiebrix.com/deploying-mods "mention")

### Setting autofocus for inputs

If you want a form field to be autofocused so a user can start typing immediately, you'll need to add the `ui:autofocus: true` attribute to the field properties for the uiScehma in the workshop.&#x20;

Example:&#x20;

```
uiSchema:
    userMessage:
      ui:widget: textarea
      ui:options:
        rows: 1
        submitOnEnter: true
        submitToolbar:
          icon:
            id: >-
              https://stylesheets.pixiebrix.com/foundever/icons/arrow-up-circle-fill.svg
            size: 16
            library: url
          show: true
      # Add the line below to set the field to autofocus when the form is rendered.
      ui:autofocus: true 
      ui:placeholder: !nunjucks Ask a question...
    ui:submitButtonOptions:
      norender: true
  submitCaption: Submit
```
