The release of Shopware 6.7 marks a pivotal evolution in the platform's architecture, tightening integration with Composer and enhancing the developer ecosystem. For plugin developers, packaging and distribution have become more standardized yet more critical than ever. This guide details how to package your plugin for modern Shopware installations, ensuring compatibility, security, and seamless distribution across the App Store or private networks.

The Modern Plugin Structure (Shopware 6.7)

In Shopware 6.7, the composer.json is the definitive source of truth. While legacy structures are supported via backward-compatibility layers, the ecosystem expects a Composer-native workflow. Your plugin must adhere to PSR-4 autoloading and include all necessary metadata in the manifest.

A standard compliant directory structure looks like this:

your-plugin/
├── src/                 # PHP source code (PSR-4)
│   └── YourPlugin/      # Namespace matching vendor name
├── config/              # Service definitions and routes
│   ├── services.xml     # Dependency injection configuration
│   └── routes.xml       # Admin API and storefront routes
├── templates/           # Overridden templates (if applicable)
├── public/              # Published assets (JS, CSS, images)
├── migration/           # Database migrations
├── CHANGELOG.md         # Version history
└── composer.json        # The package manifest

Key Changes in 6.7:

  • Configuration Flexibility: You can now mix XML and YAML for service configurations, though XML remains the standard for compatibility.
  • Asset Handling: Assets must be registered correctly to survive production builds. Ensure your plugin class implements Shopware\Core\Framework\Plugin and overrides boot() to handle publishing if necessary.
  • Strict Dependency Injection: The Service Container in 6.7 enforces stricter type checking. Your service definitions must align with the current core interfaces.

Crafting the Perfect composer.json

The composer.json file drives validation, installation, and store visibility. In 6.7, certain fields are mandatory for distribution success.

{
    "name": "vendor-name/your-plugin",
    "description": "Enhances checkout flow with real-time validation for Shopware 6.7+",
    "type": "shopware-platform-plugin",
    "version": "1.0.0",
    "license": "MIT",
    "authors": [
        {
            "name": "Your Name",
            "email": "[email protected]"
        }
    ],
    "autoload": {
        "psr-4": {
            "VendorName\\YourPlugin\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "VendorName\\YourPlugin\\Tests\\": "tests/"
        }
    },
    "require": {
        "php": "^8.1",
        "shopware/core": "^6.7.0"
    },
    "require-dev": {
        "phpunit/phpunit": "^9.5",
        "shopware/recommended-plugin-template": "@dev"
    },
    "extra": {
        "shopware-plugin-class": "VendorName\\YourPlugin\\YourPlugin",
        "label": {
            "de-DE": "Dein Plugin",
            "en-GB": "Your Plugin",
            "fr-FR": "Votre Extension"
        },
        "description": {
            "de-DE": "Beschreibung auf Deutsch",
            "en-GB": "Description in English"
        },
        "vendor": "vendor-name",
        "copyright": "2024"
    }
}

Critical Fields Explained

  • type: Must remain shopware-platform-plugin. Changing this breaks installation hooks.
  • require.shopware/core: In 6.7, use constraints like ^6.7.0 to allow minor updates while ensuring core compatibility. Avoid broad ranges that might break on major API shifts.
  • extra.vendor: This field is mandatory for App Store submissions. It determines the attribution and category metadata in the marketplace.
  • label/description: JSON-based labels are preferred in 6.7. They render immediately in the Administration without parsing XML, improving performance during package listing.

Validation and Preparation

Before distribution, rigorous validation is essential. Shopware 6.7 introduces stricter linters that catch common packaging errors.

1. Composer Validation

Run strict validation to ensure your manifest is parseable by the installation engine:

composer validate --strict

2. Using the Shopware App Store SDK

For distribution via the official marketplace, the Shopware Plugin SDK is the recommended tooling chain. It automates checks for coding standards, security vulnerabilities, and metadata completeness.

# Install the SDK CLI tools globally or within your project
composer require shopware/app-store-sdk --dev

# Run the linting and validation suite
vendor/bin/shopware-plugin-lint .

The SDK will flag issues such as missing vendor keys, insecure file permissions, or improper asset paths. Addressing these locally prevents rejection during the App Store review process.

Distribution Strategies

Shopware 6.7 supports multiple distribution channels. Choose the method that aligns with your audience.

1. Shopware App Store

For public plugins, you must package your plugin using the SDK guidelines.

  • Packaging: Use the SDK to generate a signed archive. This embeds cryptographic signatures ensuring the package hasn't been tampered with.
  • Submission: Upload via the Partner Console. The store uses the composer.json metadata to index your plugin by compatibility, features, and category.
  • Compatibility Matrix: Ensure your shopware/core constraint explicitly allows 6.7 versions. In 6.7, the Store filters plugins based on strict major/minor version matching logic.

2. Composer Archive for Direct Upload

For client deployments or community sharing without the App Store, use Composer to generate a production-ready ZIP. This method guarantees that all dependencies and the manifest are bundled correctly.

composer archive --format=zip --file=your-plugin-1.0.0

The resulting ZIP contains the manifest.json (derived from composer.json) and can be uploaded directly via Administration > Plugins. The 6.7 installer validates this format natively, skipping manual extraction steps.

3. Private Composer Repository

For enterprise or partner networks, distributing via a private repository is the most robust approach in 6.7. This enables automatic updates and dependency resolution across multiple installations.

Steps:

  1. Host your plugin on a secure registry (e.g., GitLab Package Registry, Satis, or Packagist Pro).
  2. Ensure the package publishes to the repository via CI/CD pipeline on version tags.
  3. Update the client's shopware/production project:
{
    "repositories": [
        {
            "type": "composer",
            "url": "https://repo.your-domain.com"
        }
    ],
    "require": {
        "vendor-name/your-plugin": "^1.0"
    }
}

Clients can now install or update the plugin using bin/console plugin:refresh and bin/console plugin:install --activate vendor-name/your-plugin.

Versioning, Localization, and Pitfalls

Semantic Versioning and Compatibility

Adopt strict SemVer. In 6.7, breaking changes to core interfaces can render older plugins incompatible. Always include a CHANGELOG.md detailing API changes. When submitting to the App Store, provide version-specific compatibility notes if your plugin relies on new 6.7 features like updated Storefront API endpoints or Admin DSL changes.

Localization Best Practices

Shopware 6.7 supports dynamic language switching in plugin labels. Ensure your composer.json includes all necessary locales. If you have a large number of translations, consider shipping separate localization bundles, though the JSON approach is generally sufficient for most plugins.

Common Pitfalls to Avoid

  • Missing Vendor Key: The App Store will reject packages without the extra.vendor field.
  • Loose Core Constraints: Using >=6.6.0 may cause issues as 6.7 introduces deprecation warnings and removals. Target ^6.7.0 for new plugins.
  • Asset Publishing Failures: In production environments, web servers may not execute shell scripts automatically. Ensure your plugin class handles asset publishing gracefully or document the manual steps required (bin/console theme:compile).
  • Static Class References: Verify that all static calls in your migration files and service definitions use fully qualified class names to avoid autoloading conflicts in 6.7's optimized bootstrap process.

Conclusion

Packaging and distributing a Shopware 6 plugin requires adherence to modern Composer standards and careful attention to metadata. By leveraging the composer.json as your manifest, utilizing the official App Store SDK for validation, and selecting the appropriate distribution channel, you ensure your plugin integrates seamlessly into the Shopware 6.7 ecosystem. Whether targeting the public marketplace or private enterprise deployments, these practices safeguard your plugin's longevity, security, and performance in the evolving Shopware landscape. Happy coding!