tenbruggencate / productencyclopedia-lite
Shopware 6 product encyclopedia: two-tier educational content (browse grid + deep profiles), server-rendered.
Package info
bitbucket.org/Bruggencate/sw-plugin-productencyclopedia-lite
Type:shopware-platform-plugin
pkg:composer/tenbruggencate/productencyclopedia-lite
Requires
- php: >= 8.2
- shopware/core: ~6.7
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.94
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.0
- shopware/storefront: ~6.7
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- 2.5.0
- 2.4.1
- 2.4.0
- 2.3.9
- 2.3.8
- 2.3.7
- 2.3.6
- 2.3.5
- 2.3.4
- 2.3.3
- 2.3.2
- 2.3.1
- 2.3.0
- 2.2.0
- 2.1.1
- 2.1.0
- 2.0.0
- 1.4.0
- 1.3.1
- 1.3.0
- 1.1.3
- 1.1.2
- dev-feat/custom-fields-card
- dev-feat/product-links
- dev-fix/seo-urls-when-disabled
- dev-feat/admin-entries
- dev-fix/encyclopedia-2-3-9
- dev-docs/packagist-images
- dev-feat/utm-links
- dev-docs/fleet-hygiene
- dev-fix/banner-i18n
- dev-fix/noindex-when-empty
- dev-fix/w1-docs-truth
- dev-fix/scrub-customer-strings
- dev-docs/readme-more-from-links
- dev-feat/encyclopedia-hreflang
- dev-feat/encyclopedia-sitemap-provider
- dev-fix/funnel-url-repoint
- dev-feat/suite-catalog-lite-pro-pairings
- dev-feat/rename-to-lite-package
- dev-feat/tb-suite-card
- dev-docs/lite-pro-strategy-resync-2
- dev-docs/lite-pro-strategy-resync
- dev-docs/cross-promotion
- dev-docs/readme-branding
- dev-chore/refresh-screenshots-v1.3.1
- dev-chore/audit-fixes-v1.3.0
- dev-chore/ux-polish-v1.2.0
- dev-chore/packagist-description-and-screenshot-cleanup
- dev-chore/initial-extraction
This package is auto-updated.
Last update: 2026-10-06 14:13:29 UTC
README
Product Encyclopedia Lite
![]()
Structured educational content pages for Shopware 6. Two-tier index pattern: a lightweight browse grid that grows fast + a curated deep-profile registry that grows slowly. Built for content-heavy catalogs โ teas, wines, spices and the like.
License: MIT ยท Shopware: 6.7.x ยท PHP: 8.2 or newer
๐ฌ๐ง English ยท ๐ณ๐ฑ Nederlands ยท ๐ฉ๐ช Deutsch
Lite tier โ and what Pro adds
Product Encyclopedia Lite (this package, tenbruggencate/productencyclopedia-lite) is the free tier of the Product Encyclopedia family. It handles the foundation: structured educational content pages (browse grid + deep profiles), server-rendered Twig templates, per-sales-channel config and the registry pattern you extend from your hosting project. If you need "give a content-heavy catalog a real encyclopedia layer", Lite is the whole answer.
Product Encyclopedia Pro is shipped and installs side by side with Lite โ it requires this package and extends it rather than replacing it. tenbruggencate/productencyclopedia-pro is not on Packagist: it is delivered directly today, with a Shopware Store listing in preparation. Pro 1.x adds the product coupling that Lite 2.4 and older leave out:
- Choose per profile which products are recommended and in what order
- A "Related products" section using Shopware's standard product cards: price, availability and add-to-cart work out of the box
- Managed under Settings โ Product Encyclopedia Pro: product picker with search-as-you-type, list with edit and delete; EN/NL/DE
- Robust: deleted products lose their links automatically, no duplicate links, profiles without links stay unchanged
- Twig helpers
tb_pepro_related_products()andtb_pepro_load_related_products()for your own templates - Export all data button: JSON with links and configuration, also via API; keep or remove data on uninstall
Product links moved to Lite (2.5). Linking products to an entry is now part of Lite (see Product links). While Pro 1.x is active it keeps rendering its own "Related products" section and Lite hides its own, so a page never shows two; Pro 2.0 hands its links over to Lite.
โ More about Product Encyclopedia Pro
Screenshots
Neutral storefront screenshots follow in a later release.
What it does
Content-heavy catalogs (teas, wines, spices, knives) need two kinds of educational page โ but they shouldn't grow at the same rate:
- A fast-growing browse grid where every new SKU can appear immediately with a title + thumbnail + one-liner
- A slow-growing deep-profile registry where a handful of curated items get real editorial content (origins, how-to-use, care, history)
Most content plugins force you to pick one. This plugin ships both tiers, linked by slug, so you can add items to the browse grid the day they're in stock and invest in deep profiles at your own pace.
Install
Product Encyclopedia Lite is free and distributable via Composer / Packagist or via the Shopware Store.
composer require tenbruggencate/productencyclopedia-lite
bin/console plugin:refresh
bin/console plugin:install --activate TenBruggencateProductEncyclopedia
bin/console cache:clear
The plugin class name stays TenBruggencateProductEncyclopedia (grandfathered from v1.x โ only the composer package name changed in v2.0.0). If you're upgrading from v1.x see the v2.0.0 changelog entry for the one-line composer manifest update.
Two-tier design
BrowseIndex (lightweight tier)
| Purpose | fast-growing grid for browsing and discovery |
| Data per entry | slug, title, one filterable attribute value, one-liner description |
| Growth rate | fast โ new entries appear the moment they're in stock |
| Example | 40+ teas in a visual grid, filterable by colour (green, black, white) |
ProfileRegistry (rich tier)
| Purpose | curated deep profiles with full editorial content |
| Data per entry | slug, title, description, image, multiple attribute groups, tags, ordered content sections |
| Growth rate | slow โ each entry is a real content commitment |
| Example | 10 teas with origin and harvest data, tasting notes, brewing and storage guidance |
Browse entries have an optional profileSlug that links to a deep profile when one exists. The browse grid works standalone โ not every item needs a deep profile.
Configuration
In the Shopware admin under Settings โ System โ Plugins โ Product Encyclopedia Lite.
| Field | Default | Purpose |
|---|---|---|
enabled | true | Kill switch for all encyclopedia routes |
baseRoute | encyclopedia | Deprecated, ignored. Has no effect on the URLs; will be removed in 3.0 |
itemLabel | Item | What entries are called (tea, wine, spice) |
itemLabelPlural | Items | Plural form |
filterAttribute | colour | Which attribute shows as filter pills on the browse grid |
Routes
| Route ID | Path | Controller |
|---|---|---|
product-encyclopedia.browse | /encyclopedia/browse | BrowseController::index |
product-encyclopedia.profile | /encyclopedia/{slug} | ProfileController::show |
product-encyclopedia.group | /encyclopedia/group/{group}/{value} | AttributeGroupController::show |
While a sales channel has no entries to show, the browse hub is served noindex,follow with no canonical and is omitted from that channel's sitemap โ the same EncyclopediaIndexability rule drives the controller and EncyclopediaUrlProvider, so they cannot drift.
Content in the admin (2.4)
Entries can live in the database instead of (or next to) the PHP registry:
- Tables:
tb_encyclopedia_entry(technicalslug,active,position,filterValue,attributesJSON[{"group": "origin", "values": ["taiwan"]}],tags,canonicalUrl,mediaId),tb_encyclopedia_entry_translation(title,seoSlug,summary,body,faqJSON[{"question": "โฆ", "answer": "โฆ"}],metaTitle,metaDescription,customFields) andtb_encyclopedia_entry_sales_channel(no rows = every sales channel). All fields are available in the Admin API astb_encyclopedia_entry. - HTML: only
bodyaccepts HTML. It is sanitised on write with thetb_encyclopedia_bodyset (h2โh4, p, br, lists, a, strong/em/b/i, blockquote, figure/figcaption/img, tables). Everything else is plain text and escaped on output. - SEO URLs: each entry gets a Shopware SEO URL per sales channel and language, default template
{{ prefix }}/{{ slug }}(Settings โบ SEO, routeproduct-encyclopedia.profile).prefixisencyclopedie(nl),lexikon(de),encyclopedia(others);slugis the language's ownseoSlug, else a slug of its own title. The overview getsencyclopedie//encyclopedia//lexikon/. The technical routes (/encyclopedia/{slug},/encyclopedia/browse) keep working and 301 to the SEO URL. After adding a domain or editing the template, runbin/console dal:refresh:index --only=tb_encyclopedia_entry.indexer. - Registry + database:
EncyclopediaProviderInterfacemerges both. A database entry with the same slug as a registry item wins, even when inactive (log notice, once). - Page: automatic table of contents from the body's H2s (from two headings), FAQ as
<details>plus FAQPage JSON-LD,dateModifiedin the Article JSON-LD. An entry withcanonicalUrlredirects (301) there and stays out of the sitemap. - Cache + sitemap: HTTP cache tags
tb-encyclopedia-listing,tb-encyclopedia-entry-<id>andtb-encyclopedia-profile-<slug>, invalidated on every entry write. The sitemap lists SEO URLs with the entry'supdated_ataslastmod. - Switching it off: the per-sales-channel
enabledsetting still returns 404 on every encyclopedia URL of that channel, SEO URLs included, and empties its sitemap part.
Admin module (2.4)
Content โบ Encyclopedia in the administration:
- List: search (title, slug), sales-channel filter, sort by position / title / slug, an active switch per row, delete. Entries defined in the PHP registry are listed read-only with a Code badge; "Copy to editable entry" imports one into the database (the DB entry then takes over the slug).
- Detail: tabs General (title, slug, active, position, sales channels โ none = all, image), Content (summary, text editor โ HTML sanitised on save, FAQ repeater), Attributes (groups with values, filter value, tags) and SEO (SEO slug, meta title / description, link target, current SEO URLs). Translated fields follow the language switch.
- Link target (
canonicalUrl): an absolutehttp(s)://URL or a root-relative path (/โฆ), e.g. a category page โ the entry then redirects (301) there and stays out of the sitemap. - ACL: roles
tb_encyclopedia.viewer/.editor/.creator/.deleter(Settings โบ Users & permissions โบ Content โบ Encyclopedia). - Server-side validation (admin, Admin API and import alike): slug format
[a-z0-9]with single-/_separators, max. 120 chars, unique; reserved slugsbrowse,group,a-z,searchand the overview prefixes (encyclopedia,encyclopedie,lexikon, plus a literal template prefix); no two active entries with the same SEO URL in one sales channel + language (the error names the other entry); link target http(s) or/โฆ;attributes,tagsandfaqJSON shape. - Overview prefix: follows the entry SEO template. With the default
{{ prefix }}/{{ slug }}the overview lives atencyclopedie//encyclopedia//lexikon/; with a fixed first segment, e.g.kennisbank/{{ slug }}, it lives atkennisbank/in every language. SEO URLs are written on plugin activation / update, on every entry write and (queued) when a sales channel domain or the template changes.
Import and export (2.4)
Admin: Export all, Export selected, Import JSON (shows a dry-run diff first: create / update / unchanged / error per entry; Import now applies it). Console:
bin/console tb:encyclopedia:export [--file=entries.json] # stdout without --file
bin/console tb:encyclopedia:import entries.json [--dry-run] # upsert by slug
bin/console tb:encyclopedia:import-registry [--dry-run] [--file=registry.json]
Format (format is versioned: 2.5 writes tb-encyclopedia/2 and still imports tb-encyclopedia/1 files, which have no products):
{
"format": "tb-encyclopedia/2",
"exportedAt": "2026-10-06T12:00:00+00:00",
"entries": [{
"slug": "oolong", "active": true, "position": 0, "filterValue": "half-oxidised",
"attributes": [{"group": "origin", "values": ["taiwan"]}], "tags": ["tea"],
"canonicalUrl": null, "media": {"id": "0190โฆ", "fileName": "oolong.jpg"},
"salesChannels": ["Storefront"],
"translations": {
"default": {"title": "Oolong", "seoSlug": null, "summary": "โฆ", "body": "<h2>โฆ</h2><p>โฆ</p>",
"faq": [{"question": "โฆ", "answer": "โฆ"}], "metaTitle": null, "metaDescription": null, "customFields": null},
"nl-NL": {"title": "Oolong", "summary": "โฆ"}
},
"products": [{"productNumber": "SW10012", "id": "0191โฆ", "position": 0}]
}]
}
default= the system language; other keys are locale codes. Sales channels by name or id;[]= all.- Upsert by
slug; keys missing from an entry stay untouched.mediais only linked when that media id exists in the target shop (files are never downloaded). - The body is sanitised (same allow-list as the admin) and every entry is validated like an API write. All or nothing: one invalid entry aborts the whole import;
--dry-runruns the same checks and rolls back. products(format 2): the complete list of linked products of that slug, matched byproductNumber(portable between shops), theidas fallback; a product the target shop doesn't have is skipped with a warning.[]removes every link; noproductskey (e.g. a format 1 file) leaves the links untouched.import-registryconverts the PHP registry: text intodefault,contentSectionsinto<h2>heading</h2>+ body, the filter value from the browse tile, images reported (not imported), browse tiles without a profile skipped.
Product links (2.5)
Show products on an encyclopedia page โ moved down from Pro 1.x.
- Admin: tab Products on the entry detail page (search by name or product number, add, move up / down, remove; saved right away, available once the entry is saved). Registry (code) items get a Products button in the list.
- Storefront: the linked products appear as Shopware's standard product boxes below the content, in your order, up to 24. Only products visible in the current sales channel are shown (same rules as cross-selling: active, visibility "everywhere", closeout products hidden when out of stock if the shop is set up that way). The page is tagged with every linked product (
product-<id>), so a price, stock or visibility change refreshes it; changing a link refreshestb-encyclopedia-profile-<slug>. - Table:
tb_encyclopedia_product_link(entrySlug,productId+productVersionId,position; unique per slug + product). Keyed by slug, so registry items can carry products too; renaming an entry's slug moves its links along; deleting a product deletes its links. - Coming from Pro 1.x: the 2.5.0 update copies the rows of Pro's
tb_pepro_profile_product_link(live product version, existing links kept, Pro's table untouched). While Pro 1.x is active, Lite's product section is hidden and Pro's is shown; links you add in Lite in the meantime appear once Pro is updated to 2.0 (which re-syncs late Pro edits and then removes its own table). - Export/import: included as
products(see above). Uninstalling without keep user data drops the table.
Populating with data
The plugin ships with empty registries. Extend ArrayProfileRegistry in your theme plugin:
final class MyTeaRegistry extends ArrayProfileRegistry
{
protected function buildItems(): array
{
return [
'sencha' => new ProfileItem(
slug: 'sencha',
title: 'Sencha',
description: 'A steamed Japanese green tea.',
imageUrl: '/images/sencha.jpg',
attributeGroups: [
['name' => 'origin', 'values' => ['japan']],
['name' => 'colour', 'values' => ['green']],
],
tags: ['grassy', 'green-tea'],
contentSections: [
['heading' => 'Brewing', 'body' => 'Steep at 70โ80 ยฐC for one to two minutes...'],
],
),
];
}
}
Register your subclass in services.xml:
<service id="TenBruggencateProductEncyclopedia\Registry\ProfileRegistryInterface"
class="MyPlugin\Registry\MyTeaRegistry"/>
Standards
- Performance โ registries are in-memory arrays; zero DB queries for profile lookup. Browse grid uses server-side filtering (no JS framework, works without JavaScript).
- SEO โ every profile page emits structured
ArticleJSON-LD.meta_titleandmeta_descriptionare derived from the profile data and overridable per entry. Filter-pill URLs are crawlable as/encyclopedia/group/{attribute}/{value}(server-rendered, no#fragmentrouting). - GDPR โ stateless. No cookies, no tracking, no per-visitor data. Full data-flow documentation in
GDPR.md. - WCAG 2.2 AA โ semantic heading hierarchy (
h1โ profile title;h2โ content section headings); filter pills are<a>tags (keyboard + screen-reader accessible); focus state inherited from theme. Live axe-core audit output + localised-copy evidence:docs/ACCESSIBILITY.md. - Security โ all profile / browse data comes from PHP registries; no user-controllable input reaches templates or DB. No XSS surface.
- Uninstall โ
plugin:uninstall --keep-user-datapreserves everyTenBruggencateProductEncyclopedia.config.*row; without the flag the destructive path clears them all. No owned tables โ content comes from your hosting project's registries, not from this plugin.
Production-readiness checklist
A deliberately short list of things to verify before enabling the plugin on a customer-facing storefront. Not legal cover โ the MIT license already disclaims warranty โ but practical guidance an experienced operator would want anyway.
- [ ] Provide BrowseEntry + ProfileItem registries from your hosting project. This plugin defines the shape (interfaces, controllers, templates) but doesn't ship content โ your theme plugin or a content-only sibling registers the actual entries. With no registry wired in,
/encyclopedia/browserenders an empty grid and profile slugs return 404. Plan the content shape before flipping the install on prod. - [ ] Know that the URLs are fixed. The pages live at
/encyclopedia/*(browse hub, attribute groups, profiles). Neither thebaseRoutesetting nor Shopware's SEO URL templates change that. If you need another prefix (/teas/*), override the routes in your own plugin. - [ ] Test profile-slug โ browse-entry linkage on staging. Browse cards optionally link to deep profiles via
profileSlug; a typo in either side silently breaks the cross-link without a 404 (the card just doesn't become a link). Render a few cards and confirm the ones with deep profiles do link out. - [ ] Run axe-core on a profile page before launch. The plugin's templates are WCAG-clean, but your theme's typography + colour-contrast applies once tokens are inherited โ the audit has to happen with your theme active, not against the plugin in isolation.
- [ ] Plan content cadence honestly. The two-tier model only pays off if browse entries grow fast and profiles grow slow. Shipping 20 cards with 0 deep profiles is fine; shipping 20 cards with 20 half-finished profiles is a maintenance burden visible to every visitor โ leave a slug empty rather than ship Lorem Ipsum.
Snippets
Ships with translations for nl-NL, en-GB, and de-DE. Override in your theme plugin's snippet JSON files using the product-encyclopedia.* key namespace.
Compatibility
Core platform
| Shopware | PHP | Status |
|---|---|---|
| 6.7.x โ tested with 6.7.15 | 8.2 or newer | Stable |
| 6.6.x | โ | Not supported |
| 6.5.x and earlier | โ | Not supported |
Database
| Engine | Version | Notes |
|---|---|---|
| MySQL | 8.0+ | Primary target; JSON functions used for config-row manipulation in migrations |
| MariaDB | 10.11+ | Tested end-to-end; earlier versions lack some JSON operator support |
Browsers (storefront)
Evergreen browsers only โ the two most recent stable releases of each:
| Browser | Desktop | Mobile |
|---|---|---|
| Chrome / Chromium | โ | โ |
| Firefox | โ | โ |
| Safari | โ (macOS) | โ (iOS 16+) |
| Edge | โ | โ |
Internet Explorer and legacy Edge are not supported. The plugin emits no runtime JS (where applicable) so graceful degradation on older browsers usually still renders content, just without progressive enhancements.
Admin browsers
Same evergreen matrix โ the Shopware admin is Vue-based and has its own compatibility baseline that this plugin doesn't extend or narrow.
Development
| Tool | Version | Scope |
|---|---|---|
| PHP | โฅ 8.2 | Runtime + test suite |
| Composer | 2.x | Dependency management |
| Node.js | โฅ 18 | Only needed if you edit SCSS and re-run the theme compile |
Accessibility
WCAG 2.2 level A + AA โ see docs/ACCESSIBILITY.md for axe-core audit output and per-page violations.
What we test before each release
- Full PHPUnit unit suite against PHP 8.2 (source-inspection tests don't need a kernel)
- PHPStan level 8 + PHP-CS-Fixer (@PSR12 + @Symfony)
- Composer validate on every plugin
- Live-DB smoke tests (plugin install โ activate โ route render โ uninstall cycle) against Shopware 6.7.15
- axe-core audit on the primary storefront surfaces (see ACCESSIBILITY.md)
Related plugins
Sibling plugins from the same publisher:
- TenBruggencateMultiBrand โ when active, profiles render with per-brand
--brand-*tokens so the same encyclopedia looks distinct across brand domains - TenBruggencateAnalytics โ profile views and filter-pill clicks are tracked as custom events when Analytics is active
- TenBruggencateNewsletterLite โ GDPR-safe newsletter signup with double opt-in
- TenBruggencateMaintenance โ branded maintenance page with HTTP 503 + Retry-After
- TenBruggencateLegalPages โ drop-in legal templates with merge fields
Support
- Email: guy@tenbruggencatedevelopment.nl
- Docs & news: tenbruggencatedevelopment.nl
- Source / issues: Bitbucket repo
- Security vulnerabilities: see
SECURITY.mdโ email first, no public issues, 72-hour acknowledgement SLA
License
MIT ยฉ Ten Bruggencate Development
More from Ten Bruggencate Development
Free Lite plugins for Shopware 6.7, each with a Pro edition for when you need more. Overview: tenbruggencatedevelopment.nl/en/initiatieven/shopware-plugins
- Analytics โ Matomo or Plausible, cookieless, with e-commerce events
- Legal Pages โ terms, privacy, shipping and returns pages from templates ยท Pro: cookie consent, accessibility statement
- Maintenance โ a branded, SEO-correct (HTTP 503) maintenance page
- Multi-Brand โ several brands on one Shopware, recognised by domain
- Newsletter โ GDPR-safe sign-up with double opt-in ยท Pro: campaigns and segments
- Product Encyclopedia โ educational content pages linked to your products
- Seasons โ scheduled theme variants (colours, typography, hero)
- Social Login โ passwordless login link, Google and Facebook
- Stock Alert โ "notify me when it's back" with double opt-in