Skip to main content
Write a Svelte component to define how a block looks and behaves. Add fields so editors can change its content. The examples below show code you can adapt for your own blocks.

Watch the workflow

Build a component with an editable field

Watch the workflow in Primo. Download video · Download captions
  1. Open the page type to create a reusable block.
  2. Switch to content and create a Text field.
  3. Label the field Headline. Its key is headline.
  4. Set the default content for the field.
  5. Reference the field in your component markup.
  6. Preview the result, then create the block.

Components vs Blocks

A Svelte component is the code. A Primo block combines that code with field definitions and default content: Components are pure Svelte code:
  • Reusable UI elements (Button, Card, Hero)
  • Accept props and handle logic
  • No content fields attached
  • Reusable within a Svelte application; Primo blocks compile independently
Blocks are components with content fields:
  • Same Svelte component code
  • Plus editable content fields (text, images, links)
  • Used specifically in page types and pages
  • Editors can modify content, not code
When you create a block in Primo, you’re writing a Svelte component and then attaching fields to it. The component code stays the same; fields make it editable.

Component Structure

Every Primo component follows this structure:

Writing Your First Component

Create a block named Button for this example. Its fields and style options are choices you define:
1

Identify the fields you need

Think about what data your component needs. For a button block:
  • text: The button text
  • href: The link destination
  • variant: The button style (primary, secondary, outline)
Create text as Text, href as URL, and variant as Select with primary, secondary, and outline options. The browser compiler makes these fields available in your component code. For compatibility with older CLI static builders, declare them with $props().
Plan your fields first, then reference them in your template. Set default content in the Content view; in CLI files, use content.yaml.
2

Add the markup

Write the HTML structure:
3

Style the component

Add scoped styles:

Best Practices

1. Handle Empty Values

Components should work gracefully even with empty fields:

2. Use Conditional Rendering

Only show elements when content exists:

3. Handle Arrays Safely

When working with repeater fields, always check if the array has items:

4. Use Scoped Styles

Primo components use scoped styles by default. Use :global() when you need to style child elements:

5. Make Components Responsive

Always consider mobile devices:

6. Create Component Variations

Create Select fields and write the styles for the options you want to offer. Names such as light, dark, primary, and large below are example values; they have no styling effect until your code handles them: Layout variations:
Color/theme variations:
Size variations:
One flexible block with variant options is easier to maintain than multiple similar blocks. Editors can adjust layouts without developers creating new components.

Working with Rich Content

Rich Text Fields

When using rich text fields, use {@html} to render HTML:
Only use {@html} with trusted content. {@html} inserts HTML without escaping. Do not assume imported Markdown or HTML is sanitized, and do not render untrusted visitor input with it.

Markdown Content

Primo converts Markdown fields to HTML before passing them to your block. Render the result directly; running it through another Markdown parser would process the content twice.

Advanced Patterns

Reactive Statements

Use $derived for computed values based on fields:

Event Handling

Handle user interactions:

Conditional Classes

Use dynamic classes for variants:

Reuse markup inside a block

Blocks compile independently. A relative import such as ./Button.svelte does not automatically resolve another Primo block. Keep reusable markup in a Svelte snippet within the block, or place separate blocks as sections on the page.
Add headline and cta_text as Text fields and cta_link as a Link field before using this example.

Performance Considerations

Lazy Loading Images

For image-heavy components:

Optimize Re-renders

Use derived values efficiently:

Testing Your Components

Use the Preview

Primo’s in-browser editor provides instant preview:
  1. Write your component code
  2. Add test content in fields
  3. See changes update in real-time
Test with empty fields, long text, special characters, and edge cases to ensure your component is robust.

Test Different Screen Sizes

Use browser dev tools in the preview to test:
  • Mobile (320px - 768px)
  • Tablet (768px - 1024px)
  • Desktop (1024px+)

Common Patterns

These are Svelte examples for blocks you create, not built-in blocks. Add fields matching the variables each example uses before previewing it.

Card Component

Grid Layout

Accordion Component

Next Steps

Working with Fields

Learn how to attach content fields to your components.

Using the Component Library

Organize and reuse components across sites.

Field Types Reference

Complete reference of all available field types.

Your First Site

See components in action with a complete site example.
The best components are simple, focused, and reusable. Start with basic functionality, then add complexity only when needed.