tenbruggencate / seasons-lite
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
Type:shopware-platform-plugin
pkg:composer/tenbruggencate/seasons-lite
Requires
- php: >=8.1
- shopware/core: ~6.7
- shopware/storefront: ~6.7
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.94
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.0
- dev-main
- 2.1.0
- 2.0.0
- 1.4.0
- 1.3.1
- 1.3.0
- 1.2.1
- 1.1.4
- 1.1.3
- 1.1.2
- dev-feat/suite-catalog-lite-pro-pairings
- dev-feat/rename-to-lite-package
- dev-feat/tb-suite-card
- dev-docs/lite-pro-strategy-resync-2
- dev-docs/lite-pro-strategy-resync
- dev-docs/cross-promotion
- dev-docs/readme-branding
- dev-chore/refresh-screenshots-v1.3.1
- dev-chore/audit-fixes-v1.3.0
- dev-chore/docs-screenshots-v1.2.1
- dev-chore/ux-polish-v1.2.0
- dev-chore/packagist-description-normalise
- dev-chore/admin-screenshots-and-readme-polish
- dev-chore/initial-extraction
This package is auto-updated.
Last update: 2026-05-24 01:06:04 UTC
README
Seasons Lite
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 — what's live now + what's queued next |
Variants — list / edit / clone / delete |
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/seasons→tenbruggencate/seasons-litein v2.0.0. Runcomposer remove tenbruggencate/seasonsthen thecomposer requireabove; the plugin class staysTenBruggencateSeasons(grandfathered) so the Shopwareplugintable 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
Baselinevariant plus four Dutch placeholder palettes (Lente / Zomer / Herfst / Winter) with deliberately-ugly colours. Placeholders are flaggedrequires_customization=trueand 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:
- Find schedules where
applied_at IS NULL AND start_at <= now(). - For each, apply the variant:
ThemeService::updateTheme→ThemeService::compileThemeById. - On success stamp
applied_atand resetfailed_attempts. - 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_schedulerow 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
| Shopware | PHP | Status |
|---|---|---|
| 6.7.x — tested against 6.7.8, 6.7.9 | 8.1, 8.2 | Stable |
| 6.6.x | — | Not supported |
| 6.5.x and earlier | — | Not supported |
| Engine | Version | Notes |
|---|---|---|
| MySQL | 8.0+ | Primary target — JSON functions used in migrations |
| MariaDB | 10.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:
- TenBruggencateMultiBrand — pairs naturally with Seasons: a Christmas variant per brand, scheduled separately
- TenBruggencateAnalytics — variant-activation events can be tracked as Matomo / Plausible custom events
- TenBruggencateNewsletterLite — GDPR-safe newsletter signup with double opt-in
- TenBruggencateMaintenance — branded maintenance page with HTTP 503 + Retry-After
- TenBruggencateLegalPages — drop-in legal templates with merge fields
Support
- Email: guy@tenbruggencatedevelopment.nl
- Docs & news: tenbruggencatedevelopment.nl
- Source / issues: Bitbucket repo
- Security vulnerabilities: see
SECURITY.md— email first, no public issues, 72-hour acknowledgement SLA
License
MIT © Ten Bruggencate Development
More from Ten Bruggencate Development
Focused, privacy-first Shopware 6 plugins — free to start, upgrade when you grow:
- Newsletter — Lite: GDPR-safe signup & subscriber-list management · Pro: campaigns, lifecycle automations, native-data segmentation
- Legal Pages — Lite: 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
- Seasons — Lite: scheduled theme-config variants · Pro: per-variant hero media, automated campaigns, A/B variant testing, segment-aware variants, preview mode, variant analytics