← projects/WHERE slug = 'vaporbeast'
row 1 of 4
Regulated e-commerce platform
VaporBeast
Age-restricted retail, where an incorrect address is a compliance exposure rather than a missed delivery.
- slug
- vaporbeast
- kind
- Regulated e-commerce platform
- year
- 2024 — present
- role
- Software engineer, Solution25
- stack
- Shopware 6, PHP, Symfony, Vue.js, GraphQL, MySQL
- live
- vaporbeast.com ↗
- repo
- NULL
VaporBeast is a US retailer of vape and smoke-free products, selling to adults 21 and over with a separate wholesale programme. I worked on its Shopware 6 platform at Solution25 and wrote several of the plugins it depends on.
01What makes it different
Most e-commerce constraints are commercial. These are legal. Nicotine products in the United States fall under the PACT Act, which brings age verification at delivery, adult signature requirements, and real restrictions on which carriers may carry what. The storefront is age-gated before a visitor sees a product.
That changes the weight of ordinary features. Address entry is normally a conversion problem — here it decides whether a shipment is lawful and which carrier can take it. Payment is normally an integration detail — here the merchant category makes PCI scope a live concern rather than a checkbox.
02The plugins
Four extensions carry most of that weight, and each one exists because of a constraint rather than a preference. Smarty validates and normalises addresses against USPS CASS-certified data at checkout, and reports whether an address is residential or commercial and deliverable at all — which is what the carrier and service-level rules downstream key off.
Curbstone handles payment through remote tokenisation, so card data is captured by a PCI-validated Level 1 provider and never reaches the merchant's own systems. ShipHero syncs two ways with the warehouse: orders out for fulfilment, stock levels and tracking numbers back. Sales Agent lets a representative build and place an order inside a wholesale customer's account, with the agent recorded on the order, because wholesale buyers order by phone rather than self-serving.
03Extending rather than forking
The temptation on a build this specific is to modify the platform. That buys a working store and an unupgradable one, and the bill arrives at the next Shopware release.
Everything here sits on documented extension points instead: payment handlers, event subscribers and service decorators, custom entities with their own administration modules, scheduled tasks and the message queue for anything talking to a third party. Nothing polls a remote API inside a request the customer is waiting on.
04On reflection
The integrations were built one at a time as each was needed, so each grew its own approach to retries and logging. A shared convention for talking to a third party — one place for backoff, failure states and traceability — would have been worth establishing before the second one, not after the fourth.