### Install SuluHeadlessBundle with Composer
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/README.md
Use this command to add the bundle to your project's dependencies.
```bash
composer require sulu/headless-bundle
```
--------------------------------
### Example JSON Response for a Page
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
This is an example of the JSON structure returned by the HeadlessWebsiteController for a page request.
```json
{
"id": "a5181a5a-b030-4933-b3b0-e9faf7ec756c",
"type": "page",
"template": "default",
"content": {
"title": "My Page",
"description": "Welcome to my headless page."
},
"view": {
"title": [],
"description": []
},
"extension": {
"seo": {
"title": "",
"description": "",
"keywords": "",
"canonicalUrl": "",
"noIndex": false,
"noFollow": false,
"hideInSitemap": false
},
"excerpt": {
"title": "",
"more": "",
"description": "",
"categories": [],
"tags": [],
"icon": null,
"image": null
}
},
"author": "2",
"authored": "2024-01-15T10:00:00+0000",
"changer": 2,
"changed": "2024-03-01T12:00:00+0000",
"creator": 2,
"created": "2024-01-15T10:00:00+0000"
}
```
--------------------------------
### Navigation API Example
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/README.md
Example of a request to the navigation API, specifying depth, flat structure, and excerpt inclusion. This API provides navigation tree data.
```http
/api/navigations/main?depth=2&flat=false&excerpt=true
```
--------------------------------
### Search API Example
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/README.md
Example of a request to the search API, including a query parameter for the search term. This API allows searching content within Sulu.
```http
/api/search?q=CMS
```
--------------------------------
### Example JSON Output for Color Picker Resolver
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
This JSON demonstrates the expected output for a page field using the `ColorPickerResolver`. It shows how the serialized `content` and `view` data are structured.
```json
// Resulting JSON for a page with a "brand_color" field using this resolver
{
"content": {
"brand_color": "#ff5733"
},
"view": {
"brand_color": { "hex": "#FF5733" }
}
}
```
--------------------------------
### Page Content as JSON Example
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/README.md
This JSON object represents the content of a page delivered via the HeadlessWebsiteController. It includes page data, meta information, and extension details like SEO and excerpt.
```json
{
"id": "a5181a5a-b030-4933-b3b0-e9faf7ec756c",
"type": "page",
"template": "headless-template",
"content": {
"title": "Headless Example Page",
"url": "/headless-example",
"contacts": [
{
"id": 416,
"firstName": "Homer",
"lastName": "Simpson",
"fullName": "Homer Simpson",
"title": "Dr. ",
"position": "Nuclear safety Inspector at the Springfield Nuclear Power Plan"
}
]
},
"view": {
"title": [],
"url": [],
"contacts": []
},
"extension": {
"seo": {
"title": "",
"description": "",
"keywords": "",
"canonicalUrl": "",
"noIndex": false,
"noFollow": false,
"hideInSitemap": false
},
"excerpt": {
"title": "",
"more": "",
"description": "",
"categories": [],
"tags": [],
"icon": null,
"image": null
}
},
"author": "2",
"authored": "2019-12-03T11:01:38+0100",
"changer": 2,
"changed": "2020-01-30T07:47:46+0100",
"creator": 2,
"created": "2019-12-03T11:01:38+0100"
}
```
--------------------------------
### Implement Custom Color Picker Content Type Resolver
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
Implement the `ContentTypeResolverInterface` to serialize custom content types like a color picker. This example normalizes color values and provides metadata for the frontend.
```php
null]);
}
// Normalize to lowercase hex, expose raw value in view for frontend
return new ContentView(
\strtolower($data), // content: used in JSON response "content" key
['hex' => $data], // view: used in JSON response "view" key
);
}
}
```
--------------------------------
### Custom Controller Using StructureResolver
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
This PHP example shows how to inject and use the `StructureResolverInterface` within a custom controller to resolve dimension content to a JSON-serializable array, including extensions.
```php
getLocale();
$snippet = $this->snippetRepository->findOneBy([
'uuid' => $uuid,
'locale' => $locale,
'stage' => DimensionContentInterface::STAGE_LIVE,
]);
if (null === $snippet) {
return new JsonResponse(['error' => 'Snippet not found'], 404);
}
$dimensionContent = $this->contentAggregator->aggregate($snippet, [
'locale' => $locale,
'stage' => DimensionContentInterface::STAGE_LIVE,
]);
// Resolve the full structure including SEO/excerpt extensions
$data = $this->structureResolver->resolve($dimensionContent, $locale, includeExtension: true);
return new JsonResponse($data);
}
}
```
--------------------------------
### Fetch Flat Navigation List from UUID Subtree
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
Retrieves a flat list of navigation items starting from a specific UUID, with a maximum depth of 3. Useful for fetching specific sections of a navigation tree.
```bash
# Fetch a flat list of navigation items from a specific UUID subtree
curl "https://example.org/en/api/navigations/main?uuid=abc123&flat=true&depth=3"
```
--------------------------------
### Analytics API Response Example
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
This JSON structure represents the data returned by the Analytics API, detailing different tracking services like Google Analytics and Matomo.
```json
[
{
"id": 1,
"title": "Google Analytics",
"allDomains": false,
"content": "G-XXXXXXXXXX",
"type": "google_analytics4",
"webspace": "example"
},
{
"id": 2,
"title": "Matomo",
"allDomains": true,
"content": "",
"type": "custom",
"webspace": "example"
}
]
```
--------------------------------
### Include SuluHeadlessBundle Routes
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/README.md
Configure the bundle's routes by creating a new YAML file in your project's config directory.
```yaml
sulu_headless:
type: portal
resource: "@SuluHeadlessBundle/Resources/config/routing_website.yml"
```
--------------------------------
### Implement DataProviderResolverInterface for Custom Smart Content Data Providers
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
Implement DataProviderResolverInterface to integrate custom Sulu SmartContent data providers. This interface controls how smart content properties fetch and serialize their items and requires implementations to be auto-tagged.
```php
productRepository->findByFilters(
$filters,
$page,
$pageSize ?? 10,
$limit,
);
$items = \array_map(fn($p) => [
'id' => $p->getId(),
'name' => $p->getName(),
'price' => $p->getPrice(),
'slug' => $p->getSlug(),
], $products);
return new DataProviderResult($items, hasNextPage: \count($products) === ($pageSize ?? 10));
}
}
```
--------------------------------
### Fetch Page Content as JSON
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
Fetch page content as JSON by appending `.json` to any page URL. This demonstrates how to consume the headless API.
```bash
curl https://example.org/en/my-page.json
```
--------------------------------
### Fetch Navigation Tree with Excerpt Data
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
Retrieves the main navigation, two levels deep, as a tree structure including excerpt data. Use this to build hierarchical navigation menus with associated metadata.
```bash
# Fetch the main navigation, 2 levels deep, as a tree with excerpt data
curl "https://example.org/en/api/navigations/main?depth=2&flat=false&excerpt=true"
```
```json
{
"_embedded": {
"items": [
{
"id": "abc123",
"uuid": "abc123",
"linkType": null,
"title": "About Us",
"url": "/en/about",
"template": "default",
"locale": "en",
"webspaceKey": "example",
"published": "2024-01-10T09:00:00+00:00",
"publishedState": true,
"authored": "2024-01-10T09:00:00+00:00",
"changed": "2024-02-01T08:00:00+00:00",
"created": "2024-01-10T09:00:00+00:00",
"urls": { "en": "/en/about" },
"excerpt": {
"title": "About Our Company",
"description": "Learn about our history.",
"more": "",
"icon": null,
"image": {
"id": 5,
"title": "About Banner",
"url": "/uploads/media/about.jpg",
"type": "image",
"formatPreferredExtension": "webp",
"formatUri": "/media/5/{format}/about.{extension}?v=1-0"
},
"categories": [],
"tags": []
},
"children": [
{
"id": "def456",
"title": "Our Team",
"url": "/en/about/team",
"children": []
}
]
}
]
}
}
```
--------------------------------
### Enable SuluHeadlessBundle in bundles.php
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/README.md
Register the bundle in your Symfony application's configuration.
```php
return [
/* ... */
Sulu\Bundle\HeadlessBundle\SuluHeadlessBundle::class => ['all' => true],
];
```
--------------------------------
### Serve Page Content as JSON
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
The HeadlessWebsiteController serves full page structures as JSON objects when requests are appended with `.json`. For HTML requests, it falls back to standard rendering and injects the JSON data into a `headless` variable.
```APIDOC
## GET /api/pages/{uuid}.json
### Description
Fetches the content of a specific page as a JSON object.
### Method
GET
### Endpoint
/api/pages/{uuid}.json
### Parameters
#### Path Parameters
- **uuid** (string) - Required - The unique identifier of the page.
### Response
#### Success Response (200)
- **id** (string) - The page ID.
- **type** (string) - The resource type, always "page".
- **template** (string) - The page template key.
- **content** (object) - The page content fields.
- **view** (object) - The view representation of the content.
- **extension** (object) - Page extensions like SEO and excerpt.
- **author** (string) - The ID of the user who authored the page.
- **authored** (string) - The date and time the page was authored.
- **changer** (string) - The ID of the user who last changed the page.
- **changed** (string) - The date and time the page was last changed.
- **creator** (string) - The ID of the user who created the page.
- **created** (string) - The date and time the page was created.
### Request Example
```bash
curl https://example.org/en/my-page.json
```
### Response Example
```json
{
"id": "a5181a5a-b030-4933-b3b0-e9faf7ec756c",
"type": "page",
"template": "default",
"content": {
"title": "My Page",
"description": "Welcome to my headless page."
},
"view": {
"title": [],
"description": []
},
"extension": {
"seo": {
"title": "",
"description": "",
"keywords": "",
"canonicalUrl": "",
"noIndex": false,
"noFollow": false,
"hideInSitemap": false
},
"excerpt": {
"title": "",
"more": "",
"description": "",
"categories": [],
"tags": [],
"icon": null,
"image": null
}
},
"author": "2",
"authored": "2024-01-15T10:00:00+0000",
"changer": 2,
"changed": "2024-03-01T12:00:00+0000",
"creator": 2,
"created": "2024-01-15T10:00:00+0000"
}
```
```
--------------------------------
### Set HeadlessWebsiteController for Page Templates
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/README.md
Configure your page templates to use the HeadlessWebsiteController to serve JSON content. This is typically done in an XML template definition.
```xml
Sulu\Bundle\HeadlessBundle\Controller\HeadlessWebsiteController::indexAction
```
--------------------------------
### Media Serialization: Add extension placeholder
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/UPGRADE.md
Before this update, the preferred extension was always added to the URI. Now, it's extracted into `preferredExtension` and `{extension}` is used in the URI. Non-image media formats omit `formatUri` and `formatPreferredExtension`.
```json
{
"formatUri": "/media/1/{format}/media-1.png?v=1-0"
}
```
```json
{
"formatPreferredExtension": "png",
"formatUri": "/media/1/{format}/media-1.{extension}?v=1-0"
}
```
--------------------------------
### Configure Page Template to Use Headless Controller
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
Configure a page template to use the HeadlessWebsiteController for JSON delivery. This ensures that requests with the .json format return structured page data.
```xml
default
pages/default
Sulu\Bundle\HeadlessBundle\Controller\HeadlessWebsiteController::indexAction
Title
Description
```
--------------------------------
### Navigation API
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
Exposes Sulu navigation contexts as a JSON endpoint, supporting tree and flat output modes, configurable depth, and optional excerpt data.
```APIDOC
## GET /api/navigations/{contextKey}
### Description
Fetches navigation data for a given context key.
### Method
GET
### Endpoint
/api/navigations/{contextKey}
### Parameters
#### Path Parameters
- **contextKey** (string) - Required - The key of the navigation context to retrieve.
#### Query Parameters
- **depth** (integer) - Optional - The maximum depth of the navigation tree to return.
- **flat** (boolean) - Optional - If true, returns a flat list of navigation items instead of a tree.
- **excerpt** (boolean) - Optional - If true, includes excerpt data for each navigation item.
### Response
#### Success Response (200)
- **items** (array) - An array of navigation items, structured as a tree or flat list depending on the `flat` parameter.
### Request Example
```bash
curl https://example.org/en/api/navigations/main?depth=3&flat=true
```
```
--------------------------------
### Fetch Navigation Tree
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
Retrieves the main navigation, up to two levels deep, structured as a tree with excerpt data. Supports parameters for depth, flat structure, and excerpt inclusion.
```APIDOC
## GET /api/navigations/{navigationKey}
### Description
Fetches navigation data for a given navigation key. Supports controlling the depth of the tree, whether the output should be a flat list, and whether to include excerpt data.
### Method
GET
### Endpoint
`/api/navigations/{navigationKey}`
### Query Parameters
- **depth** (integer) - Optional - The maximum depth of the navigation tree to fetch.
- **flat** (boolean) - Optional - If true, returns a flat list of navigation items instead of a tree structure.
- **excerpt** (boolean) - Optional - If true, includes excerpt data for each navigation item.
- **uuid** (string) - Optional - Filters navigation items by a specific UUID, useful for fetching subtrees.
### Response
#### Success Response (200)
Returns a JSON object containing the navigation structure, potentially with `_embedded.items` for tree views or a flat list.
### Request Example
```bash
curl "https://example.org/en/api/navigations/main?depth=2&flat=false&excerpt=true"
```
### Response Example
```json
{
"_embedded": {
"items": [
{
"id": "abc123",
"uuid": "abc123",
"linkType": null,
"title": "About Us",
"url": "/en/about",
"template": "default",
"locale": "en",
"webspaceKey": "example",
"published": "2024-01-10T09:00:00+00:00",
"publishedState": true,
"authored": "2024-01-10T09:00:00+00:00",
"changed": "2024-02-01T08:00:00+00:00",
"created": "2024-01-10T09:00:00+00:00",
"urls": { "en": "/en/about" },
"excerpt": {
"title": "About Our Company",
"description": "Learn about our history.",
"more": "",
"icon": null,
"image": {
"id": 5,
"title": "About Banner",
"url": "/uploads/media/about.jpg",
"type": "image",
"formatPreferredExtension": "webp",
"formatUri": "/media/5/{format}/about.{extension}?v=1-0"
},
"categories": [],
"tags": []
},
"children": [
{
"id": "def456",
"title": "Our Team",
"url": "/en/about/team",
"children": []
}
]
}
]
}
}
```
```
--------------------------------
### Search Content with Highlighting
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
Performs a full-text search across content, automatically filtering by locale and webspace. Matched terms in `title` and `content` fields are highlighted.
```bash
# Search for pages matching "headless CMS"
curl "https://example.org/en/api/search?q=headless+CMS"
```
```json
{
"_embedded": {
"hits": [
{
"id": "page-uuid-001",
"title": "Headless CMS Overview",
"url": "/en/headless-cms-overview",
"locale": "en",
"resourceKey": "pages",
"resourceId": "page-uuid-001",
"content": "Sulu is a powerful headless CMS built on Symfony...",
"authoredAt": "2024-02-01T00:00:00+00:00",
"webspaces": ["example"],
"_formatted": {
"title": "Headless CMS Overview",
"content": "Sulu is a powerful headless CMS..."
},
"media": {
"id": 12,
"title": "CMS Diagram",
"url": "/uploads/media/cms-diagram.png",
"type": "image",
"formatPreferredExtension": "webp",
"formatUri": "/media/12/{format}/cms-diagram.{extension}?v=1-0"
}
}
]
}
}
```
--------------------------------
### DataProviderResolverInterface Namespace Change
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/UPGRADE.md
The import path for ProviderConfigurationInterface has changed. Update the use statement to reflect the new namespace.
```php
use Sulu\Component\SmartContent\Configuration\ProviderConfigurationInterface;
```
```php
use Sulu\Bundle\AdminBundle\SmartContent\Configuration\ProviderConfigurationInterface;
```
--------------------------------
### Fetch Analytics Configuration via API
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
Use this endpoint to retrieve analytics configurations managed in the Sulu admin for headless frontends. It returns tracking script details like IDs and types.
```bash
curl "https://example.org/en/api/analytics.json"
```
--------------------------------
### Controller Attributes: Changed data passed to templates
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/UPGRADE.md
The `HeadlessWebsiteController` now passes data compatible with Sulu's `DefaultController`. The `jsonData` attribute is removed; use `headless|json_encode` instead. The `headless` attribute contains data generated by the `StructureResolver`.
```php
[
"type" => "page",
"authored" => "2020-11-25T14:31:23+0000",
"changed" => "2020-11-25T16:23:59+0000",
"created" => "2020-11-25T14:31:24+0000",
"content" => ["...content resolved by the StructureResolver"],
"view" => ["...view resolved by the StructureResolver"],
"extension" => ["...extension resolved by the StructureResolver"],
"jsonData" => "json string representation of data returned by the StructureResolver"
]
```
```twig
{{ jsonData|raw }}
```
```php
[
"authored" => DateTime::class,
"changed" => DateTime::class,
"created" => DateTime::class,
"content" => ["...content resolved by the DefaultController"],
"view" => ["...view resolved by the DefaultController"],
"extension" => ["...extension resolved by the DefaultController"],
"headless" => [
"type" => "page",
"authored" => "2020-11-25T14:31:23+0000",
"changed" => "2020-11-25T16:23:59+0000",
"created" => "2020-11-25T14:31:24+0000",
"content" => ["...content resolved by the StructureResolver"],
"view" => ["...view resolved by the StructureResolver"],
"extension" => ["...extension resolved by the StructureResolver"],
]
]
```
```twig
{{ headless|json_encode|raw }}
```
--------------------------------
### Navigation API
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/README.md
Provides JSON API for accessing navigation data.
```APIDOC
## GET /api/navigations/{contextKey}
### Description
Retrieves navigation data for a given context key.
### Method
GET
### Endpoint
`/api/navigations/{contextKey}`
### Parameters
#### Path Parameters
- **contextKey** (string) - Required - The key of the navigation context.
#### Query Parameters
- **depth** (integer) - Optional - Maximum depth of the navigation tree that is loaded. Defaults to `1`.
- **flat** (boolean) - Optional - Return navigation as flat list instead of tree. Defaults to `false`.
- **excerpt** (boolean) - Optional - Include excerpt data in the returned navigation. Defaults to `false`.
### Request Example
`/api/navigations/main?depth=2&flat=false&excerpt=true`
```
--------------------------------
### Serialize Media Entities to JSON with MediaSerializer
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
Inject and use MediaSerializer in a custom service to convert Sulu MediaInterface entities into JSON-safe arrays. This process strips internal fields and generates format URIs.
```php
*/
public function serializeForApi(MediaInterface $media, string $locale): array
{
return $this->mediaSerializer->serialize($media, $locale);
}
}
```
```json
{
"id": 42,
"title": "Hero Banner",
"description": "Main hero image",
"locale": "en",
"url": "/uploads/media/hero-banner.jpg",
"type": "image",
"mimeType": "image/jpeg",
"size": 204800,
"width": 1920,
"height": 1080,
"formatPreferredExtension": "webp",
"formatUri": "/media/42/{format}/hero-banner.{extension}?v=1-0"
}
```
--------------------------------
### HeadlessWebsiteController Method Renaming
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/UPGRADE.md
The resolveStructure method has been renamed to resolveHeadlessData. Update your calls to use the new method name and ensure it receives the correct parameters.
```php
protected function resolveStructure(StructureInterface $structure): array;
```
```php
protected function resolveHeadlessData(DimensionContentInterface $object, string $locale): array;
```
--------------------------------
### Page Content Delivery
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/README.md
The HeadlessWebsiteController delivers page content as a JSON object. This can be enabled per template by setting the controller to Sulu\Bundle\HeadlessBundle\Controller\HeadlessWebsiteController::indexAction. The content is available via `{pageUrl}.json`.
```APIDOC
## GET {pageUrl}.json
### Description
Retrieves the content of a page as a JSON object, including meta information like page template and excerpt data.
### Method
GET
### Endpoint
`{pageUrl}.json`
### Response
#### Success Response (200)
- **id** (string) - Unique identifier of the page.
- **type** (string) - Type of the content, typically "page".
- **template** (string) - The template used for the page.
- **content** (object) - The main content of the page.
- **view** (object) - Data for the Twig template view.
- **extension** (object) - Additional extensions like SEO and excerpt.
- **author** (string) - The author of the page.
- **authored** (string) - The date and time the page was authored.
- **changer** (integer) - The user ID of the last changer.
- **changed** (string) - The date and time the page was last changed.
- **creator** (integer) - The user ID of the creator.
- **created** (string) - The date and time the page was created.
### Response Example
```json
{
"id": "a5181a5a-b030-4933-b3b0-e9faf7ec756c",
"type": "page",
"template": "headless-template",
"content": {
"title": "Headless Example Page",
"url": "/headless-example",
"contacts": [
{
"id": 416,
"firstName": "Homer",
"lastName": "Simpson",
"fullName": "Homer Simpson",
"title": "Dr. ",
"position": "Nuclear safety Inspector at the Springfield Nuclear Power Plan"
}
]
},
"view": {
"title": [],
"url": [],
"contacts": []
},
"extension": {
"seo": {
"title": "",
"description": "",
"keywords": "",
"canonicalUrl": "",
"noIndex": false,
"noFollow": false,
"hideInSitemap": false
},
"excerpt": {
"title": "",
"more": "",
"description": "",
"categories": [],
"tags": [],
"icon": null,
"image": null
}
},
"author": "2",
"authored": "2019-12-03T11:01:38+0100",
"changer": 2,
"changed": "2020-01-30T07:47:46+0100",
"creator": 2,
"created": "2019-12-03T11:01:38+0100"
}
```
```
--------------------------------
### Fetch Snippet Area with Extension Data
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
Retrieves a snippet area's content, including excerpt and SEO extension data. This is useful for globally shared content blocks that require additional metadata for display or SEO purposes.
```bash
# Fetch the "footer" snippet area including excerpt/SEO extension data
curl "https://example.org/en/api/snippet-areas/footer?includeExtension=true"
```
```json
{
"id": "snippet-uuid-789",
"type": "snippet",
"template": "footer",
"content": {
"address": "123 Main Street, Springfield",
"phone": "+1 555 000 1234",
"links": [
{ "title": "Privacy Policy", "url": "/en/privacy" },
{ "title": "Imprint", "url": "/en/imprint" }
]
},
"view": {
"address": [],
"phone": [],
"links": []
},
"extension": {
"excerpt": {
"title": "",
"description": "",
"categories": [],
"tags": []
}
}
}
```
--------------------------------
### HeadlessWebsiteController indexAction Signature Change
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/UPGRADE.md
The signature for the indexAction method in HeadlessWebsiteController has changed. Ensure your implementation matches the new signature which uses DimensionContentInterface and includes a view parameter.
```php
public function indexAction(
Request $request,
StructureInterface $structure,
bool $preview = false,
bool $partial = false
): Response;
```
```php
public function indexAction(
Request $request,
DimensionContentInterface $object,
string $view,
bool $preview = false,
bool $partial = false,
): Response;
```
--------------------------------
### Selection Content Types: View parameter change
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/UPGRADE.md
The view parameter for single and multi-selection content types has been updated for consistency. Single selections now use an `id` object, and multi-selections use an `ids` array within an object.
```json
"view" {
"single_selection": 1,
"multi_selection": [1, 2],
}
```
```json
"view" {
"single_selection": {
"id": 1,
},
"multi_selection": {
"ids": [1, 2]
},
}
```
--------------------------------
### ContentTypeResolverInterface
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
Implement this interface to define how custom or unsupported Sulu content types are serialized into scalar JSON values for headless applications.
```APIDOC
## ContentTypeResolverInterface
### Description
An extension point for serializing custom or unsupported Sulu content types to scalar JSON values. Implement this interface to control the transformation of raw data into `content` and `view` fields in the JSON response.
### Interface Signature
```php
interface ContentTypeResolverInterface
{
public static function getContentType(): string;
public function resolve(mixed $data, FieldMetadata $fieldMetadata, string $locale, array $attributes = []): ContentView;
}
```
### Methods
- **getContentType()**: Returns the string key for the content type, which must match the key registered in Sulu.
- **resolve(mixed $data, FieldMetadata $fieldMetadata, string $locale, array $attributes = [])**: Resolves the raw data into a `ContentView` object containing `content` and `view` data.
### Example Implementation (`ColorPickerResolver`)
```php
null]);
}
// Normalize to lowercase hex, expose raw value in view for frontend
return new ContentView(
\strtolower($data), // content: used in JSON response "content" key
['hex' => $data], // view: used in JSON response "view" key
);
}
}
```
### Resulting JSON Example
```json
// Resulting JSON for a page with a "brand_color" field using this resolver
{
"content": {
"brand_color": "#ff5733"
},
"view": {
"brand_color": { "hex": "#FF5733" }
}
}
```
```
--------------------------------
### Search API
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/README.md
Provides JSON API for searching content.
```APIDOC
## GET /api/search?q={searchTerm}
### Description
Searches for content based on a given search term.
### Method
GET
### Endpoint
`/api/search`
### Parameters
#### Query Parameters
- **q** (string) - Required - The text you want to search for.
### Request Example
`/api/search?q=CMS`
```
--------------------------------
### StructureResolverInterface Signature Change
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/UPGRADE.md
The resolve method in StructureResolverInterface now accepts DimensionContentInterface instead of StructureInterface. Adjust your implementations accordingly.
```php
public function resolve(StructureInterface $structure, string $locale, bool $includeExtension = true): array;
```
```php
public function resolve(DimensionContentInterface $dimensionContent, string $locale, bool $includeExtension = true): array;
```
--------------------------------
### Fetch Snippet Area without Extension Data
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
Retrieves a specific snippet area's content without including any extension data. Use this for globally shared content blocks where only the core content is needed.
```bash
# Fetch the "settings" snippet area without extension data
curl "https://example.org/en/api/snippet-areas/settings"
```
--------------------------------
### Search Content within a Specific Index
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
Searches for content within a designated index, such as 'website'. This allows for targeted searches across specific content types or datasets.
```bash
# Search within a specific index
curl "https://example.org/en/api/search?q=symfony&index=website"
```
--------------------------------
### Analytics API
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
The Analytics API endpoint returns analytics configurations managed in the Sulu admin, enabling headless frontends to integrate tracking scripts without server-side rendering.
```APIDOC
## GET /api/analytics.json
### Description
Retrieves analytics configurations for the current portal URL and webspace. This allows headless frontends to inject tracking scripts managed in Sulu.
### Method
GET
### Endpoint
/api/analytics.json
### Response
#### Success Response (200)
- **analytics** (array) - An array of analytics configuration objects.
- **id** (integer) - Unique identifier for the analytics configuration.
- **title** (string) - The name of the analytics service (e.g., "Google Analytics").
- **allDomains** (boolean) - Indicates if this configuration applies to all domains.
- **content** (string) - The tracking code or identifier (e.g., measurement ID for Google Analytics).
- **type** (string) - The type of analytics service (e.g., "google_analytics4", "custom").
- **webspace** (string) - The webspace associated with this configuration.
### Request Example
```bash
curl "https://example.org/en/api/analytics.json"
```
### Response Example
```json
[
{
"id": 1,
"title": "Google Analytics",
"allDomains": false,
"content": "G-XXXXXXXXXX",
"type": "google_analytics4",
"webspace": "example"
},
{
"id": 2,
"title": "Matomo",
"allDomains": true,
"content": "",
"type": "custom",
"webspace": "example"
}
]
```
```
--------------------------------
### Integrate Headless Data into Twig Template
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
Use the `headless` variable injected into Twig templates for HTML requests to bootstrap a JavaScript Single Page Application (SPA) with pre-resolved data.
```twig
{# templates/pages/default.html.twig — headless variable is always available for HTML requests #}
{{ headless.content.title }}
{# Bootstrap a JS SPA with the pre-resolved headless data #}
```
--------------------------------
### ContentTypeResolverInterface Signature Change
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/UPGRADE.md
Content type resolvers now receive FieldMetadata instead of PropertyInterface. Update the type hint and parameter name in your resolve methods.
```php
public function resolve($data, PropertyInterface $property, string $locale, array $attributes = []): ContentView;
```
```php
public function resolve(mixed $data, FieldMetadata $fieldMetadata, string $locale, array $attributes = []): ContentView;
```
--------------------------------
### StructureResolverInterface
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
The central service for converting DimensionContent objects into resolved arrays suitable for JSON serialization, optionally including SEO/excerpt data.
```APIDOC
## StructureResolverInterface
### Description
The `StructureResolverInterface` (implemented by `StructureResolver`) is the central service that converts a `DimensionContentInterface` object into a fully resolved PHP array suitable for JSON serialization. It iterates through all template fields, delegates each to the appropriate `ContentTypeResolver`, and optionally includes SEO/excerpt extension data.
### Usage
This service is used internally by `HeadlessWebsiteController` and `SnippetAreaController`, but can also be injected directly into custom controllers for specific use cases.
### Example Usage (Custom Controller)
```php
getLocale();
$snippet = $this->snippetRepository->findOneBy([
'uuid' => $uuid,
'locale' => $locale,
'stage' => DimensionContentInterface::STAGE_LIVE,
]);
if (null === $snippet) {
return new JsonResponse(['error' => 'Snippet not found'], 404);
}
$dimensionContent = $this->contentAggregator->aggregate($snippet, [
'locale' => $locale,
'stage' => DimensionContentInterface::STAGE_LIVE,
]);
// Resolve the full structure including SEO/excerpt extensions
$data = $this->structureResolver->resolve($dimensionContent, $locale, includeExtension: true);
return new JsonResponse($data);
}
}
```
```
--------------------------------
### Search API
Source: https://context7.com/sulu/suluheadlessbundle/llms.txt
Provides full-text search capabilities powered by SEAL. It filters results by locale and webspace, highlights matched terms, and resolves referenced media objects.
```APIDOC
## GET /api/search
### Description
Performs a full-text search across content. Results are automatically filtered by locale and webspace, with matched terms highlighted in `title` and `content` fields. Referenced media objects are resolved.
### Method
GET
### Endpoint
`/api/search`
### Query Parameters
- **q** (string) - Required - The search query string.
- **index** (string) - Optional - Specifies the search index to query (e.g., `website`).
### Request Example
```bash
# Search for pages matching "headless CMS"
curl "https://example.org/en/api/search?q=headless+CMS"
# Search within a specific index
curl "https://example.org/en/api/search?q=symfony&index=website"
```
### Response
#### Success Response (200)
Returns a JSON object containing search results, typically under `_embedded.hits`, with highlighted fields and resolved media.
### Response Example
```json
{
"_embedded": {
"hits": [
{
"id": "page-uuid-001",
"title": "Headless CMS Overview",
"url": "/en/headless-cms-overview",
"locale": "en",
"resourceKey": "pages",
"resourceId": "page-uuid-001",
"content": "Sulu is a powerful headless CMS built on Symfony...",
"authoredAt": "2024-02-01T00:00:00+00:00",
"webspaces": ["example"],
"_formatted": {
"title": "Headless CMS Overview",
"content": "Sulu is a powerful headless CMS..."
},
"media": {
"id": 12,
"title": "CMS Diagram",
"url": "/uploads/media/cms-diagram.png",
"type": "image",
"formatPreferredExtension": "webp",
"formatUri": "/media/12/{format}/cms-diagram.{extension}?v=1-0"
}
}
]
}
}
```
```
--------------------------------
### Analytics API
Source: https://github.com/sulu/suluheadlessbundle/blob/3.0/README.md
Endpoint for retrieving analytics data.
```APIDOC
## GET /api/analytics.json
### Description
Retrieves analytics data.
### Method
GET
### Endpoint
`/api/analytics.json`
### Response
#### Success Response (200)
- **(structure not defined in source)** - Description of the returned analytics data.
```