Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ body {
}

.md-typeset h1 {
margin: 0 0 1rem;
margin: 0 0 0.5rem;
font-size: 24px;
line-height: 34px;
}
Expand Down
68 changes: 68 additions & 0 deletions llmstxt_preprocess.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from bs4 import BeautifulSoup


def preprocess(soup: "BeautifulSoup", output: str) -> None:

Check failure on line 7 in llmstxt_preprocess.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 22 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=ezsystems_developer-documentation&issues=AZ2wjFvdQSoJ_LA-xC9-&open=AZ2wjFvdQSoJ_LA-xC9-&pullRequest=3161

Check warning on line 7 in llmstxt_preprocess.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the unused function parameter "output".

See more on https://sonarcloud.io/project/issues?id=ezsystems_developer-documentation&issues=AZ2wjFvdQSoJ_LA-xC99&open=AZ2wjFvdQSoJ_LA-xC99&pullRequest=3161
"""
Preprocess HTML to improve markdown conversion.

Converts card macro HTML structure into markdown lists with links
so they are preserved in the llms.txt output.

Filters out release notes filter UI elements.
"""
# Remove release notes filter UI (checkboxes and labels)
# These are interactive filters, not content
filter_containers = soup.find_all("div", class_="release-notes-filters")
for container in filter_containers:
container.decompose()

# Find all cards wrapper divs (these contain groups of cards)
cards_divs = soup.find_all("div", class_=lambda c: c and c.startswith("cards "))

for cards_div in cards_divs:
# Find all card-wrapper divs within this cards group
card_wrappers = cards_div.find_all("div", class_="card-wrapper")

if not card_wrappers:
continue

# Create a list to hold all the cards in this group
ul = soup.new_tag("ul")

for card_wrapper in card_wrappers:
# Extract the link, title, and description from the card structure
link = card_wrapper.find("a", class_="card")
if not link:
continue

href = link.get("href", "")
# Fix protocol-relative URLs
if href.startswith("//"):
href = "https:" + href

title_elem = link.find("p", class_="title")
description_elem = link.find("p", class_="description")

if not title_elem:
continue

title = title_elem.get_text(strip=True)
description = description_elem.get_text(strip=True) if description_elem else ""

# Create a list item with a link and description
li = soup.new_tag("li")
link_tag = soup.new_tag("a", href=href)
link_tag.string = title
li.append(link_tag)

if description:
li.append(soup.new_string(" - "))
li.append(soup.new_string(description))

ul.append(li)

# Replace the entire cards div with the unordered list
cards_div.replace_with(ul)
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ INHERIT: plugins.yml

