---
title: Integrate Symfony with Storyblok
description: This guide walks you through integrating Storyblok as a headless CMS, fetching content, and building components to render it effectively in your Symfony project.
url: https://storyblok.com/docs/guides/symfony
---

# Integrate Symfony with Storyblok

Use Storyblok to manage the content of your website built with Symfony.

> [!NOTE]
> This guide has been tested with the following package versions:
> 
> -   `symfony/framework-bundle@8.*`
> -   `storyblok/symfony-bundle@1.14.*`
> -   `storyblok/php-content-api-client@1.15.*`
> -   PHP 8.4

## Setup

Create a new Symfony project by following the official [installation](https://symfony.com/doc/current/setup.html) manual.

If you already have a Storyblok account, log into [app.storyblok.com](https://app.storyblok.com/#/login) or [log in with GitHub](https://github.com/login?client_id=Iv23liC8pLXD6VcT2EbS&return_to=%2Flogin%2Foauth%2Fauthorize%3Fclient_id%3DIv23liC8pLXD6VcT2EbS%26redirect_uri%3Dhttps%253A%252F%252Fapp.storyblok.com%252F#/login) to continue.

Create a [new blank space](https://app.storyblok.com/#/me/spaces/new?tab=select-plan) to follow the tutorial from scratch.

[No Storyblok account yet?](https://app.storyblok.com/#/signup) Create one and start a free Storyblok space

## Installation

In the terminal, `cd` into your Symfony project and install the Storyblok packages.

```bash
composer require storyblok/php-content-api-client storyblok/symfony-bundle
```

> [!TIP]
> This guide uses a [Symfony Flex recipe](https://symfony.com/doc/current/setup.html#installing-packages), which automatically adds configuration files to your project.

In the root of your project, create a `.env` file with the access token of your space.

.env

```bash
###> storyblok/symfony-bundle ###
STORYBLOK_API_BASE_URI=https://api.storyblok.com
STORYBLOK_API_TOKEN=your_storyblok_api_token
STORYBLOK_VERSION=published # the bundle's default
###< storyblok/symfony-bundle ###
```

> [!NOTE]
> Learn how to get an [access token](https://www.storyblok.com/docs/concepts/access-tokens#space-access-token) for your Storyblok project.

## Fetch a single story

Create a `Page` content type to fetch and render all stories of the `page` content type.

src/ContentType/Page.php

```php
<?php

declare(strict_types=1);

namespace App\ContentType;

use Storyblok\Bundle\ContentType\ContentType;

final readonly class Page extends ContentType
{
  public string $uuid;
  public string $name;
  public string $slug;
  public array $body;
  public \DateTimeImmutable $publishedAt;

  public function __construct(array $values)
  {
    $this->uuid = $values['uuid'];
    $this->name = $values['name'];
    $this->slug = $values['full_slug'];
    $this->body = $values['content']['body'] ?? [];
    $this->publishedAt = new \DateTimeImmutable($values['published_at']);
  }

  public function publishedAt(): \DateTimeImmutable
  {
    return $this->publishedAt;
  }
}
```

Next, create a controller for this content type.

src/Controller/PageController.php

```php
<?php

declare(strict_types=1);

namespace App\Controller;

use App\ContentType\Page;
use Storyblok\Bundle\ContentType\Attribute\AsContentTypeController;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

#[AsContentTypeController(contentType: Page::class)]
final class PageController extends AbstractController
{
  public function __invoke(Request $request, Page $page): Response
  {
    return $this->render('page.html.twig', [
      'page' => $page,
    ]);
  }
}
```

The `#[AsContentTypeController]` attribute automatically registers the controller to handle requests for the specified content type.

Finally, add Twig templates for rendering. Start with the `base` layout:

templates/base.html.twig

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
<title>{% block title %}Welcome to Storyblok!{% endblock %}</title>

    {% block stylesheets %}
    {% endblock %}
    {% block javascripts %}
    {% endblock %}
  </head>
  <body>
    <div class="container">
      {% block body %}{% endblock %}
    </div>
  </body>
</html>
```

 {% block title %}Welcome to Storyblok!{% endblock %} {% block stylesheets %} {% endblock %} {% block javascripts %} {% endblock %}  

 {% block body %}{% endblock %}


