Search by

tenbruggencate / seasons-lite

guy@tenbruggencatedevelopment.nl

Shopware 6 theme scheduling: save named theme-config variants and schedule when each goes live (Christmas, Black Friday, Spring).

Package info

bitbucket.org/Bruggencate/sw-plugin-seasons-lite

Homepage

Issues

Documentation

Type:shopware-platform-plugin

pkg:composer/tenbruggencate/seasons-lite

Statistics

Installs: 122

Dependents: 0

Suggesters: 0


README

Ten Bruggencate Development

Seasons Lite

Packagist Version License

Schedule seasonal theme-config changes in Shopware 6.7. The free Lite tier of the TenBruggencate Seasons family.

Save named variants of your theme's configuration (Spring, Summer, Autumn, Winter — or Black Friday, Valentine's, Anniversary — whatever fits your shop). Pick one and schedule when it should become active. At the scheduled moment a Shopware scheduled task applies the variant's values to the theme config and triggers a recompile. The next variant's start time is the current one's end — rolling handover, no end-date bookkeeping.

Works with any Shopware 6.7 theme that exposes config.fields in its theme.json (that includes Shopware's own default storefront theme).

License: MIT · Shopware: 6.7.x · PHP: 8.1 / 8.2 · Composer package: tenbruggencate/seasons-lite

🇬🇧 English · 🇳🇱 Nederlands · 🇩🇪 Deutsch

Lite vs Pro

This repo is the free Lite tier of the Seasons family — scheduled theme-variant switching: palette + typography swap on a date. Production-ready, MIT-licensed, no feature gating, no license server.

A paid Pro tiertenbruggencate/seasons-pro, shipped and currently at 1.2.x — installs side by side with Lite; your existing Lite variants and schedules stay untouched. It is not published on Packagist: today it is delivered directly on request, and a Shopware Store listing is in preparation. What Pro adds:

  • A sitewide marketing banner per variant that follows Lite's schedule: it shows when the variant activates and is gone when the variant rolls off.
  • Banner text up to 500 characters (emoji welcome), an optional call to action with link and label, and optional background and text colour.
  • A toggle to pre-stage a banner; when a variant is deleted, its banner is removed automatically.
  • An accessible storefront include with its own CSS classes, plus the Twig helper tb_seasons_pro_active_banner().
  • Managed under Settings → Seasons Pro: banner list and form with a variant picker (search-as-you-type); EN / NL / DE.
  • An Export all data button: JSON with banners and configuration, also reachable over the API; keep or remove the data on uninstall.

Seasons Pro — what it does and what it costs

Screenshots

Seasons is an admin-only plugin — there's nothing for storefront visitors to see directly. The visible surface is the Shopware admin module under Content → Seasons with three views:

Overview tab — Getting started banner explaining the workflow, 'Currently active' and 'Next scheduled' sections per sales channel.

Overview — what's live now + what's queued next

Variants tab — list of named theme-config variants with Edit / Clone / Delete buttons; baseline + Lente / Zomer / Herfst / Winter placeholders flagged 'Needs customisation'.

Variants — list / edit / clone / delete

Schedule tab — Upcoming and Past timelines with a 'Schedule a variant' button.

Schedule — upcoming + past activations

Deeper walk-through with operator notes per view: docs/admin/ADMIN.md.

Install

Seasons Lite ships on public Packagist as tenbruggencate/seasons-lite and is picked up by the Shopware Plugin Manager the same way.

# Composer (development / build-pipeline-managed shops)
composer require tenbruggencate/seasons-lite:^2.0

bin/console plugin:refresh
bin/console plugin:install --activate TenBruggencateSeasons
bin/console assets:install
bin/console cache:clear

Upgrading from v1.x? The composer package was renamed tenbruggencate/seasonstenbruggencate/seasons-lite in v2.0.0. Run composer remove tenbruggencate/seasons then the composer require above; the plugin class stays TenBruggencateSeasons (grandfathered) so the Shopware plugin table row and your existing variants + schedules are untouched. No data migration, no behaviour change.

Verify the scheduled-task runner is active

Variant activations fire on the Symfony Scheduled Task tenbruggencate_seasons.apply_due_variants (60-second tick). For schedules to actually fire, one of these must be running:

# Option A — a running messenger consumer (recommended for production)
bin/console messenger:consume --limit=1 tenbruggencate_seasons.apply_due_variants

# Option B — a cron entry invoking the fallback runner every minute
bin/console scheduled-task:run

Without a consumer, scheduled variants stay queued and never activate. There is no warning banner for this in the admin — verify manually on first install.

First install — seeding is deferred to the first scheduler tick

plugin:install --activate creates the tb_seasons_variant and tb_seasons_schedule tables but leaves them empty on purpose. The Baseline + four placeholder variants (Lente / Zomer / Herfst / Winter) materialise on the first scheduler tick — typically within 60 seconds if your messenger consumer or cron is running.

If the Variants tab looks empty right after install on a shop with no scheduler running, fire one manual tick:

bin/console scheduled-task:run-single tenbruggencate_seasons.apply_due_variants

Seeding is idempotent — re-running the task does nothing once the rows exist. The same mechanism handles reinstall: the scheduler repopulates after an uninstall/reinstall cycle.

Locales

Admin strings ship in en-GB, nl-NL, de-DE. Admin snippet files live under src/Resources/app/administration/src/module/tenbruggencate-seasons/snippet/. There are no storefront snippet files: the only storefront markup is the variant-hero.html.twig include, and its text (image alt and caption) comes from the media entity, so there is nothing to translate. Additional locales are contributable via PR.

How it works

Admin UI at /admin#/tenbruggencate/seasons with three views:

  • Overview — currently-active variant per sales channel, next pending schedule with countdown, "Activate previous variant" rollback, recent activity log.
  • Variants — list / edit / clone / delete. Install seeds one Baseline variant plus four Dutch placeholder palettes (Lente / Zomer / Herfst / Winter) with deliberately-ugly colours. Placeholders are flagged requires_customization=true and cannot be scheduled until you edit them — forcing an intentional onboarding, no accidental go-live with our colours.
  • Schedule — timeline of upcoming + past schedules with status badges (pending / applied / failed). "Schedule a variant" form picks variant + sales channel + datetime.

Two owned tables: tb_seasons_variant (name / theme / config_json / flags) and tb_seasons_schedule (variant / SC / start_at / applied_at / failed_attempts).

Scheduler reliability

One-minute Symfony Scheduled Task (tenbruggencate_seasons.apply_due_variants). On each tick:

  1. Find schedules where applied_at IS NULL AND start_at <= now().
  2. For each, apply the variant: ThemeService::updateThemeThemeService::compileThemeById.
  3. On success stamp applied_at and reset failed_attempts.
  4. On failure: increment failed_attempts, log at WARNING, back off (1m → 5m → 30m → 1h → 6h, give up after 10 attempts).

Missed windows (e.g., the server was down at the scheduled start) catch up on the next tick — the most-recently-overdue variant for each sales channel wins so the shop doesn't flicker through intermediate variants.

Per-variant hero media (since v1.1.0)

Each variant can optionally carry a hero image from the Shopware media library. Upload it in the variant editor; when the variant is active, theme authors can render it via:

{# Option A — just drop the ready-made include wherever you want a seasonal banner: #}
{% include '@TenBruggencateSeasons/storefront/component/variant-hero.html.twig' %}

{# Option B — use the Twig helper and render it your own way: #}
{% set hero = tb_seasons_active_hero() %}
{% if hero %}
    <img src="{{ hero.url }}" alt="{{ hero.alt|default('') }}" class="my-custom-hero" />
{% endif %}

Zero overhead when no variant is active (the helper short-circuits before any DB work). When a variant is active, the helper makes one request-cached SystemConfigService read and one memoised media lookup per request — well under 2ms even on a warm admin box.

Variants that want to ship a hero only (no palette change) can skip the theme-config keys entirely. The Baseline variant never ships a hero by design — it's the rollback target, so it restores whatever hero was in place before the plugin took over.

Production-readiness checklist

A deliberately short list of things to verify before enabling Seasons on a production shop. Not legal cover — the MIT license already disclaims warranty — but practical guidance an experienced operator would want anyway.

  • [ ] Verify the scheduler runs in production. Without a messenger consumer or cron entry actively running tenbruggencate_seasons.apply_due_variants, scheduled variants never activate and the admin gives no warning. Test with a 2-minutes-from-now schedule on staging before trusting it on prod.
  • [ ] Edit the seeded placeholder variants before scheduling them. Lente / Zomer / Herfst / Winter ship with deliberately-ugly colours flagged requires_customization=true. The plugin refuses to schedule them until you edit them — this is by design, but the friction means you should plan an explicit "design the variants" task before the first season.
  • [ ] Plan rollback via the Overview tab, not the database. "Activate previous variant" is the supported rollback path; manual tb_seasons_schedule row edits skip the recompile and leave the storefront in an inconsistent state. The Overview tab is also the only place that records the rollback in the activity log.
  • [ ] Document your seasonal calendar somewhere visible to the team. A scheduled variant activating overnight without a Slack/email mention is the classic "why does the shop look different today?" moment. The plugin doesn't ship notifications (roadmap); document the calendar manually until then.
  • [ ] Don't try to ship CMS-page or product-badge scheduling through this plugin. Out of scope by design (see "Out of scope" below). Mixing those in via theme-config hacks works once and breaks the next time Shopware tweaks the theme-compile pipeline.

Roadmap (not shipped)

Tracked under TEN-168 in our Linear. Summary:

  • Pre-compiled variants + atomic swaps — compile at variant-save time, store compiled assets alongside the variant, apply = pointer flip. Swaps become effectively instant instead of 10-30s of compile downtime.
  • Preview mode — "preview this variant" generates a shareable short-lived token URL; only that request sees the variant, rest of the world sees the current one.
  • Notifications, diff view, approval workflow — polish tier.

Out of scope

This plugin only schedules theme-config values. CMS page scheduling, product-badge scheduling, snippet scheduling, and full theme-plugin swaps are separate problems and live (or will live) in dedicated plugins.

Compatibility

ShopwarePHPStatus
6.7.x — tested against 6.7.8, 6.7.98.1, 8.2Stable
6.6.xNot supported
6.5.x and earlierNot supported
EngineVersionNotes
MySQL8.0+Primary target — JSON functions used in migrations
MariaDB10.11+End-to-end tested

What we test before each release

  • Full PHPUnit unit suite against PHP 8.1 + 8.2 (51 tests, source-inspection — no kernel needed)
  • PHPStan level 8 + PHP-CS-Fixer (@PSR12 + @Symfony)
  • Composer validate
  • Live-DB smoke tests (plugin install → activate → variant scheduled → applied → uninstall cycle) against Shopware 6.7.8

Related plugins

Sibling plugins from the same publisher:

Support

License

MIT © Ten Bruggencate Development

More from Ten Bruggencate Development

Focused, privacy-first Shopware 6 plugins — free to start, upgrade when you grow:

  • NewsletterLite: GDPR-safe signup & subscriber-list management · Pro: campaigns, behavioural segmentation, product-pull blocks
  • Legal PagesLite: localized legal-page templates · Pro: compliance toolkit (cookie consent, accessibility statement, imprint validator, audit trail)
  • AnalyticsLite: multi-backend (Matomo / Plausible), GDPR-first · Pro: e-commerce conversion tracking
  • MaintenanceLite: branded, SEO-correct (HTTP 503) maintenance page · Pro: scheduled maintenance windows
  • Multi-BrandLite: serve multiple brands from one Shopware, by hostname · Pro: per-brand transactional email overrides
  • Product EncyclopediaLite: structured educational content pages · Pro: per-profile related-product cross-links
  • SeasonsLite: scheduled theme-config variants · Pro: per-variant marketing banners

Need more than a plugin? Ten Bruggencate Development builds and customizes Shopware 6 stores. → Let's talk