---
url: /data-modeling/blueprints.md
---

# Blueprints

Blueprints are the foundation of your site's content structure. They are PHP classes that define the structure of your content blocks and are located in the `app/Blueprints` directory of your project.

::: warning Note for older projects
Blueprints are a rather new concept in Evolve. Before that, we used to define the structure of our blocks in YAML files located in the `config/components` directory. If you are upgrading from an older version of Evolve, you can still use the YAML files, but we recommend using blueprints for new projects.
:::

## Publishing the default blueprints

If your blueprints directory is empty, you can publish the default blueprints to your project by running the following command:

```bash
php artisan vendor:publish --tag=evolve.blueprints
```

## Creating a custom blueprint

To create a custom blueprint, you need to create a new PHP class inside the `app/Blueprints` directory. You can use our Artisan command to create a new blueprint:

```bash
php artisan evolve:blueprint
```

This command will ask you for a name and label for your blueprint and create a new PHP class in the blueprints directory.

```php
namespace App\Blueprints;

use Racerfish\Evolve\Contracts\BlueprintConfig;
use Racerfish\Evolve\DTO\Blueprint;
use Racerfish\Evolve\DTO\Field;

class Quote implements BlueprintConfig
{
    public static function config(): Blueprint
    {
        return Blueprint::make('cms.quote')
            ->label('Zitat')
            ->fields([
                // ...
            ]);
    }
}
```

### Name and label

The `name` of the blueprint should be a **unique identifier** for your blueprint. The `label` is the human-readable name of your blueprint that will be displayed in the control panel.

```php
return Blueprint::make('cms.logoCloud')->label('Logo Cloud')
```

### Hidden blueprints

Hidden blueprints cannot be selected as a top-level block in the block editor. This is useful for blueprints that are only used as fieldsets, nested blocks or in a collection.

```php
return Blueprint::make('component.product')
    ->label('Produkt')
    ->hidden()
    ->fields([...])
```

### Group

You can group your blueprints together in the control panel by setting a group for your blueprint.

```php
return Blueprint::make('cms.logoCloud')
    ->label('Logo Cloud')
    ->group('Features')
```

### Fields

Fields define the data structure of your block. The `fields` method accepts an array of field definitions. You can use the `Field` class to define fields.

