tenbruggencate/seasons-lite

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

Maintainers

Package info

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

Homepage

Issues

Documentation

Type:shopware-platform-plugin

pkg:composer/tenbruggencate/seasons-lite

Statistics

Installs: 0

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 tier (tenbruggencate/seasons-pro, Shopware Store) is in development and will layer on top of Lite — install Pro and the advanced features light up in place, your existing Lite variants and schedules are untouched. Planned Pro capabilities:

  • Per-variant hero media — upload a seasonal banner image per variant from the Shopware media library; theme authors render it via a Twig include or helper (TEN-169 — already designed).
  • Automated campaigns tied to seasons — let the Pro tier orchestrate matching CMS slot copy, email blasts and discount-rule windows around each scheduled variant, so the visual swap is paired with the marketing motion.
  • A/B testing of variants — split traffic between two variants on the same date window and measure which one converts better, with first-class analytics integration.
  • Segment-aware variants — serve a different variant to first-time vs returning visitors, by country, by referrer, or by customer group, off the same schedule slot.
  • Preview mode — generate a shareable short-lived token URL that renders the variant for that request only, so a designer or marketer can review it before the scheduled go-live.
  • Variant analytics — per-variant impression / conversion dashboard so you can see which seasonal refreshes actually moved the needle, and feed that back into next year's calendar.

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 + storefront strings ship in en-GB, nl-NL, de-DE. Admin snippet files live under src/Resources/app/administration/src/module/tenbruggencate-seasons/snippet/; storefront snippets under src/Resources/snippet/. 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 (V2.3)

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 (V2 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.

V2 roadmap (not shipped yet)

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.
  • Per-variant asset overrides — upload a custom hero image / decorative SVG per variant; storefront serves the variant's overrides when active / previewed.
  • 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 (38 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, lifecycle automations, native-data segmentation
  • Legal PagesLite: localized legal-page templates · Pro: the compliance toolkit (maintained templates, cookie policy, accessibility statement)
  • Analytics — multi-backend (Matomo / Plausible), GDPR-first, cookieless-capable
  • Maintenance — a branded, SEO-correct maintenance page
  • Multi-Brand — serve multiple brands from one Shopware, by hostname
  • Product Encyclopedia — structured educational content pages linked to products
  • SeasonsLite: scheduled theme-config variants · Pro: per-variant hero media, automated campaigns, A/B variant testing, segment-aware variants, preview mode, variant analytics