What had to be custom, and why.
A wellness-retreat operator's catalogue doesn't fit e-commerce defaults. A retreat isn't a product — it's a date-bound bundle that combines accommodation, meals, and instruction into a single purchasable unit. The lead instructor isn't a product author; they are the reason a guest books. The brand's Sanskrit vocabulary and philosophy modules aren't a blog; they're a content layer that sits alongside the storefront and gives the purchasing decision its context.
We built the platform on PrestaShop 1.7.4 in late 2018, with four domain-specific modules and a heavily customised default theme. The retreat-bundles module modelled multi-date, multi-component offerings with date selection and component configuration — nothing in the PrestaShop ecosystem came close. The Sanskrit-learning module had its own database tables, frontend routes, and admin panel: a vocabulary and philosophy surface the operator could edit independently of the catalogue. A reseller module tracked B2B partner agencies with contact, country, and currency records.
The checkout flow was overridden — 67 class and controller overrides at peak — because retreat purchases have different validation rules than physical-goods checkouts. You can't buy two seats at a retreat without selecting dates. You can't leave a component field empty and proceed to payment.
Small things that kept the platform alive.
Years two through six were not dramatic. Payment-provider swaps. GDPR adjustments. Shipping-carrier additions. PHP runtime upgrades worked in across the engagement. Occasional new copy, new retreat formats, new B2B partners onboarded through the reseller module. The kind of maintenance that doesn't make a project page but is the real content of a seven-year engagement.
Most custom platforms don't survive this phase. The team that built them has moved on. The modules are undocumented. The class overrides are mystery code. Each dependency bump is a roll of the dice.
The platform survived because the same people were on it. When a payment-provider swap required changes to the checkout override, the engineer who wrote the override made the change. When a PHP runtime upgrade broke two module constructors, we knew which constructors to check. Institutional knowledge about a codebase has a compounding value that only appears when something breaks — and something always eventually breaks.
- F · 01Retreat-bundle product type
- Date-bound multi-component bundles (accommodation, meals, instruction) modelled in a custom PrestaShop module. No off-the-shelf equivalent.
- F · 02Sanskrit-learning content layer
- Separate from the storefront and the blog: its own database tables, frontend routes, and admin panel for vocabulary and philosophy content.
- F · 03B2B reseller layer
- Partner-agency tracking with contact, country, and currency records. Bookings routed through the reseller module without touching the public storefront flow.
- F · 04Customised checkout flow
- 67 class and controller overrides at peak, modelling retreat-specific validation rules — date selection, component configuration — that the default checkout doesn't enforce.
- F · 05Continuous maintenance
- Seven years of payment-provider swaps, GDPR adjustments, shipping updates, and PHP runtime upgrades — all handled by the team that wrote the original modules.
- F · 06In-flight major-version migration
- PrestaShop 1.7.4 → 1.7.8.11 completed in production; 1.7.8.11 → 8.2.3 in late-stage staging. Every override re-tested, every module given a PHP 8.x compatibility pass. The migration is the work that earns the stewardship.
The migration that's running now.
PrestaShop 1.7's end-of-life forced a choice in 2025: replatform, or migrate. Replatforming means throwing away seven years of domain-specific module work and starting over on a new stack. We made the case for migration. The operator agreed.
The migration runs in two stages. The first — PrestaShop 1.7.4 → 1.7.8.11 — landed earlier and is in production. The second — 1.7.8.11 → 8.2.3 — is the harder jump: PrestaShop 8 moved more views to Twig and changed the override system enough that all 67 class and controller overrides need to be re-tested or refactored. Every custom module needs a PHP 8.x compatibility pass.
October 2025 alone produced 245 commits on the 8.2.3 migration branch. The work runs in a branched staging environment with mirrored production data. Every checkout flow, every retreat bundle configuration, every Sanskrit-content route is being tested against the new version before the cutover window opens. The migration is methodical and slow because the audit trail it leaves matters as much as the upgraded code.
The reason the migration is possible — and stays within budget — is that the team doing it wrote the original modules. We didn't discover the complexity; we already owned it.
The case for staying on the same team for the upgrade.
Seven years. One team throughout. A major-version migration currently in late-stage staging.
The platform in production today runs PrestaShop 1.7.8.11 with the retreat-bundles module, the Sanskrit-learning surface, the B2B reseller layer, and the customised checkout flow intact. The 8.2.3 branch is the next step — the migration that resists being treated as a one-week sprint, and the part nobody plans for at the start of a custom-platform engagement.
The value of a long engagement on a custom platform isn't the initial build. Anyone can build the first version. The value is accumulated context: knowing which override is load-bearing, which module assumption will shatter under a new framework version, which PHP class the payment step depends on in a way the documentation doesn't mention. That context doesn't transfer to a new team in a migration brief. It lives in the people who wrote the code. The migration that's now in staging is possible — and survivable — because the same team owns the original code.
They wrote the modules. They were the right team to migrate them.