You can use static methods to choose from a variety of field types and presets. (Check out all [available field types](#available-field-types).)

```php
    ->fields([
        Field::title(),
        Field::string('description', 'Beschreibung'),
        Field::richtext('content', 'Inhalt'),
    ])
```

#### Repeatable fields

You can make a field or a fieldset repeatable by calling the `repeatable` method on the field definition.

```php
Field::richtext('content', 'Inhalt')->repeatable()
```

#### Default value

You can set the default value for fields using the `default` method.

```php
Field::toggleSwitch('published', 'Veröffentlicht')->default(true)
```

#### Display width

You can choose how wide the field should be displayed in the control panel using the `width` method. Every TailwindCSS width class is supported.

```php
Field::string('title', 'Titel')->width('1/2')
```

#### Fieldsets

You can group fields together using fieldsets. Fieldsets are created using the `fieldset` method and can contain other fields or reference another blueprint.

```php
// Define a fieldset inline
Field::fieldset('panel', 'Panel', [
    Field::string('title', 'Titel'),
    Field::richtext('content', 'Inhalt'),
])

// Or reference another blueprint
Field::fieldset('panel', 'Panel', \App\Blueprints\Panel::class)
```

#### Available field types

Evolve provides a variety of field types that you can use in your blueprints. Here are some of the available field types:

Type | Description
\--- | ---
`string` | A simple text input field.
`text` | A textarea field.
`richtext` | A WYSIWYG editor field.
`number` | A number input field.
`url` | A URL input field.
`date` | A date input field.
`datetime` | A datetime input field.
`select` | A select dropdown field with predefined `options`.
`multi-select` | A multi-select dropdown field with predefined `options`.
`checkboxGroup` | A group of checkboxes with predefined `options`.
`radioGroup` | A group of radio buttons with predefined `options`.
`toggleSwitch` | A toggle switch field.
`resource` | A field to select a resource (Eloquent model).
`resourceCollection` | A field to select a collection of resources.
`media` | A field to select files from the media library.
`video` | A field to select a video from Vimeo.
`fieldset` | A fieldset to group fields together.

### Customizing the preview

You can customize the preview title and description shown in the block editor by defining the `preview` method in your blueprint.

**Change preview fields**: You can use the parameters to define which fields should be used for the title and description of the block.

```php
    ->fields([
        Field::string('heading', 'Überschrift'),
        Field::richtext('intro', 'Einleitung'),
    ])
    ->preview(
        title: 'heading'
        description: 'intro'
    )
```

**Computed preview**: You can also define a computed preview for your block by passing a closure any of the parameters. The closure receives the current `Block` instance and should return a string.

```php
    ->fields([
        Field::fieldset('logos', 'Logos', [
            Field::string('title', 'Titel'),
            Field::media('logo', 'Logo'),
        ]),
    ])
    ->preview(
        title: fn (Block $block) => $block->_logos->pluck('title')->join(', ')
        description: fn (Block $block) => $block->_logos->count() . ' Logos'
    )
```

### Nested blocks

You can enable nesting of blocks with the `allowNestedBlocks` method. This allows users to add blocks inside this block in the block editor.

**Allow all types**: This is especially useful for "layout"-blocks that define something like a grid or a column layout and allows any block to be added inside.

```php
return Blueprint::make('layout.grid')
    ->label('Grid Layout')
    ->fields([...])
    ->allowNestedBlocks()
```

**Allow specific types**: You can define which type of blocks are allowed to be nested inside this block by passing an array of blueprint class names.

```php
return Blueprint::make('layout.card-grid')
    ->label('Card Grid')
    ->fields([...])
    ->allowNestedBlocks([
        \App\Blueprints\Card::class,
        \App\Blueprints\Tile::class,
    ])
```

### Relationships

You can define dynamic relationships between blocks or other models using the `relationship` method on a select, multi-select, radio group or checkbox group field.

**Relationship to a collection:**

Define a relationship to a collection by passing the collection name as a string.

```php
Field::select('category', 'Kategorie')->relationship('product_categories')
```

**Relationship to a model:**

Define a relationship to an Eloquent model by passing the model class.

```php
Field::select('author', 'Autor')->relationship(User::class)
```

::: tip Note
Related models should implement the `Evolve\Contracts\Selectable` interface. This interface is required to display the related models in form.

Alternatively, you can [customize the displayed options](#customizing-the-displayed-options) by passing a closure to the `options` parameter.
:::

#### Customizing the relationship name

By default, the relationship field will use the `name` of the related model. You can customize the relationship name by passing a second parameter to the `relationship` method.

```php
Field::select('author', 'Autor')->relationship(User::class, 'bookAuthor')
```

#### Customizing the displayed options

You can customize the options that are displayed in the relationship field by passing a closure to the `options` parameter. The closure should return an array of \[id => label] tuples.

```php
Field::select('author', 'Autor', fn () => User::all()->pluck('name', 'id')->toArray())
    ->relationship(User::class)
```

### Collections configuration

You can configure settings for blueprints that are used in collections by using the `collection` method.

```php
return Blueprint::make('cms.product')
    ->label('Produkt')
    ->collection(
        routeable: true,
        baseQuery: fn (Builder $query) => $query->reorder()->latest(),
    )
```

-> Read more about [Collections](/data-modeling/collections).

## Frontend

To render your block in the frontend, you need to create a Blade view that corresponds to your blueprint. The Blade view should be located in the `theme/views/components/blocks` directory.

-> Read more about [rendering blocks in the frontend](/frontend/blocks.md).
