mageos / module-blog

mageos/module-blog

Blog module for Mage-OS / Magento 2 — posts, categories, tags, authors, SEO, GraphQL.

magento2-module Compatibility: Not compatible Code Quality: Fail Tests: Fail Security: Pass OSL-3.0

MageOS Blog

A blog module for Mage-OS and Magento 2. Posts, categories, tags, authors, scheduled publishing, RSS, sitemap, 6 storefront widgets, SEO (meta tags, Open Graph, Twitter Cards, JSON-LD), and a full GraphQL API. Works with Luma and Hyvä themes.

Install

composer require mageos/module-blog
bin/magento module:enable MageOS_Blog
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:clean

For Hyvä storefronts, also install the companion template package:

composer require mageos/module-blog-hyva

Enable

The module ships disabled. Turn it on under Stores → Configuration → MageOS → Blog → General → Enabled (or set mageos_blog/general/enabled = 1).

Key admin settings

All settings live under Stores → Configuration → MageOS → Blog.

Path Purpose
mageos_blog/general/enabled Master kill switch. Router and cron both short-circuit when off.
mageos_blog/post/posts_per_page Listing pagination size.
mageos_blog/post/default_robots Fallback meta robots value for posts that don't override it.
mageos_blog/seo/og_default_type Default og:type. Usually article.
mageos_blog/seo/json_ld_enabled Emit Article JSON-LD on post detail pages.
mageos_blog/seo/twitter_site Twitter handle used for twitter:site.
mageos_blog/sidebar/* Per-widget toggles for search, recent posts, category list, tag cloud, archive.
mageos_blog/sitemap/{post,category,tag}/* Per-entity sitemap enable + changefreq + priority.
mageos_blog/rss/enabled, mageos_blog/rss/limit RSS feed at /blog/rss.

Compatibility

PHP 8.2 PHP 8.3
Magento 2.4.6 yes yes
Magento 2.4.7 yes yes
Hyvä 1.3+ yes yes
Luma yes yes

Requires magento/module-url-rewrite-graph-ql for the GraphQL URL resolver integration.

Storefront URLs

By default:

  • Post: /blog/{url-key}
  • Category: /blog/category/{url-key}
  • Tag: /blog/tag/{url-key}
  • Author: /blog/author/{slug}
  • RSS: /blog/rss
  • Search: /blog/search?q=...

URL shape is driven by mageos_blog/permalink/* config. URL rewrites populate on save via the repository plugins in Plugin/Repository/.

GraphQL

Queries: blogPost, blogPosts, blogCategory, blogCategories, blogTag, blogTags, blogAuthor, blogAuthors. Each list query accepts filter, sort, pageSize, currentPage and returns items + page_info + total_count.

Mutations: createBlogPost, updateBlogPost, deleteBlogPost (and the equivalent for category / tag / author). Every mutation requires an admin token and passes through Magento\Framework\AuthorizationInterface against the entity's ACL resource (MageOS_Blog::post, MageOS_Blog::category, MageOS_Blog::tag, MageOS_Blog::author).

urlResolver(url: "/blog/my-post") returns { type: BLOG_POST, id, relative_url }. Supported types: BLOG_POST, BLOG_CATEGORY, BLOG_TAG, BLOG_AUTHOR.

Full schema: etc/schema.graphqls.

Upgrade notes

v1.0.0 is a greenfield rewrite. There is no migration path from any v0.x fork, including the original Magefan-derived codebase that lived under this package name before the rewrite. To move off a v0 install, export content from the old admin, fresh-install v1, and re-import via the admin or GraphQL.

Development

composer install
vendor/bin/phpunit --testsuite unit
vendor/bin/phpstan analyse --memory-limit=1G
vendor/bin/phpcs --standard=phpcs.xml.dist
vendor/bin/php-cs-fixer fix --dry-run --diff
vendor/bin/infection --min-msi=75 --threads=4

Integration tests live under Test/Integration/ and run in CI against a live Magento install via graycoreio/github-actions-magento2.

Contributing

Issues and PRs welcome at https://github.com/mage-os/module-blog. Please follow Conventional Commits, include tests for new behavior, and keep PRs small and reviewable.

License

OSL-3.0. See LICENSE.

Attribution

Design inspired by Magefan Blog (OSL-3.0). v1 is an independent implementation with no shared code.

Changelog

All notable changes to this project are documented here.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

1.0.0 - 2026-04-20

First release of the greenfield rewrite. No migration path from pre-v1 forks.

Added

  • Content model. Four entities (blog_post, blog_category, blog_tag, blog_author) with DB-level foreign keys and cascading deletes. Store-view scoping via pivot tables. Fulltext indexes on post and category content for search.
  • Admin UI. UI-component grids and forms for posts, categories, tags, authors. Image upload (featured image, OG image, gallery) via a single MageOS\Blog\ImageUpload virtualType. Related-posts and related-products pickers on the post form.
  • Storefront. Custom router with URL-rewrite integration. Post detail, category detail, tag detail, author detail, blog index, search, pagination. Luma template set under view/frontend/templates/; Hyvä template set ships in the companion package mageos/module-blog-hyva.
  • Scheduled publishing. Cron\PublishScheduledPosts runs every minute, finds posts whose publish_date just passed, and re-saves them to invalidate FPC. Gated by mageos_blog/general/enabled.
  • SEO. meta title, meta description, meta keywords, meta robots, canonical link, Open Graph, Twitter Cards, and Article JSON-LD on post detail pages. Configurable defaults under mageos_blog/seo/*.
  • RSS. /blog/rss emits RSS 2.0 XML. Limit configurable via mageos_blog/rss/limit.
  • Sitemap. Three ItemProviders (post, category, tag) wired into Magento\Sitemap\Model\ItemProvider\Composite. Per-entity enable / frequency / priority under mageos_blog/sitemap/*.
  • Search. DB-fulltext-backed search against the MAGEOS_BLOG_POST_FULLTEXT index. Controller at /blog/search?q=.... OpenSearch / Magento_Search integration deferred to v1.1.
  • Widgets. 6 storefront widgets: recent posts, featured post, post list, post link, category link, tag link. Admin chooser blocks for picking a post / category / tag from grids.
  • GraphQL. Queries (blogPost, blogPosts, blogCategory, blogCategories, blogTag, blogTags, blogAuthor, blogAuthors). Mutations (create / update / delete for all four entities). URL resolver integration: urlResolver(url:"/blog/my-post") returns type: BLOG_POST. Mutations require admin token plus ACL.
  • Hyvä support. A Plugin\Magento\Framework\View\TemplateEngine\Php plugin injects a HyvaThemeDetection helper into every .phtml scope. Plugin\Magento\Framework\View\Element\TemplateRewrite remaps MageOS_Blog::X paths to MageOS_Blog::hyva/X on Hyvä themes.
  • i18n. Seed i18n/en_US.csv with 236 phrases.
  • Quality gates. PHPStan level 8, PHPCS (Magento2 ruleset), PHP-CS-Fixer, PHPUnit unit suite (57 tests), Infection mutation testing (baselines: MSI 54%, Covered MSI 70%).

Notes on design

Design inspired by Magefan Blog (OSL-3.0). v1 is an independent implementation with no shared code.

Deferred to v1.1

  • Comments (native, moderation, spam, email).
  • Content importers from Mageplaza, Magefan, Aheadworks, Mirasvit, WordPress. Will ship as a separate mageos/module-blog-migration package.
  • OpenSearch / Magento_Search indexer + mview + etc/search_request.xml.
  • PageBuilder content editing.
  • Hyvä-native .phtml set (detection plugin is in place; the companion package is empty until v1.1).
  • Configurable URL prefix, custom per-page CSS, preview-token model, Commerce-only AdminGWS plugin, MFTF tests, gravatar autofetch, per-post multi-language content variants.
  • Infection MSI ≥ 75% / Covered MSI ≥ 80%. v1.0 ships at 54% / 70% respectively; raising the floor depends on expanding unit-test coverage into ViewModel/Post/Detail (JSON-LD shape edge cases) and Model/HyvaThemeDetection (theme-chain walking).
Versions
Version Stability QA Status Compatibility Released
1.0.0 stable Fail Not compatible Details 2026-04-20 13:36:00

Requires 15

Package Constraint
php ^8.2
magento/framework ^103.0.7
magento/module-backend *
magento/module-catalog *
magento/module-cms *
magento/module-customer *
magento/module-graph-ql *
magento/module-media-storage *
magento/module-search *
magento/module-sitemap *
magento/module-store *
magento/module-ui *
magento/module-url-rewrite *
magento/module-url-rewrite-graph-ql *
magento/module-widget *

Requires-dev 6

Package Constraint
phpunit/phpunit ^10.5
phpstan/phpstan ^2.0
bitexpert/phpstan-magento ^0.42
friendsofphp/php-cs-fixer ^3.50
magento/magento-coding-standard ^40
infection/infection ^0.29

Compatibility

Each Magento release line is installed on its supported PHP versions, then the module is built (DI compilation + static-content deploy) and its unit and integration suites are run. The matrix shows the lines and PHP versions the module is confirmed to install and run on. Code-quality results further down (phpstan, phpcs, …) are reported separately and never affect compatibility.

Compatibility matrix (Magento × PHP)
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 Fail di error Fail di error
2.4.8 Fail di error Fail di error
2.4.9 Fail unknown not tested

Code Quality

Advisory checks against the module's source. Static analysis runs once across the whole module; PHPStan re-runs per Magento + PHP version because resolvable symbols differ between releases. These NEVER affect the Compatibility badge — a phpcs finding can't make a module incompatible.

Static analysis

Coding standards (phpcs), mess detection (phpmd), copy-pasted code (cpd), PHP cross-version compatibility, composer.json validity. Each runs once for the whole module.

Static analysis results
Tool Status Findings Summary
PHPCS Fail 206 21 errors, 185 warnings (ruleset: Magento2) — 1 auto-fixable with phpcbf
PHPMD Warning 145 145 rule violations (UnusedFormalParameter:102, MissingImport:16, CyclomaticComplexity:11, NPathComplexity:11, ExcessiveClassComplexity:2)
Cpd Warning 9 9 duplicated chunks spanning 311 total lines (min-lines=5, min-tokens=70)
Composer validate Info 13 valid; 13 advisory notes (composer validate --strict)

PHPStan

Type-checks the module's PHP against a real Magento install at the configured gate level. Re-runs per Magento and PHP version because resolvable symbols differ between releases. Cell → details modal.

PHPStan results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 2 2
2.4.8 2 2
2.4.9 2 2

Tests

Unit and integration suites, run for each applicable Magento and PHP version. A test failure speaks to the module's behaviour, not its compatibility with a Magento line, so it is reported here separately and never reddens the compatibility matrix.

Unit tests

Unit tests results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 Pass Pass
2.4.8 Pass Pass
2.4.9 Pass not tested

Integration tests

Integration tests results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 Error Error
2.4.8 Error Error
2.4.9 Error not tested

Security

Security checks run directly against the module: an audit of its declared dependencies for known vulnerabilities (composer audit) and a scan of its source for malware and web-shell signatures. Each runs once. A malware detection fails the version outright.

Security results
Tool Status Findings Summary
Composer audit Pass 0
Malware scan Pass 0
License
OSL-3.0
Make it pay

Turn an existing module into recurring revenue.

If you already maintain a Magento 2 module on GitHub or GitLab, listing it on Packagento takes about five minutes. We mirror your tags, handle distribution signing, and route paid licenses through Stripe Connect, so you can keep shipping the way you already do.