Watch the workflow
Build a component with an editable field
Watch the workflow in Primo. Download video · Download captionsRead the walkthrough
Read the walkthrough
- Open the page type to create a reusable block.
- Switch to content and create a Text field.
- Label the field Headline. Its key is headline.
- Set the default content for the field.
- Reference the field in your component markup.
- Preview the result, then create the block.
Where fields live
Fields define editable content on sites, page types, and blocks. A definition specifies the label, key, and type; the content holds its value. Use site fields for global content, page fields for content that describes a page, and block fields for an individual section.Add fields in the browser
You need developer access to change field definitions.1
Open the block
Create or open a block in the library or the page type’s Blocks tab. Switch to Content to add fields and default content.
2
Set the label, key, and type
Add a field with a clear label, such as Headline. Set its key to
headline and its type to Text. Keys are case-sensitive and must match the variables in your block code.3
Write the markup
Reference the field directly. The browser compiler supplies field variables automatically. You can omit Add
$props() in this workflow; if you declare it yourself, include every field the block uses. Use Svelte 5 runes instead of export let.component.svelte
image as an Image field before using this example. data-key connects the element to its field for inline editing; it is especially useful when content repeats.4
Set default content and save
Enter a headline and, optionally, select an image. Save the block. Defaults seed new sections; later edits to a section belong to that section.
5
Verify on a page
Add the block to the page type’s available blocks, place it on a page, and edit both inline and through Edit content. Save the dialog and confirm the page shows the values you entered.
Define fields in files
A block needsconfig.yaml, component.svelte, fields.yaml, and content.yaml. Create them under sites/my-site/blocks/hero/:
config.yaml
fields.yaml
content.yaml
component.svelte, you can declare the field props explicitly. This works in the browser, in CLI 0.2.1, and with older static builders:
component.svelte
fields.yaml is a bare list; content.yaml is an object keyed by field name. Use config for field-specific options. Keep existing _id values when editing an export and omit them for new fields.
Run primo validate -d sites/my-site from the workspace root. If primo dev --author files is already running, wait for it to import the files and check the preview.
Choose supported field types
See Field types for the complete list. Use:- Text for plain text, including email addresses and phone numbers.
- Rich Text or Markdown for formatted content; render the resolved HTML with
{@html content}. - Image for images; check
image?.urlbefore rendering. - Link for a URL and label; check
link?.urland uselink.urlandlink.label. - Toggle for true/false values (
type: switchin files). - Repeater for a list of objects and Group for one object.
- Info for instructions displayed in the editor.
Repeaters and groups
Nested definitions usesubfields, not fields:
fields.yaml
content.yaml
component.svelte
subfields structure with type: group. Its value is one object rather than an array. Guard optional nested values before accessing them.
Reference site and page fields
A field namedlogo in a block does not automatically read the site’s logo. Add a Site Field reference and select the source field. Use Page Field to reference a field on the current page.
- Site Field references are available in page types and blocks.
- Page Field references are available in blocks.
- Editing a reference through the content form updates its source value. A site-field change can affect many pages; a page-field change affects that page and listings that reference it.
- Reference fields do not support inline editing. Use the content form or edit the source field.
fields.yaml
logo and a Text field title on a blog-post page type before adding these references. In file-authored blocks, a Page Field target uses <page-type-folder>--<field-key>. In the browser, select the page type and source field.
Watch: Connect site and page field references
This custom example shows the source of each reference and which pages an edit affects. Download video · Download captionsRead the walkthrough
Read the walkthrough
- This custom Navigation block reads shared site fields.
- Brand name is a Site Field reference to the source field in Site content.
- Editing the reference in the content form updates that source value.
- The header and footer now display the same shared brand name.
- The custom Post Content block reads this post’s page fields.
- Its Title is a Page Field reference to the Blog Post title field.
- Save a new title for this post.
- The listing reads the updated title. The second post keeps its own title.
Conditional fields
Use Set condition in a field’s menu to show it only when another value matches. The controlling field must precede the dependent field at the same nesting level. Comparisons are Equals (=) and Doesn’t equal (!=).
For example, put a Toggle named show_image before an Image field and show the image field only when the toggle is true. This is a condition you configure; it changes which fields the editor sees. Add {#if show_image} in your block if you also want to hide the image on the published page.
Defaults, instructions, and validation
Set default values in the block’s content, not adefault property in its field schema. In files, defaults belong in content.yaml. Use template fallbacks for empty values and an Info field to explain content requirements.
Primo’s browser field editor does not offer required-field enforcement, regex patterns, or text-length limits. Image fields provide maximum file size and maximum dimension options. Schema validation through the CLI checks file structure and value shapes; it does not replace content review or a backend validator for visitor-submitted forms.
fields.yaml
Derived values and interactions
Use Svelte 5 runes for computed values. In a block with acards Repeater containing featured (Toggle) and title (Text), you can filter the displayed cards:
component.svelte
$state for interactive state and onclick for event handlers. Do not mix runes with legacy $: statements or export let declarations.
Verify field behavior
Test empty values, long text, missing images, empty repeaters, and optional group content. Add two instances of the block to ensure their section content is independent. Test shared references on more than one page, then publish and check the public result.Next steps
Field types
Look up supported types and value shapes.
Writing blocks
Build responsive blocks with Svelte.