Five new storefront surfaces, a Deals page made from prices you already
have, filters that work on a phone, an /llms.txt file that
lets AI shopping agents read your store — and a currency fix that
gives every price its decimal places back.
Core 1.5.0 is out. Until now, building a storefront home page in Solidshop meant creating an empty article, pointing a menu item at it, and hand-writing the HTML for a hero and a “shop by category” band. This release replaces all of that with things you place, configure and reorder like any other Joomla module — and adds the two pages every shop eventually wants: a landing page and a Deals page.
It also fixes something that had been wrong on every install since the beginning: prices were rendering without their decimal places. If you take payments through a gateway, read that section before you update.
A landing page you build from modules
The new Storefront home menu item type is the page everything else sits on. It renders the module positions around it and almost nothing itself — at most a heading and your store tagline — but it does the work a front page needs doing: the page title and meta description come from your store record, the canonical URL points at the site root, and the page publishes an Organization and a WebSite block of structured data built from the store’s own name, logo, address, phone and email. There is a new Tagline field on the store’s SEO tab; it is printed on the page and published as the organisation’s slogan.
Four new storefront modules ship in the core package to fill it:
-
Slideshow (
mod_sshop_slideshow) — the hero. Each slide takes a picture, an eyebrow line, a heading, some text and a button that links to a product, a category, a menu item or any URL, so the hero points into your catalogue rather than at a hand-typed address. It is a CSS scroll-snap track, which means swiping and keyboard scrolling work before any JavaScript runs and the first image loads at high priority; the script then adds previous/next buttons, dots, an optional 3–60 second timer with a Pause button, and screen-reader announcements. A single slide renders as a plain static hero with no controls. The timer stops on hover, on focus, when the tab is hidden, and never runs at all for a visitor whose system asks for reduced motion. -
Category showcase
(
mod_sshop_categories) — the “Shop by category” block, as a 2–6 column grid or a sideways-scrolling strip. Show everything below a parent category to a chosen depth, or pick categories by hand. A tile with no picture of its own borrows the first product’s, so it never renders blank, and an optional product count is calculated with the same rules as the listing it leads to. Categories with nothing published are left out. -
Brands (
mod_sshop_brands) — brands can now carry a logo, and the module prints them as a “Shop by brand” band linking each logo to the catalogue filtered by that brand. A Muted treatment holds every logo to one weight until the shopper points at it, which is what stops a row of mismatched brand artwork looking like a jumble. -
Recently viewed (
mod_sshop_recent) — the products this shopper has looked at, newest first. The trail lives in the session and nowhere else: no table, no profile, nothing to delete afterwards, and it ends when the session does. A product that has since been unpublished or hidden behind an access level quietly gives up its place to an older one instead of shortening the strip.
All four are ordinary Joomla modules, so they follow the usual position, assignment and access rules, and they ship with default templates you can override in your own template.
Deals, from prices you already have
A product is on sale when its compare-at price is higher than what you are charging — the same test the product card has always used to draw its -N% badge. That test is now a first-class filter across the storefront:
- a Products on Sale Only option on the products menu item, which is a Deals page;
- a Show / Hide / Only setting and a Discount ordering on the products module, which is a Deals strip on any page;
- an On sale toggle in the filters module, counted like every other facet and hidden when nothing is on sale;
- and a Biggest discount sort key in the listing sort dropdown — also available through the catalog REST API and the MCP search tool.
This is deliberately about the product’s own two prices and nothing else. A discount that the discount engine works out at cart time is not something a listing can promise, and a page that badged products the cart then charged in full would be worse than no badge at all.
Filters that work on a phone
The filters module used to land above or below the product grid on a narrow screen, which meant scrolling past the entire filter panel to reach the products. Below a configurable width (992 px by default) it now folds into an off-canvas drawer, with a Filters button on the listing toolbar next to the sort control.
Filters keep applying live while the drawer is open, the way they do
in the sidebar, and the drawer’s primary button reads
Show N results so you know what you are about to look at
before you close it. There is a Clear all beside it, and the
toolbar button carries a count of how many filters are active. Set the
width to 0 to keep the panel inline on every screen.
Your store, readable by AI agents
When a shopping assistant, a research agent or a chatbot is asked
“does this shop sell X”, all it has is your domain. The
convention that has settled for answering that is a file at the site
root called llms.txt, and Solidshop now serves one for
every store.
It is rendered on request from your live data — nothing is
written to disk, so nothing goes stale — and it lists the store
name and summary, country, currencies and languages, your top-level
categories, your policy pages, contact details, and the addresses of
the machine-readable interfaces you already publish: the catalog REST
API, the MCP endpoint with its tool names, and the XML sitemap. Two
new fields on the store’s SEO tab let you write the summary and
any notes you want agents to have. If you already have a physical
llms.txt in your web root, that one still wins.
The file is declarative on purpose: it says what exists and where to find it, and never tries to instruct the agent reading it. Anything you type into the notes is escaped, and headings inside it are flattened, so nothing pasted into that box can restructure the document.
One thing to check after updating, under System ›
Dashboard: there is a new AI discovery card
that reads your robots.txt the way a crawler does and
tells you which AI crawlers it currently shuts out — of the
site, and of the catalog API. Joomla ships
Disallow: /api/ as standard, which blocks the very
interface the file points agents at, so that row will be red on an
unmodified install. The card shows you the single Allow:
line that reopens the Solidshop routes and nothing else.
Every Solidshop extension, in one tab
System › Extensions is a new tab listing every Solidshop extension installed on the site — version, enabled or not, whether an update is waiting, and anything wrong with it — followed by the add-ons that exist but are not installed here.
Two things it does that the Joomla extension manager does not. It shows you updates that Joomla’s own installer hides: when an update record was written before Joomla could match it to an installed extension, Extensions › Update silently drops it — which is often exactly the update you are looking for. And it flags an extension that ships an update server but has no update site registered, because Joomla will never offer that extension an update, silently, for as long as it stays installed. Core extensions are grouped as one block, so a stray version number in that group means a half-finished update.
Regenerate images after changing your sizes
Product images are cut into four sizes on upload, and each file is named after the size it was cut at. Change a size or the aspect ratio under Options › Media and the existing library does not follow — the storefront starts asking for files that were never written. Until now the only way back was re-uploading everything.
The media manager now counts the images whose files no longer match your settings and offers a Regenerate images button: a batched run with a progress bar and a written / up-to-date / failed summary. Images already at the right sizes are skipped, so a run interrupted by a closed tab simply resumes when you start it again. There is a force option that rewrites everything, and a prune option that deletes derivatives at sizes you no longer use. For a large catalogue, the same job runs from the command line:
php cli/joomla.php solidshop:media:regenerate --store=1 --dry-run
Prices have their decimal places back
This is the fix to read carefully. Solidshop has been rendering every
price without its minor unit — a $104.32 product read
USD104 on product cards, in the cart, at checkout, on
invoices and in order emails. The currency formatter fell back to
0 decimal places when a currency had no settings of
its own, while the admin form that writes the same setting defaults to
2; since no currency has ever shipped with settings,
the fallback is what every store on every install was using.
The same number is what turns a price into the integer “minor unit” amount a payment gateway is charged. With zero decimal places, a $104.32 order was worth 104 minor units to a gateway reading it — a hundredth of the real total. The fallback is now 2, matching the form.
The update also corrects the currencies whose ISO 4217 minor unit is genuinely not 2 — yen and won have none, the Bahraini dinar has three — but only where you have never opened that currency’s Locale tab and saved it. If you have set decimal places yourself, your setting stands.
So: after updating, your catalogue will read $104.32 where
it read USD104. Nothing stored has changed. If you
adjusted any price to compensate for the old behaviour, revisit it,
and if you take payments through a gateway, reconcile its records
across the update. Fresh installs now also show a currency’s
sign rather than its code — existing stores keep whatever they
have, and either way it is switchable per currency under
Currencies › Locale.
Also fixed
- Choosing a variant said “Variant does not exist” for most combinations. The lookup that turns the chosen options into a variant matched on the last option value for every one of them, so only some combinations ever resolved. This has been wrong since 1.1.0 and is the most important fix in the release for anyone selling variants.
- Variant edits were silently discarded. A variant with an empty compare-at price could not be saved at all — the database rejected the blank value, the row was never updated, and the admin still reported success. Every variant of the product carried the same blank, so no variant edit on that product could be saved.
-
Product and category pages had no breadcrumbs. A
product reached through a Shop menu item read
Home › Shopand stopped there. Since the breadcrumbs module also builds theBreadcrumbListstructured data that search engines show in product results, the trail was short there too. Product pages now add their category and their own name; a listing narrowed to one category or brand names itself. - The mini-cart drawer’s remove button did nothing on any page except the product and cart views — the quantity stepper was dead in the same places, and the badge stopped syncing after each drawer fetch.
- The products module ignored its ordering and Featured settings. Every strip ranked by popularity whatever you chose, so a “Featured products” strip showed the same products as “Best sellers”. The ordering list also gained Price and Units Sold.
- Empty filter sections printed a heading over an empty box — the Rating facet did this on every store without the review plugin installed. And Clear All Filters left the checkboxes ticked over an unfiltered grid.
- Option buttons wrapped onto rows with no space between them on a product with many values in one option.
-
The media size settings were never validated, so
typing
800pxraised a warning on every image and clearing a field took the page down. Thesrcseta product image publishes now describes each file by the width it was actually cut at, instead of the shipped defaults. - Order-page badges were unreadable — near-black text on dark blue, below the WCAG AA contrast minimum — and the order products table sat flush against its card edge.
-
The XML sitemap was served as HTML with no
X-Robots-Tag: the headers were queued and then thrown away before the response was sent. - The filters module now renders only on listing pages. A product page inheriting a listing’s menu item inherited its modules too, and a filter panel there was a set of links to a different page.
- And a fresh install now starts from a sensible store record — My Store, US/USD, matching the shipping table and location seeded beside it, rather than a Euro-denominated placeholder company with an Italian address.
All 22 translated languages were re-synced against English for this release: 161 new strings each, covering everything above.
Updating
Core 1.5.0 is a one-click update from System › Update. The schema change is small — two nullable columns on the brands table — plus the guarded currency correction described above.
Three things to do afterwards. Publish the new storefront modules you
want (Joomla installs modules unpublished and without a position, and
an update never rearranges your module layout). Check the prices on
your storefront, and reconcile your gateway records if you take
payments. And look at System › Dashboard › AI
discovery to decide what your robots.txt should
say — or switch the whole feature off under
Options › AI discovery if you would rather not
publish the file at all.
For the complete, itemised list of every change, see the Solidshop changelog.