diff --git a/bundles/index.rst b/bundles/index.rst
index 2ab2f84a..bca08a8e 100644
--- a/bundles/index.rst
+++ b/bundles/index.rst
@@ -15,6 +15,7 @@ Bundles
routing_auto/index
routing/index
search/index
+ seo/index
simple_cms/index
tree_browser/index
diff --git a/bundles/map.rst.inc b/bundles/map.rst.inc
index 387d92fc..a8e67e34 100644
--- a/bundles/map.rst.inc
+++ b/bundles/map.rst.inc
@@ -59,6 +59,12 @@ library or they introduce a complete new concept.
* :doc:`search/introduction`
+* :doc:`seo/index`
+
+ * :doc:`seo/introduction`
+ * :doc:`seo/seo_aware`
+ * :doc:`seo/extractors`
+
* :doc:`tree_browser/index`
* :doc:`tree_browser/introduction`
diff --git a/bundles/seo/extractors.rst b/bundles/seo/extractors.rst
new file mode 100644
index 00000000..f6ba2155
--- /dev/null
+++ b/bundles/seo/extractors.rst
@@ -0,0 +1,127 @@
+Using Extractors to Retrieve the Seo Metadata
+=============================================
+
+Instead of setting every value to the ``SeoMetadata`` manually, an extractor
+can do the work for you. Extractors are executed when the content object
+implements a specific interface. The method required by that interface will
+return the value for the specific SEO data. The extractor will then update the
+``SeoMetadata`` object for the current object with the returned value.
+
+Available Extractors
+--------------------
+
++--------------------------------+---------------------------+----------------------------------------------+
+| ExtractorInterface | Method | Type |
++================================+===========================+==============================================+
+| ``DescriptionReadInterface`` | ``getSeoDescription()`` | Returns the meta description |
++--------------------------------+---------------------------+----------------------------------------------+
+| ``TitleReadInterface`` | ``getSeoTitle()`` | Returns the page title |
++--------------------------------+---------------------------+----------------------------------------------+
+| - | ``getTitle()`` | If the document has a ``getTitle()`` method, |
+| | | it'll be used as the page title |
++--------------------------------+---------------------------+----------------------------------------------+
+| ``OriginalUrlReadInterface`` | ``getSeoOriginalUrl()`` | Returns a absolute url object to redirect to |
+| | | or create a canonical link from |
++--------------------------------+---------------------------+----------------------------------------------+
+| ``OriginalRouteReadInterface`` | ``getSeoOriginalRoute()`` | Return a ``Route`` object to redirect to |
+| | | or create a canonical link from |
++--------------------------------+---------------------------+----------------------------------------------+
+| ``ExtrasReadInterface`` | ``getSeoExtras()`` | Returns an associative array using |
+| | | ``property``, ``http-equiv`` and ``name`` |
+| | | as keys (see below from an example). |
++--------------------------------+---------------------------+----------------------------------------------+
+
+.. note::
+
+ The interfaces life in the ``Symfony\Cmf\Bundle\SeoBundle\Extractor``
+ namespace.
+
+An Example
+----------
+
+Assume you have an ``Article`` object and you want to use both the ``$title``
+and ``$date`` properties as page title and the ``$intro`` property as
+description, you can implement both interfaces and your result will be::
+
+ // src/Acme/BlogBundle/Document/Article.php
+ namespace Acme\BlogBundle\Document;
+
+ use Symfony\Cmf\Bundle\SeoBundle\Extractor\TitleReadInterface;
+ use Symfony\Cmf\Bundle\SeoBundle\Extractor\DescriptionReadInterface;
+ use Symfony\Cmf\Bundle\SeoBundle\Extractor\ExtrasReadInterface;
+
+ class Article implements TitleReadInterface, DescriptionReadInterface, ExtraReadInterface
+ {
+ protected $title;
+ protected $publishDate;
+ protected $intro;
+
+ // ...
+ public function getSeoTitle()
+ {
+ return $this->title.' ~ '.date($this->publishDate, 'm-Y');
+ }
+
+ public function getSeoDescription()
+ {
+ return $this->intro;
+ }
+
+ public function getSeoExtras()
+ {
+ return array(
+ 'property' => array(
+ 'og:title' => $this->title,
+ 'og:description' => $this->description,
+ ),
+ );
+ }
+ }
+
+Creating Your Own Extractor
+---------------------------
+
+To customize the extraction process, you can create your own extractor. Just
+create a class which implements the ``SeoExtractorInterface`` and tag it with
+``cmf_seo.extractor``:
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ parameters:
+ acme_demo.extractor.custom.class: Acme\DemoBundle\Extractor\MyCustomExtractor
+
+ services:
+ acme_demo.extractor.custom:
+ class: "%acme_demo.extractor.custom.class%"
+ tags:
+ - { name: cmf_seo.extractor }
+
+ .. code-block:: xml
+
+
+
+
+ Acme\DemoBundle\Extractor\MyCustomExtractor
+
+
+
+
+
+
+
+
+
+ .. code-block:: php
+
+ $container->addParameter(
+ 'acme_demo.extractor.custom.class',
+ 'Acme\DemoBundle\Extractor\MyCustomExtractor'
+ );
+
+ $container->register('acme_demo.extractor.custom', '%acme_demo.extractor.custom.class%')
+ ->addTag('cmf_seo.extractor')
+ ;
diff --git a/bundles/seo/index.rst b/bundles/seo/index.rst
new file mode 100644
index 00000000..2c3866c1
--- /dev/null
+++ b/bundles/seo/index.rst
@@ -0,0 +1,9 @@
+SeoBundle
+=========
+
+.. toctree::
+ :maxdepth: 2
+
+ introduction
+ seo_aware
+ extractors
diff --git a/bundles/seo/introduction.rst b/bundles/seo/introduction.rst
new file mode 100644
index 00000000..3454a0c7
--- /dev/null
+++ b/bundles/seo/introduction.rst
@@ -0,0 +1,343 @@
+SeoBundle
+=========
+
+ This bundle provides a layer on top of the `SonataSeoBundle`_, to make it
+ easier to collect SEO data from content documents.
+
+Installation
+------------
+
+You can install this bundle `with composer`_ using the
+``symfony-cmf/seo-content-bundle`` package on `Packagist`_.
+
+Both the CmfSeoBundle and SonataSeoBundle must be registered in the
+``AppKernel``::
+
+ // app/appKernel.php
+
+ // ...
+ public function registerBundles()
+ {
+ $bundles = array(
+ // ...
+ new Sonata\SeoBundle\SonataSeoBundle(),
+ new Symfony\Cmf\Bundle\SeoBundle\CmfSeoBundle(),
+ );
+
+ // ...
+
+ return $bundles;
+ }
+
+Usage
+~~~~~
+
+The simplest use of this bundle would be to just set some configuration to the
+``sonata_seo`` configuration section and use the twig helper in your templates.
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ # app/config/config.yml
+ sonata_seo:
+ page:
+ title: Page's default title
+ metas:
+ name:
+ description: The default description of the page
+ keywords: default, sonata, seo
+
+ .. code-block:: php
+
+ // app/config/config.php
+ $container->loadFromExtension('sonata_seo', array(
+ 'page' => array(
+ 'title' => 'Page's default title',
+ 'metas' => array(
+ 'name' => array(
+ 'description' => 'default description',
+ 'keywords' => 'default, key, other',
+ ),
+ ),
+ ),
+ ));
+
+The only thing to do now is to use the twig helper in your templates:
+
+.. code-block:: html+jinja
+
+
+
+
+
+
+
+
+This will render a page with the default title ("Page's default title") as
+title element. The information definded for description and keywords will go
+into the correct metatags.
+
+.. seealso::
+
+ To get a deeper look into the SonataSeoBundle, you should visit the
+ `Sonata documentation`_.
+
+Using SeoMetadata
+-----------------
+
+The basic example shown above works perfectly without the CmfSeoBundle. The
+CmfSeoBundle provides more extension points to configure the SEO data with
+data from the document (e.g. a ``StaticContent`` document). This is done by
+using SEO metadata. This is SEO data which will be used for a particular
+document. This metadata can hold:
+
+* The title;
+* The meta keywords;
+* The meta description;
+* The original URL (when more than one URL contains the same content).
+* Anything else that uses the ```` tag with the ``property``, ``name``
+ or ``http-equiv`` type (e.g. Open Graph data).
+
+The content object is retrieved from the request attributes. By default, it
+uses the ``DynamicRouter::CONTENT_KEY`` constant when the
+:doc:`RoutingBundle <../routing/introduction>` is installed. To change this,
+or if you don't use the RoutingBundle, you can configure it with
+``cmf_seo.content_key``.
+This bundle provides two ways of using this metadata:
+
+#. Implementing the ``SeoAwareInterface`` and persisting the ``SeoMetadata``
+ with the object.
+#. Using the extractors, to extract the ``SeoMetadata`` from already existing
+ values (e.g. the title of the page).
+
+You can also combine both ways, even on the same document. In that case, the
+persisted ``SeoMetadata`` can be changed by the extractors, to add or tweak
+the current available SEO information. For instance, if you are writing a
+``BlogPost`` class, you want the SEO keywords to be set to the tags/category
+of the post and any additional tags set by the admin.
+
+Persisting the ``SeoMetadata`` with the document makes it easy to edit for the
+admin, while using the extractors are perfect to easily use values from the
+displayed content.
+
+Both ways are documented in detail in seperate sections:
+
+* :doc:`seo_aware`
+* :doc:`extractors`
+
+Choosing the Original Route Pattern
+-----------------------------------
+
+Search engines don't like it when you provide the same content under several
+URLs. The CMF allows you to have several URLs for the same content if you need
+that. There are two solutions to avoid penalties with search engines:
+
+* Create a canonical link that identifies the original URL:
+ ````
+* Define an "original url" and redirect all duplicate URLs to it.
+
+The ``SeoMetadata`` can be configured with the original URL for the current
+page. By default, this bundle will create a canonical link for the page. If
+you want to change that to redirect instead, you can set the
+``original_route_pattern`` option:
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ # app/config/config.yml
+ cmf_seo:
+ original_route_pattern: redirect
+
+ .. code-block:: xml
+
+
+
+
+ .. code-block:: php
+
+ // app/config/config.php
+ $container->loadFromExtension(
+ 'cmf_seo' => array(
+ 'original_route_pattern' => 'redirect',
+ ),
+ );
+
+.. _bundles-seo-title-description-emplate:
+
+Defining a Title and Description Template
+-----------------------------------------
+
+Most of the times, the title of a site has a static and a dynamic part. For
+instance, "The title of the Page - Symfony". Here, "- Symfony" is static and
+"The title of the Page" will be replaced by the current title. It would not be
+nice if you had to add this static part to all your titles in documents.
+
+The CmfSeoBundle allows you to define a title and description template for
+this reason. When using these settings, there are 2 placeholders available:
+``%content_title%`` and ``%content_description%``. These will be replaced with
+the title extracted from the content object and the description extracted from
+the content object.
+
+.. caution::
+
+ The title and description template is only used when the title is not set
+ on the content object or when the content object is not available,
+ otherwise it'll use the default set by the SonataSeoBundle. You should
+ make sure that the defaults also follow the template.
+
+For instance, to configure the titles of the symfony.com pages, you would do:
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ # app/config/config.yml
+ cmf_seo:
+ title: "%%content_title%% - Symfony"
+
+ .. code-block:: xml
+
+
+
+
+ .. code-block:: php
+
+ // app/config/config.php
+ $container->loadFromExtension('cmf_seo', array(
+ 'title' => '%%content_title%% - Symfony',
+ ));
+
+.. caution::
+
+ Be sure to escape the percentage characters by using a double percentage
+ character, otherwise the container will try to replace it with the value
+ of a container parameter.
+
+This syntax might look familiar if you have used the Translation component
+before. And that's correct, under the hood the Translation component is used
+to replace the placeholders with the correct values. This also means you get
+Multi Language Support for free!
+
+For instance, you can do:
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ # app/config/config.yml
+ cmf_seo:
+ title: seo.title
+ description: seo.description
+
+ .. code-block:: xml
+
+
+
+
+ .. code-block:: php
+
+ // app/config/config.php
+ $container->loadFromExtension('cmf_seo', array(
+ 'title' => 'seo.title',
+ 'description' => 'seo.description',
+ ));
+
+And then configure the translation messages:
+
+.. configuration-block::
+
+ .. code-block:: xml
+
+
+
+
+
+
+
+ seo.title
+ %content_title% | Default title
+
+
+ seo.description
+ Default description. %content_description%
+
+
+
+
+
+ .. code-block:: php
+
+ // app/Resources/translations/messages.en.php
+ return array(
+ 'seo' => array(
+ 'title' => '%content_title% | Default title',
+ 'description' => 'Default description. %content_description',
+ ),
+ );
+
+ .. code-block:: yaml
+
+ # app/Resources/translations/messages.en.yml
+ seo:
+ title: "%content_title% | Default title"
+ description: "Default description. %content_description%"
+
+.. tip::
+
+ You don't have to escape the percent characters here, since the
+ Translation loaders know how to deal with them.
+
+For changing the default translation domain (messages), you should use the
+``cmf_seo.translation_domain`` setting:
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ # app/config/config.yml
+ cmf_seo:
+ translation_domain: AcmeDemoBundle
+
+ .. code-block:: xml
+
+
+
+
+
+
+ .. code-block:: php
+
+ // app/config/config.php
+ $container->loadFromExtension(
+ 'cmf_seo' => array(
+ 'translation_domain' => 'AcmeDemoBundle',
+ ),
+ );
+
+Conclusion
+----------
+
+That's it! You have now created a SEO optimized website using nothing more
+than a couple of simple settings.
+
+.. _`SonataSeoBundle`: https://github.com/sonata-project/SonataSeoBundle
+.. _`with composer`: http://getcomposer.org
+.. _`packagist`: https://packagist.org/packages/symfony-cmf/menu-bundle
+.. _`Sonata documentation`: http://sonata-project.org/bundles/seo/master/doc/index.html
diff --git a/bundles/seo/seo_aware.rst b/bundles/seo/seo_aware.rst
new file mode 100644
index 00000000..ed81031c
--- /dev/null
+++ b/bundles/seo/seo_aware.rst
@@ -0,0 +1,252 @@
+Saving the SeoMetadata in the Object
+====================================
+
+The ``SeoMetadata`` can be saved in the object, so you can persist it into the
+database. This option gives admins the possiblity of changing the SEO data for
+the document.
+
+In order to save the ``SeoMetadata`` in the object, the object should
+implement the ``SeoAwareInterface``. This requires a getter and a setter for
+the ``SeoMetadata``::
+
+ // src/Acme/SiteBundle/Document/Page.php
+ namespace Acme\SiteBundle\Document;
+
+ use Symfony\Cmf\Bundle\SeoBundle\SeoAwareInterface;
+
+ class Page implements SeoAwareInterface
+ {
+ protected $seoMetadata;
+
+ // ...
+ public function getSeoMetadata()
+ {
+ return $this->seoMetadata;
+ }
+
+ public function setSeoMetadata($metadata)
+ {
+ $this->seoMetadata = $metadata;
+ }
+ }
+
+Now you can set some SEO data for this ``Page`` using the metadata::
+
+ use Acme\SiteBundle\Document\Page;
+ use Symfony\Cmf\Bundle\SeoBundle\SeoMetadata;
+
+ $page = new Page();
+ // ... set some page properties
+
+ $pageMetadata = new SeoMetadata();
+ $pageMetadata->setDescription('A special SEO description.');
+ $pageMetadata->setTags('seo, cmf, symfony');
+
+ $page->setSeoMetadata($pageMetadata);
+
+Doctrine PHPCR-ODM Integration
+------------------------------
+
+In order to easily persist the SeoMetadata when using Doctrine PHPCR-ODM, the
+SeoBundle provides a special ``SeoMetadata`` document with the correct
+mappings. This document should be mapped as a child of the content document.
+
+To be able to use this document, you have to enable the PHPCR persistence:
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ # app/config/config.yml
+ cmf_seo:
+ persistence:
+ phpcr: true
+
+ .. code-block:: xml
+
+
+
+
+
+
+
+
+ .. code-block:: php
+
+ // app/config/config.php
+ $container->loadFromExtension('cmf_seo', array(
+ 'persistence' => array(
+ 'phpcr' => true,
+ ),
+ ));
+
+.. tip::
+
+ This is not needed if you already enabled PHPCR on the ``cmf_core``
+ bundle. See :doc:`the CoreBundle docs <../core/persistence>` for more
+ information.
+
+After you've enabled PHPCR, map your seoMetadata as a child:
+
+.. configuration-block::
+
+ .. code-block:: php-annotations
+
+ // src/Acme/SiteBundle/Document/Page.php
+ namespace Acme\SiteBundle\Document;
+
+ use Symfony\Cmf\Bundle\SeoBundle\SeoAwareInterface;
+ use Doctrine\ODM\PHPCR\Mapping\Annotations as PHPCR;
+
+ /**
+ * @PHPCR\Document()
+ */
+ class Page implements SeoAwareInterface
+ {
+ /**
+ * @PHPCR\Child
+ */
+ protected $seoMetadata;
+
+ // ...
+ }
+
+ .. code-block:: yaml
+
+ # src/Acme/SiteBundle/Resources/config/doctrine/Page.odm.yml
+ Acme\SiteBundle\Document\Page:
+ # ...
+ child:
+ # ...
+ seoMetadata: ~
+
+ .. code-block:: xml
+
+
+
+
+
+
+
+
+
+
+And after that, you can use the
+``Symfony\Cmf\Bundle\SeoBundle\Doctrine\Phpcr\SeoMetadata`` document::
+
+ // src/Acme/SiteBundle/DataFixture/PHPCR/LoadPageData.php
+ namespace Acme\SiteBundle\DataFixtures\PHPCR;
+
+ use Acme\SiteBundle\Document\Page;
+ use Symfony\Cmf\Bundle\SeoBundle\Doctrine\Phpcr\SeoMetadata;
+ use Doctrine\Common\Persistence\ObjectManager;
+ use Doctrine\Common\DataFixtures\FixtureInterface;
+
+ class LoadPageData implements FixtureInterface
+ {
+ public function load(ObjectManager $manager)
+ {
+ $page = new Page();
+ // ... set some page properties
+
+ $pageMetadata = new SeoMetadata();
+ $pageMetadata->setDescription('A special SEO description.');
+ $pageMetadata->setTags('seo, cmf, symfony');
+
+ $page->setSeoMetadata($pageMetadata);
+
+ $manager->persist($page);
+ $manager->flush();
+ }
+ }
+
+Doctrine ORM
+------------
+
+You can also use the Doctrine ORM with the CmfSeoBundle. You can just use the
+``Symfony\Cmf\Bundle\SeoBundle\SeoMetadata`` class and map it as an
+object:
+
+.. configuration-block::
+
+ .. code-block:: php-annotations
+
+ // src/Acme/SiteBundle/Entity/Page.php
+ namespace Acme\SiteBundle\Entity;
+
+ use Symfony\Cmf\Bundle\SeoBundle\SeoAwareInterface;
+ use Doctrine\ORM\Mapping as ORM;
+
+ /**
+ * @ORM\Entity()
+ */
+ class Page implements SeoAwareInterface
+ {
+ /**
+ * @ORM\Column(type="object")
+ */
+ protected $seoMetadata;
+
+ // ...
+ }
+
+ .. code-block:: yaml
+
+ # src/Acme/SiteBundle/Resources/config/doctrine/Page.orm.yml
+ Acme\SiteBundle\Entity\Page:
+ # ...
+ fields:
+ # ...
+ seoMetadata:
+ type: object
+
+ .. code-block:: xml
+
+
+
+
+
+
+
+
+
+
+
+You can also choose to put the ``SeoMetadata`` class into a seperate table. To
+do this, you have to enable ORM support just like you enabled PHPCR enabled
+above and add a OneToOne or ManyToOne relation between the content entity and
+the ``SeoMetadata`` entity.
+
+Form Type
+---------
+
+The bundle also provides a special form type called ``seo_metadata``. This
+form type can be used in forms to edit the ``SeoMetadata`` object.
+
+.. caution::
+
+ The bundles requires the `BurgovKeyValueFormBundle`_ when using the form
+ type. Make sure you install and enable it.
+
+Sonata Admin Integration
+------------------------
+
+Besides providing a form type, the bundle also provides a Sonata Admin
+Extension. This extension adds a field for the ``SeoMetadata`` when an admin
+edits an objec that implements the ``SeoAwareInterface`` in the Sonata Admin
+panel.
+
+.. caution::
+
+ The Sonata Admin uses the Form Type provided by the CmfSeoBundle, make
+ sure you have the `BurgovKeyValueFormBundle`_ installed.
+
+.. _`BurgovKeyValueFormBundle`: https://github.com/Burgov/KeyValueFormBundle
diff --git a/reference/configuration/routing.rst b/reference/configuration/routing.rst
index b19b2ccc..1bf69722 100644
--- a/reference/configuration/routing.rst
+++ b/reference/configuration/routing.rst
@@ -365,7 +365,6 @@ phpcr
),
));
-
enabled
*******
diff --git a/reference/configuration/seo.rst b/reference/configuration/seo.rst
new file mode 100644
index 00000000..fc22956e
--- /dev/null
+++ b/reference/configuration/seo.rst
@@ -0,0 +1,136 @@
+SeoBundle Configuration
+=======================
+
+The SeoBundle takes care of the SEO information of a page and can be
+configured under the ``cmf_seo`` key in your application configuration. When
+using XML, you can use the ``http://cmf.symfony.com/schema/dic/seo``
+namespace.
+
+Configuration
+-------------
+
+persistence
+~~~~~~~~~~~
+
+phpcr
+"""""
+
+.. configuration-block::
+
+ .. code-block:: yaml
+
+ # app/config/config.yml
+ cmf_seo:
+ dynamic:
+ persistence:
+ phpcr:
+ enabled: false
+ manager_name: ~
+
+ .. code-block:: xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+ .. code-block:: php
+
+ $container->loadFromExtension('cmf_seo', array(
+ 'dynamic' => array(
+ 'persistence' => array(
+ 'phpcr' => array(
+ 'enabled' => false,
+ 'manager_name' => null,
+ ),
+ ),
+ ),
+ ));
+
+enabled
+*******
+
+.. include:: partials/persistence_phpcr_enabled.rst.inc
+
+manager_name
+************
+
+.. include:: partials/persistence_phpcr_manager_name.rst.inc
+
+translation_domain
+~~~~~~~~~~~~~~~~~~
+
+**type**: ``string`` **default**: ``messages``
+
+The translation domain to use when translating the title and description
+template. See :ref:`bundles-seo-title-description-emplate` for more
+information.
+
+
+title
+~~~~~
+
+**type**: ``string`` **default**: ``null``
+
+The title template, read :ref:`here `
+about the usage.
+
+description
+~~~~~~~~~~~
+
+**type**: ``string`` **default**: ``null``
+
+The description template, read :ref:`here `
+about the usage.
+
+original_route_pattern
+~~~~~~~~~~~~~~~~~~~~~~
+
+**type**: ``string`` **default**: ``canonical``
+
+The original route strategy to use when multiple routes have the same content.
+Can be one of ``canonical`` or ``redirect``.
+
+content_key
+~~~~~~~~~~~
+
+**type**: ``string`` **default**: ``null`` (or ``DynamicRouter::CONTENT_KEY`` when RoutingBundle is enabled)
+
+The name of the Request attribute which contains the content object. This is
+required when the RoutingBundle is not enabled, otherwise it defaults to
+``DynamicRouter::CONTENT_KEY`` (which evaluates to ``contentDocument``).
+
+sonata_admin_extension
+~~~~~~~~~~~~~~~~~~~~~~
+
+If set to ``true``, the Sonata Admin Extension provided by the SeoBundle is
+activated.
+
+enabled
+"""""""
+
+**type**: ``enum`` **valid values** ``true|false|auto`` **default**: ``auto``
+
+If ``true``, the Sonata Admin Extension will be activated. If set to ``auto``,
+it is activated only if the SonataPhpcrAdminBundle is present.
+
+If the :doc:`CoreBundle <../../bundles/core/index>` is registered, this will default to the value
+of ``cmf_core.persistence.phpcr.use_sonata_admin``.
+
+form_group
+""""""""""
+
+**type**: ``string`` **default**: ``form.group_seo``
+
+The name of the form group of the group provided by the Sonata Admin
+Extension.
diff --git a/reference/index.rst b/reference/index.rst
index 90393c53..78fbd819 100644
--- a/reference/index.rst
+++ b/reference/index.rst
@@ -4,16 +4,17 @@ Reference
.. toctree::
:hidden:
- configuration/block.rst
- configuration/content.rst
- configuration/core.rst
- configuration/create.rst
- configuration/media.rst
- configuration/menu.rst
- configuration/routing.rst
- configuration/search.rst
- configuration/simple_cms.rst
- configuration/tree_browser.rst
- configuration/phpcr_odm.rst
+ configuration/block
+ configuration/content
+ configuration/core
+ configuration/create
+ configuration/media
+ configuration/menu
+ configuration/routing
+ configuration/search
+ configuration/seo
+ configuration/simple_cms
+ configuration/tree_browser
+ configuration/phpcr_odm
.. include:: map.rst.inc
diff --git a/reference/map.rst.inc b/reference/map.rst.inc
index 3e453923..463bc2f1 100644
--- a/reference/map.rst.inc
+++ b/reference/map.rst.inc
@@ -8,6 +8,7 @@
* :doc:`configuration/menu`
* :doc:`configuration/routing`
* :doc:`configuration/search`
+ * :doc:`configuration/seo`
* :doc:`configuration/simple_cms`
* :doc:`configuration/tree_browser`
* :doc:`configuration/phpcr_odm`