Skip to main content
Fields are what transform your components into editable blocks. You write the component code, then attach fields to make specific parts editable by content editors. This guide shows you how to add and configure fields effectively.

Understanding Fields

Fields bridge the gap between code and content:
  • Component code defines structure and styling
  • Fields define what content editors can edit
  • Together they create blocks that are both powerful and editable
Fields can be added to both blocks (for component-level editing) and page types (for page-level metadata). The process is the same for both.

Adding Fields to a Block

1

Create or open your component

In the Component Library, create a new block or open an existing one.
2

Write your component code

Build your component. Fields are globally available—no need to declare them:
<section class="hero">
  <h1>{headline}</h1>
  <p>{description}</p>
  {#if image?.url}
    <img src={image.url} alt={image.alt} />
  {/if}
</section>
Fields are automatically available in your component code. Just reference them directly like {headline} or {image.url}.
3

Open the field editor

Click “Add Field” or the fields panel in the component editor.
4

Create your first field

Configure the field:
  • Field name: Must match your prop name (e.g., headline)
  • Field type: Choose the appropriate type (e.g., Text, Rich Text, Image)
  • Label: Display name for editors (e.g., “Headline”)
  • Default value: Optional pre-filled value
The field name must exactly match the prop name in your component code.
5

Add more fields

Repeat for each prop you want to make editable:
  • description → Rich Text field
  • image → Image field
You don’t need to create fields for every prop. Only create fields for content you want editors to control.
6

Save your block

Click “Save Block” to save your component with its fields.

Field Naming

When you create a field, the field name determines how you reference it in your component:
<!-- If you create a field named "cta_text" -->
<button>{cta_text}</button>
Field configuration:
  • Field name: cta_text (how you reference it in code)
  • Label: “CTA Text” (what editors see in the UI)
Field names are case-sensitive. cta_text and ctaText are different variables in your component.

Common Field Patterns

Hero Block

A typical hero block might use these fields in the template:
<section class="hero" style={background_image?.url ? `background-image: url(${background_image.url})` : ''}>
  <h1>{headline}</h1>
  <p>{subheadline}</p>
  {#if cta_link?.url}
    <a href={cta_link.url}>{cta_link.label}</a>
  {/if}
</section>
Fields to create:
  • headline (Text) - Main headline
  • subheadline (Text) - Supporting text
  • cta_link (Link) - Button link with label
  • background_image (Image, optional) - Background image

Text Block

A simple text block:
<div class="text-{alignment}">
  {@html content}
</div>
Fields to create:
  • content (Rich Text) - The main content
  • alignment (Select) - Options: “left”, “center”, “right”

Image Block

An image with caption:
<figure>
  {#if image?.url}
    <img src={image.url} alt={image.alt} />
  {/if}
  {#if caption}
    <figcaption>{caption}</figcaption>
  {/if}
</figure>
Fields to create:
  • image (Image) - The image (includes URL and alt text)
  • caption (Text, optional) - Image caption

Card Grid Block

A grid of cards using a repeater:
<div class="grid cols-{columns}">
  {#each cards as card}
    <div class="card">
      {#if card.image?.url}
        <img src={card.image.url} alt={card.image.alt || card.title} />
      {/if}
      <h3>{card.title}</h3>
      <p>{card.description}</p>
      {#if card.link?.url}
        <a href={card.link.url}>{card.link.label || "Learn more"}</a>
      {/if}
    </div>
  {/each}
</div>
Fields to create:
  • cards (Repeater) with nested fields:
    • title (Text)
    • description (Text)
    • image (Image, optional)
    • link (Link, optional)
  • columns (Number) - Number of columns

Template Syntax Guide

Pala blocks use Svelte 5 syntax. Here’s the essential syntax you’ll use most often when working with fields.

Basic Interpolation

Display field values in your template:
<h1>{headline}</h1>
<p>{description}</p>

<!-- Image fields have .url and .alt properties -->
<img src={image.url} alt={image.alt} />

Fallback Values

Provide default values when fields are empty:
<!-- Using || operator -->
<h1>{headline || "Welcome"}</h1>

<!-- Using ?? for null/undefined only -->
<p>{description ?? "No description available"}</p>

Conditionals

Show or hide elements based on field values:
<!-- Simple if -->
{#if image?.url}
  <img src={image.url} alt={image.alt} />
{/if}

<!-- If/else -->
{#if featured}
  <span class="badge">Featured</span>
{:else}
  <span class="badge">Standard</span>
{/if}

<!-- Multiple conditions -->
{#if variant === "primary"}
  <button class="btn-primary">{cta_text}</button>
{:else if variant === "secondary"}
  <button class="btn-secondary">{cta_text}</button>
{:else}
  <button class="btn-default">{cta_text}</button>
{/if}

Loops (Repeater Fields)

Iterate over repeater field arrays:
<!-- Basic loop -->
{#each items as item}
  <div class="item">
    <h3>{item.title}</h3>
    <p>{item.description}</p>
  </div>
{/each}

<!-- With index -->
{#each features as feature, index}
  <div class="feature">
    <span class="number">{index + 1}</span>
    <h3>{feature.title}</h3>
  </div>
{/each}

<!-- With else (when array is empty) -->
{#each items as item}
  <div>{item.name}</div>
{:else}
  <p>No items to display</p>
{/each}

HTML Rendering

Render HTML from rich text or markdown fields:
<!-- Rich text content -->
<div class="content">
  {@html content}
</div>

<!-- Markdown content (processed automatically) -->
<article class="markdown">
  {@html markdown_content}
</article>
Rich text and markdown fields render HTML using {@html}. Since content comes from trusted editors (not site visitors), this is safe to use.

Reactive Statements

Compute derived values from fields:
<script>
  // Computed value based on fields
  $: fullName = `${firstName} ${lastName}`;

  // Computed array from repeater
  $: featuredItems = items.filter(item => item.featured);

  // Multiple statements
  $: {
    const total = items.reduce((sum, item) => sum + item.price, 0);
    console.log('Total:', total);
  }
</script>

<h1>Welcome, {fullName}</h1>

{#each featuredItems as item}
  <div>{item.title}</div>
{/each}

Event Handlers

Handle user interactions:
<script>
  function handleClick() {
    console.log('Button clicked');
    // Analytics, tracking, etc.
  }

  function handleSubmit(event) {
    event.preventDefault();
    // Handle form submission
  }
</script>

<button on:click={handleClick}>{cta_text}</button>

<form on:submit={handleSubmit}>
  <!-- form fields -->
</form>

Class Directives

Apply classes conditionally:
<!-- Single class -->
<div class:active={isActive}>Content</div>

<!-- Multiple classes -->
<div
  class:primary={variant === "primary"}
  class:large={size === "large"}
  class:featured={featured}
>
  Content
</div>

<!-- Shorthand (when variable matches class name) -->
<div class:featured>Content</div>

Style Directives

Apply inline styles dynamically:
<!-- Single style -->
<div style:color={textColor}>Colored text</div>

<!-- Multiple styles -->
<div
  style:background-color={backgroundColor}
  style:color={textColor}
  style:padding="{spacing}rem"
>
  Styled content
</div>

<!-- CSS custom properties -->
<div style:--theme-color={themeColor}>
  Content with CSS variable
</div>

Snippets (Reusable Templates)

Create reusable template chunks within a block:
{#snippet card(title, description)}
  <div class="card">
    <h3>{title}</h3>
    <p>{description}</p>
  </div>
{/snippet}

<!-- Use the snippet -->
{@render card("First Card", "Description here")}
{@render card("Second Card", "Another description")}

<!-- Use in loops -->
{#each items as item}
  {@render card(item.title, item.description)}
{/each}

What You Won’t Need

These Svelte features are not relevant for Pala blocks:
  • Stores - No need for cross-component state; fields are globally available within each block
  • Context API - Use relational fields instead (Page Field, Site Field, Page, Page List) to reference data from elsewhere
  • $bindable - Only for component authoring, not block templates
  • Custom elements - Blocks compile to standard components
  • SvelteKit features - Routing, load functions, etc. (Pala handles this)
  • Component slots - Blocks don’t accept slotted content

Learn More

For advanced Svelte features and patterns, see the Svelte 5 documentation.

Field Configuration

Required Fields

Mark fields as required when they’re essential:
A Hero block’s headline field should be required—a hero without a headline doesn’t make sense.
When to require:
  • Essential content (headlines, titles)
  • Fields that affect functionality
  • Fields needed for proper display
When not to require:
  • Optional enhancements (images, captions)
  • Fields with sensible defaults
  • Decorative elements

Default Values

You can set default values in the field configuration, or handle empty values in your template:
<!-- Option 1: Use field defaults (set in field config) -->
<h1>{headline}</h1>

<!-- Option 2: Provide fallback values in template -->
<h1>{headline || "Welcome"}</h1>

<!-- Option 3: Conditionally render -->
{#if headline}
  <h1>{headline}</h1>
{/if}
Best practices:
  • Set sensible defaults in field configuration
  • Handle empty/missing values gracefully
  • Make components functional even with minimal content

Help Text

Add help text to guide editors:
Field: background_image Help text: “Optional background image. Recommended size: 1920x1080px. Will be used as a fallback if no image is provided.”
Good help text:
  • Explains what the field is for
  • Provides guidance on content
  • Mentions any requirements (size, format, etc.)

Placeholders

Use placeholders to show example content:
  • Headline field: “Enter your headline here”
  • Description field: “Describe your product or service”
  • Link field: “/about” or “https://example.com
Placeholders help editors understand what to enter, especially for fields like URLs or slugs.

Advanced Field Patterns

Conditional Fields

Some fields should only appear when others have values:Setting up conditionals:
  1. Create the control field (e.g., video_type)
  2. Configure dependent fields to show/hide based on the control field
  3. Test with different values

Repeater Fields

Repeaters let editors add multiple items:
1

Create the repeater field

Add a Repeater field (e.g., features).
2

Add nested fields

Inside the repeater, add fields for each item:
  • title (Text)
  • description (Text)
  • icon (Image, optional)
3

Use in component

Reference the repeater field as an array:
{#each features as feature}
  <div class="feature">
    <h3>{feature.title}</h3>
    <p>{feature.description}</p>
  </div>
{/each}

Group Fields

Groups organize related fields:
1

Create a group field

Add a Group field (e.g., author).
2

Add fields to the group

Inside the group, add related fields:
  • name (Text)
  • email (Email)
  • bio (Textarea)
3

Use in component

Reference the group field as an object:
<div class="author">
  <h3>{author.name}</h3>
  <p>{author.bio}</p>
  <a href="mailto:{author.email}">Contact</a>
</div>

Field Validation

Text Validation

Add validation rules to text fields:
  • Min length: Minimum character count
  • Max length: Maximum character count
  • Pattern: Regex pattern for format validation
An email field might use pattern: ^[^\s@]+@[^\s@]+\.[^\s@]+$

Number Validation

For number fields:
  • Min value: Minimum allowed number
  • Max value: Maximum allowed number
  • Step: Increment/decrement step
A “Price” field might have:
  • Min: 0
  • Max: 10000
  • Step: 0.01 (for cents)

File Validation

For image and file fields:
  • Allowed formats: File extensions (jpg, png, pdf, etc.)
  • Max file size: Maximum upload size in MB
  • Dimensions: Min/max width and height (for images)

Testing Fields

Test with Empty Values

Always test your components with empty fields:
{#if headline}
  <h1>{headline}</h1>
{/if}

{#if image?.url}
  <img src={image.url} alt={image.alt} />
{/if}

Test with Default Values

Verify defaults work (if you set them in field configuration):
  1. Create a page with your block
  2. Don’t fill in any fields
  3. Check that the component displays correctly with default values

Test Edge Cases

Try:
  • Very long text
  • Special characters
  • Empty arrays (for repeaters)
  • Missing nested fields (for groups)

Best Practices

1. Start Simple

Begin with essential fields, add more as needed:
Simple Hero:
  Fields: headline, subheadline, cta_text

Enhanced Hero:
  Fields: headline, subheadline, cta_text, background_image, overlay_color

2. Use Descriptive Labels

Labels are what editors see:
  • ✅ “Featured Image”
  • ✅ “Publication Date”
  • ✅ “Author Name”
  • ❌ “Field 1”
  • ❌ “Data”

3. Provide Helpful Defaults

Set defaults in field configuration to make components work immediately:
  • Number fields: Set sensible defaults (e.g., columns defaults to 3)
  • Boolean fields: Set appropriate defaults (e.g., show_title defaults to true)
  • Select fields: Pre-select the most common option (e.g., alignment defaults to “left”)
Use Groups or organize fields logically:
  • Content fields: headline, description, content
  • Media fields: image, video, background
  • Settings fields: alignment, columns, variant

5. Validate Input

Add validation to prevent errors:
  • Required fields for essential content
  • Format validation for emails, URLs
  • Size limits for files and text

Common Mistakes

Mismatched Names

Field names must match how you reference them in code:
<!-- If field is named "ctaText" in field config -->
<button>{ctaText}</button>

<!-- Not "cta_text" - field names are case-sensitive -->

Not Handling Empty Values

Always handle missing or empty field values:
<!-- Bad: Breaks if headline is empty -->
<h1>{headline}</h1>

<!-- Good: Handles empty values -->
{#if headline}
  <h1>{headline}</h1>
{/if}

<!-- Also good: Provides fallback -->
<h1>{headline || "Welcome"}</h1>

Over-Complicating

Start simple, add complexity later:
# Start here
Fields: title, description

# Add later if needed
Fields: title, description, image, link, category, tags, featured

Next Steps

The best fields are the ones editors actually use. Start with essential fields, then add more based on feedback from content editors.