site_name: Developer Documentation
repo_url: https://github.com/ibexa/documentation-developer
edit_uri: edit/5.0/docs/
site_url: https://doc.ibexa.co/en/latest/
copyright: "Copyright 1999-2026 Ibexa AS and others"
validation:
Expand Down
155 changes: 155 additions & 0 deletions plugins.yml
Original file line number Diff line number Diff line change
Expand Up @@ -586,3 +586,158 @@ plugins:
'ai_actions/install_ai_actions.md': 'ai_actions/configure_ai_actions.md'
'discounts/install_discounts.md': 'discounts/configure_discounts.md'
'content_management/collaborative_editing/install_collaborative_editing.md': 'content_management/collaborative_editing/configure_collaborative_editing.md'
- llmstxt:
preprocess: llmstxt_preprocess.py
markdown_description: |
> Ibexa DXP developer documentation - comprehensive technical guide for building digital experiences with Ibexa, a modern PHP-based Digital Experience Platform built on Symfony Full Stack Framework.
Ibexa is an enterprise-grade content management and digital commerce platform that comes in three editions: Headless (API-first content management), Experience (full DXP with Page Builder and forms), and Commerce (complete e-commerce solution).
Key technical capabilities include: flexible content modeling with custom field types, powerful REST and GraphQL APIs, headless and traditional architecture support, Product Information Management (PIM), integrated commerce features (cart, checkout, payment, shipping), multi-site and multi-language support, advanced search with Elasticsearch/Solr, customizable Twig templating, Symfony-based extensibility, workflow management, AI Actions for content generation, Form Builder, and comprehensive user/permission management.
The platform is designed for developers to build scalable content-driven applications, e-commerce sites, and headless solutions with enterprise features like Customer Data Platform (CDP), personalization, editorial workflows, and extensive APIs. Built with modern PHP practices on Symfony 7.x, supporting MySQL/MariaDB and PostgreSQL databases.
full_output: llms-full.txt
sections:
Ibexa Developer Documentation:
- index.md
Ibexa DXP editions:
- ibexa_products/*.md
Getting started:
- getting_started/*.md
Tutorials:
- tutorials/tutorials.md
- tutorials/beginner_tutorial/*.md
- tutorials/generic_field_type/*.md
- tutorials/page_and_form_tutorial/*.md
API:
- api/api.md
- api/event_reference/*.md
- api/graphql/*.md
- api/php_api/php_api.md
- api/rest_api/rest_api_authentication.md
- api/rest_api/extending_rest_api/*.md
- api/rest_api/rest_api_usage/*.md
Administration:
- administration/administration.md
- administration/admin_panel/*.md
- administration/back_office/*.md
- administration/back_office/back_office_elements/*.md
- administration/back_office/back_office_menus/*.md
- administration/back_office/back_office_tabs/*.md
- administration/back_office/browser/*.md
- administration/configuration/*.md
- administration/content_organization/*.md
- administration/dashboard/*.md
- administration/project_organization/*.md
- administration/recent_activity/recent_activity.md
Content management:
- content_management/*.md
- content_management/collaborative_editing/*.md
- content_management/content_api/*.md
- content_management/content_management_api/*.md
- content_management/data_migration/*.md
- content_management/field_types/*.md
- content_management/field_types/field_type_reference/*.md
- content_management/file_management/*.md
- content_management/forms/*.md
- content_management/images/*.md
- content_management/pages/*.md
- content_management/rich_text/*.md
- content_management/taxonomy/*.md
- content_management/url_management/*.md
- content_management/workflow/*.md
Templating:
- templating/*.md
- templating/design_engine/*.md
- templating/embed_and_list_content/*.md
- templating/layout/*.md
- templating/queries_and_controllers/*.md
- templating/render_content/*.md
- templating/templates/*.md
- templating/twig_function_reference/*.md
- templating/urls_and_routes/*.md
AI Actions:
- ai_actions/*.md
PIM (Product management):
- pim/*.md
- pim/attributes/*.md
Commerce:
- commerce/commerce.md
- commerce/cart/*.md
- commerce/checkout/*.md
- commerce/order_management/*.md
- commerce/payment/*.md
- commerce/shipping_management/*.md
- commerce/storefront/*.md
- commerce/transactional_emails/*.md
Discounts:
- discounts/*.md
Customer management:
- customer_management/*.md
Ibexa Engage:
- ibexa_engage/*.md
Multisite:
- multisite/*.md
- multisite/languages/*.md
- multisite/site_factory/*.md
- multisite/siteaccess/*.md
Permissions:
- permissions/*.md
Users:
- users/*.md
CDP (Customer Data Platform):
- cdp/*.md
- cdp/cdp_activation/*.md
Search:
- search/*.md
- search/activity_log_search_reference/*.md
- search/aggregation_reference/*.md
- search/ai_actions_search_reference/*.md
- search/collaboration_search_reference/*.md
- search/content_type_search_reference/*.md
- search/criteria_reference/*.md
- search/discounts_search_reference/*.md
- search/extensibility/*.md
- search/search_engines/search_engines.md
- search/search_engines/elasticsearch/*.md
- search/search_engines/legacy_search_engine/*.md
- search/search_engines/solr_search_engine/*.md
- search/sort_clause_reference/*.md
- search/url_search_reference/*.md
Ibexa Cloud:
- ibexa_cloud/*.md
Infrastructure and maintenance:
- infrastructure_and_maintenance/*.md
- infrastructure_and_maintenance/cache/*.md
- infrastructure_and_maintenance/cache/http_cache/*.md
- infrastructure_and_maintenance/clustering/*.md
- infrastructure_and_maintenance/security/*.md
Update and migration:
- update_and_migration/update_ibexa_dxp.md
- update_and_migration/from_4.0/to_4.1.md
- update_and_migration/from_4.1/update_from_4.1.md
- update_and_migration/from_4.2/update_from_4.2.md
- update_and_migration/from_4.3/*.md
- update_and_migration/from_4.4/update_from_4.4.md
- update_and_migration/from_4.5/update_from_4.5.md
- update_and_migration/from_4.6/*.md
- update_and_migration/from_5.0/update_from_5.0.md
- update_and_migration/migrate_to_ibexa_dxp/*.md
Resources:
- resources/*.md
- resources/contributing/*.md
Product guides:
- product_guides/product_guides.md
Release notes:
- release_notes/release_notes.md
- release_notes/ibexa_dxp_v5.0.md
- release_notes/ibexa_dxp_v5.0_deprecations.md
- release_notes/ibexa_dxp_v4.6.md
- release_notes/ibexa_dxp_v4.5.md
- release_notes/ibexa_dxp_v4.4.md
- release_notes/ibexa_dxp_v4.3.md
- release_notes/ibexa_dxp_v4.2.md
- release_notes/ibexa_dxp_v4.1.md
- release_notes/ibexa_dxp_v4.0.md
PHP API Reference - Signatures:
- api/php_api/php_api_reference.md
- api/php_api/php_api_signatures.md
REST API Reference:
- api/rest_api/rest_api_reference_overview.md
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ mkdocs-macros-plugin==1.3.7
mkdocs-redirects==1.2.2
mkdocs-autolinks-plugin==0.7.1
Jinja2==3.1.6
mkdocs-llmstxt
103 changes: 103 additions & 0 deletions theme/assets/page-actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/**
* Page Actions JavaScript
* Handles functionality for page action buttons (Copy for LLM, View as Markdown, Edit on GitHub)
*/

