Zero Blog
Module: Zero_Blog. A blog for the Zero storefront: posts written in the
Zero CMS editor (with AI), categories, tags, authors, products in posts and
posts on product pages, comments with moderation, an RSS feed, and the SEO
search engines look for. No JavaScript on its pages; everything is cached
by the full page cache or Varnish and refreshed by cache tags when you save.
For editors
Content > Blog
| Section | |
|---|---|
| Posts | Title, URL key (made from the title when empty), publish date (a future one schedules the post), author, store views, excerpt, featured image with alt text, categories, tags (typed, comma separated: new ones are created), products (SKUs), SEO fields, comments on or off |
| Categories | Title, URL key, description, position, SEO fields |
| Tags | The same, without position |
| Authors | Name, job title, bio, photo, website, LinkedIn and X links |
| Comments | Approve, reject or delete. A comment shows under its post once approved |
| Settings | Stores > Configuration > Zero > Blog |
The text of a post is written in the Zero CMS editor: Save and Edit Content on the post form, or Edit Content in the grid. Posts use the same components as pages, plus:
- Article: long text in Markdown.
##and###headings become the table of contents beside the post (three or more##headings). - Image, Quote, and HTML (for imported posts).
The editor's AI drafts a post from a description, rewrites a text field, and translates a post. A post with no content yet shows its excerpt.
Products: list SKUs on the post. They show under the post as product cards, and the post shows under From the blog on their product pages (up to three posts per product). Products can also go inside the text with the Product slider component.
Languages: a post belongs to store views. A post in another language is its own post, assigned to that store view; it can use the same URL key.
URLs
/blog |
The newest posts (?p=2, ?p=3… for older pages) |
/blog/<url-key> |
A post |
/blog/category/<url-key> |
A category |
/blog/tag/<url-key> |
A tag |
/blog/author/<url-key> |
An author with their posts |
/blog/rss.xml |
RSS 2.0, the 20 newest posts |
blog is Blog Path in the settings. When a published post's URL key
changes, its old URL redirects (301) to the new one. Redirects are URL
rewrites of type zero-blog (Marketing > URL Rewrites).
Search engines
Every blog page has:
- a title, meta description and canonical URL (a post can point its canonical at the place it was first published, and set meta robots);
- Open Graph and Twitter card tags (
og:typearticle for posts, witharticle:published_time,article:author,article:section,article:tag), following the store's Sharing in Social Media setting (on, off, X account, default image); - structured data (JSON-LD):
BlogPostingwith author, publisher, dates, image, word count and reading time;Blogon the index;CollectionPagefor categories and tags;ProfilePagewithPerson(andsameAsprofile links) for authors;BreadcrumbListeverywhere; - breadcrumbs: Home > Blog > Category > Post;
- semantic HTML: one
h1,article,time datetime,rel="author",rel="tag",rel="prev"/"next"on page links; - the featured image as WebP in several sizes, loaded eagerly with
fetchpriority="high"on a post (it is the largest paint), lazily in lists.
Posts, categories and authors with posts are added to Magento's XML sitemap (Marketing > SEO & Search > Site Map) with their dates and the featured image. Priority and frequency: settings > XML Sitemap.
AMP isn't supported on purpose: Google stopped favouring AMP pages in 2021, and Zero pages are already fast.
Comments
Readers leave a name, email and comment. Every comment waits for approval; the email is never shown. Spam protection without a captcha: a hidden field that bots fill (their comments are dropped, they get the normal answer), five comments per visitor in ten minutes, no more than three links. Turn comments off for the store (settings) or for one post.
Importing
bin/magento zero:blog:import wordpress --file=export.xml
bin/magento zero:blog:import magefan
bin/magento zero:blog:import amasty
| Source | What is read |
|---|---|
| WordPress | The export file (Tools > Export > Posts). Published, scheduled and draft posts, authors, categories, tags, featured images, Yoast or Rank Math SEO fields. WordPress's line breaks become paragraphs; shortcodes are dropped (captions keep their image and text) |
| Magefan Blog | Its tables in this database (still there after the extension is disabled): posts, categories, tags, store views, featured images. Authors from its author table or the admin users who wrote posts |
| Amasty Blog | Its tables in this database: posts (status published or scheduled), categories, tags, authors, store views, thumbnails |
A post's text becomes one HTML component (cleaned: no scripts, styles or
embeds). Magento directives such as {{media url="…"}} become real URLs.
Featured images are copied into pub/media/zero_blog/import (downloaded
for WordPress). Each post's old address redirects (301) to the new one:
WordPress uses the post's real link, Magefan blog/post/{key}, Amasty
blog/{key}.html; change it with --old-pattern=news/{key}.
Options: --dry-run (show what would happen), --no-images,
--no-redirects, -v (one line per post). Posts whose URL key already
exists are skipped, so it can run again. Clean the page cache afterwards.
For developers
| Table | |
|---|---|
zero_blog_post |
Posts (published_at in UTC, reading_time counted when the text is saved) |
zero_blog_post_store, _category, _tag, _product |
A post's links |
zero_blog_category, zero_blog_tag, zero_blog_author |
|
zero_blog_comment |
Comments (status: 0 pending, 1 approved, 2 rejected) |
A post's text is Zero CMS content of type zero_blog_post
(Model\Cms\PostTarget makes it editable). Controller\Router maps the
URLs above; Model\Page\Meta sets each page's head and breadcrumbs,
Block\Head adds Open Graph and JSON-LD and carries the page's cache tags.
Cache tags: every blog page has zero_blog; a post zero_blog_post_<id>;
the "From the blog" block zero_blog_product_<product id>, which a post
carries for every product it links to (or linked to). Saving a post
refreshes its page, the lists, and only those product pages. A new pending
comment refreshes nothing; approving one refreshes its post.
Templates are in the module (view/frontend/templates), styled with the
theme's Tailwind classes; override them in a child theme as usual.
Tests
dev/tests/zero-e2e/tests/blog.spec.ts (storefront: lists, a post's head
tags and structured data, table of contents, product links, RSS, comments)
and blog-admin.spec.ts (admin: a post written and published, its content
edited, a comment approved). Unit tests in Test/Unit.
Disabling or removing
Its data lives in its own tables (zero_blog_author, zero_blog_post, zero_blog_post_store, zero_blog_category, zero_blog_post_category, zero_blog_tag, …). With the module's code still in
place, bin/magento module:disable Zero_Blog followed by setup:upgrade
drops those tables (Magento's declarative schema), and enabling the module
again brings them back empty. To keep the data, switch the feature off in
Stores > Configuration where it has a setting, or back up first:
bin/magento setup:upgrade --safe-mode=1 dumps the data before anything is
dropped (--data-restore=1 puts it back). Deleting the module's code instead
leaves the tables in place.
