I wanted to understand assets in Statamic for good, so I decided to document everything I've ever done with them. The support team doesn't understand me very well; I think it's because I'm not using the right YAML terms. I wrote this document to learn and to help explain things to other people who might think in terms that I use, rather than in the terms that official documentation uses.

I'm now satisfied with my understand of assets, but I still can't figure out how to use image assets in bard fields. Earlier today, someone else was asking about images in bard fields on the Slack channel, and I folded that conversation into my investigation here.

First, let's point out where in the structure of a Statamic project are the files that affect the rendering of UI controls and the referencing of fields from within templates.

Places where fieldtype stuff comes from

  1. Frontmatter YAML at the top of markdown (.md) content files. Directories: site/content/pages for pages and site/content/collections for collections (/index.md for the homepage)
  2. Fieldtype YAML files. Directory: site/settings/fieldsets
  3. Asset content manifests. Directory: site/content/assets (/main.yaml for the default asset bin)

.

Confusion 1: What is the asset "type"?

Asset  browser control successfully populated in the back end interface for a content section

The above screenshot shows a correctly rendered asset UI control. For most other fieldtypes, it's easy to get the correct control simply by putting type: beneath the field specification in the YAML fieldset file that is being used by a content page. (A fieldset file is being used by a content page when the markdown file's YAML has fieldset:.)

For most kinds of UI content controls, specifying type: in the fieldset file is all that is required to get the desired UI control on the back end.

Examples:

divisions_toggle:
    type: toggle
    display: Use identity section?
    instructions: Hide or revieal the identity section below

This correctly creates a toggle switch.

left_identity_heading:
    type: text
    display: Name for first division
    instructions: Enter a heading for the first identity section
    show_when:
      divisions_toggle: true

This correctly creates a text field, where a simple text string is inserted through my template.

  right_identity_writeup:
    type: textarea
    display: Description for second division
    instructions: Write a short mission statement
    show_when:
      divisions_toggle: true

This correctly creates a standard text box.

Assets actually do follow this pattern, even though there is some additional complexity. The correct way to specify an asset from within fieldset YAML is type: assets. Importantly, "type: asset" does not work---it throws a "FatalException" PHP error.

Using the array looping syntax for specifying an image out of an asset group -- combined with a fieldtype in the fieldset file specified by the page's markdown file -- this Antlers code outputs my image both on the webpage and in a little preview in the control panel:

{{ assets:right_identity_logo_img }}
<img src="{{ url }}" alt="{{ alt }}" />
{{ /assets:right_identity_logo_img }}

In fact, even the alt attribute successfully outputs into the rendered HTML element with the desired text. Within the Statamic project, the image alt text comes not from the page content, but from the YAML for an asset group located in site/content/assets, with the default asset YAML file being site/content/assets/main.yaml.

When using the control panel to upload images and edit their meta information, the two UI fields for "Title" and "Alt Text" write into title and alt write into the YAML file for the asset group.

image metadata fields in the Statamic asset browser

I have never seen this data successfully pre-populated into the UI from properly configuring the text files beforehand, because I've always been confused about the asset groups and where the data is coming from.

The main.yaml file open in Statmic, showing two uploaded images

The bottom two images with blurred text are listed in this file because I uploaded them through the Asset Browser.

Confusion 2: What is an asset "Container"?

A major source of confusion is that asset data can be referenced from two places -- fieldtypes or Containers. It's still unclear to me what piece of YAML is affecting a Container, and whether the code that affects the appearance of the control panel back end is from the asset's container or the fieldset's YAML.

The documentation for asset template tags points out this dichotomy. Above, I've describe Statamic's built in organization features for assets ambiguously as "groups," because I've been confused about how an asset Container is specified in YAML.

The main documentation article about assets explains what an asset is:

Each Asset Container and its configuration is represented by a YAML file inside site/content/assets. The name of that file (e.g. main.yaml) the container ID (main).

Note that second sentence. The filename is the container ID. I wonder if this is the same ID that the asset tag documentation means when it says,

Your site's Assets are managed and stored independently of your pages and entries and have a joined relationship through their id.

That might be important; at any rate, this control panel alert is common:

"No asset container specified" notice

In a different project, I avoided having that notice appear on the control panel above the successfully populated image preview with this:

{{ asset:section_image }}
<img src="{{ url }}" />
{{ /asset:section_image }}

In that project, section_image references this from the asset container YAML:

title: Main Assets
path: assets
url: /assets
section_image:
  img/headshot.jpg:
    title: headshot
    alt: headshot
    focus: 52-44
assets:
  img/black-bear-cubs.jpg:
    title: Black Bear Cubs
    alt: Some black bears standing up

This main.yaml file continues with all the rest of the default image assets from the Redwood theme, much like in the screenshot of my text editor showing a different main.yaml.

So, the thing that I named section_image is on the same YAML level as the assets name space thing. (My lack of familiarity with YAML terminology is a significant part of my confusion over all of this.)

