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
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- 2.1.4
- 2.1.3
- 2.1.2
- 2.1.1
- 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-fix/w1-docs-truth
- dev-docs/readme-more-from-links
- dev-docs/seasons-pro-released
- dev-fix/funnel-url-repoint
- 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-09-04 00:33:57 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, 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 — 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 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
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 (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_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 (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
| 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 (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:
- 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, behavioural segmentation, product-pull blocks
- Legal Pages — Lite: localized legal-page templates · Pro: compliance toolkit (cookie consent, accessibility statement, imprint validator, audit trail)
- Analytics — Lite: multi-backend (Matomo / Plausible), GDPR-first · Pro: e-commerce conversion tracking
- Maintenance — Lite: branded, SEO-correct (HTTP 503) maintenance page · Pro: scheduled maintenance windows
- Multi-Brand — Lite: serve multiple brands from one Shopware, by hostname · Pro: per-brand transactional email overrides
- Product Encyclopedia — Lite: structured educational content pages · Pro: per-profile related-product cross-links
- Seasons — Lite: 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