### 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 ``` -------------------------------- ### 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 ``` -------------------------------- ### 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. ```