Terminology aside, using the control panel to upload an image places it inside the assets namespace in the default container's YAML file. So, following this observation, shouldn't the correct tag for referencing an image listed under assets be {{asset:assets}}?

But promoting the identifiers for those two images in my other project to the same level as "assets" in their main.yaml doesn't get rid of the notice. It also doesn't get rid of the images, either on the webpage or previewed in the control panel -- even when I've commented out or deleted the original inclusion of these images beneath "assets".

(For a few minutes, I was thinking that moving the identifier in main.yaml removed the preview from one of the two images. However, actually the reason that the preview wasn't appearing was that I had only set type: assets for the first image in the page's fieldset file. When the assets fieldset type is not specified, the image can still come through on the webpage, but the control panel will only show a text field with the image path.)

Other Asset Containers

I did create a second asset container once. I think I used the command for the php CLI interface in order to set it up initially, but I can't remember.

I named the container "static" (not really a great choice when the system you're using has a similar name), and my static.yaml file looks like this:

title: Static Files
path: static
url: /static
assets:
  resume.pdf:
    title: Resume

I templated it like this:

{{ asset:download_doc }}
<a class="button-link" href="{{ url }}">download résumé</a>
{{ /asset:download_doc }}

This was the use case the generated the successful asset browser control.

Does it matter that I used the identifier "assets:" in my static.yaml? I tried changing "assets" to "downloads" and it still seems to work.

Confusion 3: "image" is not a fieldtype type

This is how following the examples on the Replicator and Bard documentation could be confusing. The documentation for these pages shows type: image inside a bard_field namespace. However, putting "type: image" inside a fieldset file produces the PHP FatalException error.

Fieldset files are for declaring all relevant types -- assets, bard, and replicator included. (I'm guessing fieldset files are distinctly not for any kind of content.)

A bard field is declared in the fieldset file:

freeform:
    type: bard

And used in the template with the same namespace ("freeform" being my example here):

{{ freeform }}
        {{ if type == "text" }}
            <div class="textblock">
                {{ text }}
            </div>
        {{ elseif type == "image" }}
            <figure class="homepic">
                <img src="{{ image }}" alt="{{ caption }}" />
                <figcaption>{{ caption }}</figcaption>
            </figure>
        {{ /if }}
{{ /freeform }}

And with the content inserted on top of index.md, content does successfully populate onto the homepage:

freeform:
  -
    type: text
    text: <p>Thanks for visiting the black bears. They've been lonely.</p>
  -
    type: image
    image: /assets/img/black-bear-cubs.jpg
    caption: The bears from Redwood theme

The control panel recognizes the text part of the bard field, but all we get for the image part is an empty draggy rectangle thing. control panel bard field, showing empty section for image

Here there are three sources of confusion:

  1. The identifier image is being used for two different things that are not inherently related to each other.
  2. Both identifiers are arbitrary.
  3. None of this is related to the assets fieldtype or to asset containers, except where the text of the image url is inserted into the template, because the value of one of those image thingies is the path of an image.

Let's get rid of the ambiguity by changing the identifiers. Now our template looks like this:

{{ freeform }}
        {{ if type == "text" }}
            <div class="textblock">
                {{ text }}
            </div>
        {{ elseif type == "jarcandle" }}
            <figure class="homepic">
                <img src="{{ willywonka }}" alt="{{ caption }}" />
                <figcaption>{{ caption }}</figcaption>
            </figure>
        {{ /if }}
{{ /freeform }}

I suspect that it doesn't matter what identifier is used in the if and elseif conditionals, as long as the same identifier in the conditional is used in the content markdown file. With that in mind, the relevant definition in index.md now looks like this:

freeform:
  -
    type: text
    text: <p>Thanks for visiting the black bears. They've been lonely.</p>
  -
    type: jarcandle
    willywonka: /assets/img/black-bear-cubs.jpg
    caption: The bears from Redwood theme

This change has no effect on the control panel or the webpage. Trying to bring in the asset controls for the image on the bard field in the control panel, I looped through this willywonka image array (of only the one image) in the template:

{{ assets:willywonka }}
<img src="{{ url }}" alt="{{ alt }}" />
{{ /assets:willywonka }}

That's accompanied by an expansion of the freeform block in the fieldset file:

freeform:
  type: bard
  willywonka:
    type: assets

It still doesn't work. It doesn't break the control panel, nor does it produce the PHP error or even prevent the image from rendering on the webpage. But it doesn't bring up the asset selection control or the image preview inside the Bard field on the control panel.

The last thing I tried was to make this willywonka identifier the equal of freeform on the hierarchy of the fieldset file, directly inside fields:. Still, there is no effect. I still don't how to properly use images within Bard fields.

If you can offer any more clarity about anything I (and potential other users) may still be confused on, please do jump in. Thanks!

Answered by Jason Varga! Go to answer.