async function copyPageForLLM() {

Check failure on line 6 in theme/assets/page-actions.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=ezsystems_developer-documentation&issues=AZ2wjFp9QSoJ_LA-xC94&open=AZ2wjFp9QSoJ_LA-xC94&pullRequest=3161
try {
const mdPath = document.querySelector('meta[name="markdown-path"]').content;
console.log('Fetching from path:', mdPath);

let markdownContent;

try {
const response = await fetch(mdPath);
if (response.ok) {
markdownContent = await response.text();
} else {
throw new Error(`HTTP error! status: ${response.status}`);
}
} catch (fetchError) {
console.log('Direct fetch failed, trying GitHub fallback...');
const editUrl = document.querySelector('meta[name="edit-url"]').content;
const rawUrl = editUrl.replace('/edit/', '/raw/');

try {
const response = await fetch(rawUrl);
if (response.ok) {
markdownContent = await response.text();
} else {
const proxyUrl = `https://api.allorigins.win/get?url=${encodeURIComponent(rawUrl)}`;
const proxyResponse = await fetch(proxyUrl);
if (proxyResponse.ok) {
const proxyData = await proxyResponse.json();
markdownContent = proxyData.contents;
} else {
throw new Error('All fetch methods failed');
}
}
} catch (githubError) {
throw new Error('GitHub fallback failed');
}

Check warning on line 41 in theme/assets/page-actions.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Handle this exception or don't catch it at all.

See more on https://sonarcloud.io/project/issues?id=ezsystems_developer-documentation&issues=AZ2wjFp9QSoJ_LA-xC96&open=AZ2wjFp9QSoJ_LA-xC96&pullRequest=3161
}

Check warning on line 42 in theme/assets/page-actions.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Handle this exception or don't catch it at all.

See more on https://sonarcloud.io/project/issues?id=ezsystems_developer-documentation&issues=AZ2wjFp9QSoJ_LA-xC95&open=AZ2wjFp9QSoJ_LA-xC95&pullRequest=3161

if (!markdownContent) {
throw new Error('No content received');
}

await navigator.clipboard.writeText(markdownContent);
showButtonFeedback('success', 'Copied!', '📋');

} catch (error) {
console.error('Failed to copy content:', error);

try {
const mdPath = document.querySelector('meta[name="markdown-path"]').content;
window.open(mdPath, '_blank');
showButtonFeedback('info', 'Opened in tab', '🔗');
} catch (fallbackError) {
showButtonFeedback('error', 'Failed', '❌');
}

Check warning on line 60 in theme/assets/page-actions.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Handle this exception or don't catch it at all.

See more on https://sonarcloud.io/project/issues?id=ezsystems_developer-documentation&issues=AZ2wjFp9QSoJ_LA-xC97&open=AZ2wjFp9QSoJ_LA-xC97&pullRequest=3161
}
}

function showButtonFeedback(type, message, icon) {
const button = document.querySelector('button[onclick="copyPageForLLM()"]');
if (!button) return;

const originalHTML = button.innerHTML;
button.innerHTML = `${icon} ${message}`;

if (type === 'success') {
button.style.background = '#d4edda';
button.style.borderColor = '#c3e6cb';
button.style.color = '#155724';
} else if (type === 'error') {
button.style.background = '#f8d7da';
button.style.borderColor = '#f5c6cb';
button.style.color = '#721c24';
} else if (type === 'info') {
button.style.background = '#d1ecf1';
button.style.borderColor = '#bee5eb';
button.style.color = '#0c5460';
}

setTimeout(() => {
button.innerHTML = originalHTML;
button.style.background = '';
button.style.borderColor = '';
button.style.color = '';
}, 2000);
}

document.addEventListener('DOMContentLoaded', function() {
console.log('Page actions initialized');

const pageActions = document.getElementById('page-actions');
const firstH1 = document.querySelector('.bootstrap-iso h1, h1');

if (pageActions && firstH1) {
firstH1.insertAdjacentElement('afterend', pageActions);

Check failure on line 100 in theme/assets/page-actions.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `firstH1.after(pageActions)` over `firstH1.insertAdjacentElement('afterend', pageActions)`.

See more on https://sonarcloud.io/project/issues?id=ezsystems_developer-documentation&issues=AZ2wjFp9QSoJ_LA-xC98&open=AZ2wjFp9QSoJ_LA-xC98&pullRequest=3161
pageActions.style.display = 'flex';
}
});
Loading
Loading