AMPSU case study: Medusa ecommerce with paid recipes
AMPSU is an Estonian brand for home cooks. It sells pizza ovens, accessories and flour, and it publishes recipes. The shop and the recipes come from the same person and the same idea, so online they had to work as one place. This is how we built it, why we picked each tool, and what we learned along the way.
At a glance
- Front end: one Next.js storefront at ampsu.ee that serves both the shop and the recipes.
- Shop: Medusa runs products, stock and orders. Montonio takes payments, Omniva delivers.
- Recipes: content lives in Directus, subscriptions and payments in Stripe.
- Status: at the time of writing the shop is live on ampsu.ee. The recipe platform is built and merged, waiting for its final switch-on.
The brief
AMPSU sells physical products and wants to sell recipes as well. Those are two very different businesses:
- Physical goods need stock levels, bank-link payments, parcel lockers and tracking codes.
- Digital content needs user accounts, recurring billing and control over who can see what.
For the customer, though, it has to feel like one site. A pizza recipe should lead straight to a pizza oven. Someone who buys an oven should find out what to cook in it.
Why two systems instead of one
The first decision was whether to force everything into one platform. We didn't. Order fulfilment and content subscriptions work so differently that merging them would have made both worse.
So AMPSU runs two subsystems behind one storefront and one domain, each with its own payments, content and customer data.
The shop: Medusa, Montonio and Omniva
Medusa is an open-source headless commerce platform. We chose it because it gives you products, carts, orders and an admin out of the box without locking you into a theme or a set of payment and shipping partners. That matters in Estonia, where shoppers expect to pay by bank link and collect from a parcel locker, not just pay by card and wait for a courier.
Montonio handles payments. The customer pays through their own bank via Montonio, and the order is only created in Medusa once Montonio confirms the payment. The amount is always calculated on the server from the cart, never taken from the browser.
Omniva we integrated directly. Shipments were first registered through Montonio; later we moved that to Omniva's own API. After payment, this happens automatically:
- The shipment is registered with Omniva and gets a tracking code.
- The order is marked as fulfilled in Medusa, with the tracking code attached.
- The customer's confirmation email includes the Omniva tracking link.
- Every 15 minutes the system pulls new tracking events from Omniva and updates the order, for example to "delivered".
- If Omniva rejects a shipment, the shop owner gets an email with the reason and can fix the address in the admin.
Delivery covers Estonia, Latvia, Lithuania and Finland, the four countries in the direct Omniva contract. The free-shipping threshold is different for parcel lockers and courier, because courier delivery costs more.
Recipes: Directus and Stripe
Directus is the content system where the team adds recipes: ingredients, steps, cooking times, categories and tags. We didn't model recipes as products in Medusa. A recipe isn't stock; it has a different shape and changes far more often.
Stripe runs the recipe subscription. Recurring billing, plan changes, cancellation and card updates already exist there, and customers can manage their subscription themselves. We didn't need to build any of that.
Paid content: subscribe or buy one recipe
Paid recipes offer two options:
- A subscription, monthly or yearly, that unlocks every paid recipe.
- A single recipe, which stays unlocked for the buyer permanently. It's for people who want to try before committing.
Some recipes are free. Accounts can be created with email and password or with Google.
Access is decided in our application, not by Directus permissions. Directus only exposes published content. Whether a given person can see the full recipe depends on their subscription or purchase. Stripe notifies us of every change (started, changed, ended) and the app updates the user's status, so access always matches what has been paid for.
Where the shop and the recipes meet
The back ends are separate, but the customer sees one site.
- From recipe to product. Each recipe shows shop products that fit its category: ovens and accessories under a pizza recipe, fire pits under a barbecue recipe. Products come live from Medusa, so price and image are always current.
- Filters that help people choose. Recipes can be browsed by type of dish, cooking time, difficulty and mood.
- My Kitchen. Users tick off what they already have at home and see recipes that use those ingredients.
- Free learning corner. Some recipes and tips are open to everyone and linked from the homepage.
For the content team we wrote short guides in Estonian: how to tag a recipe so the filters find it, and how to write a product description in Medusa so it splits automatically into sections like key features, what's in the box, specs and FAQ.
What we learned
No project goes exactly to plan. A few decisions worth knowing about if you're planning something similar:
- Over-strict validation costs sales. We added a postcode check at checkout so Omniva wouldn't reject a parcel after payment. It turned out to reject real Estonian customers too, so we removed it. Simpler safeguards stayed: a phone number is required, and the country list only includes the four countries we can actually ship to.
- The cart has to survive fast clickers. When customers changed quantities quickly, cart updates collided. We fixed it at both ends: the browser now sends changes one at a time, and Medusa's locking runs on Redis.
- Two separate accounts is a deliberate trade-off. A recipe subscriber and a shop customer currently live in different systems. That keeps both sides simpler and stops one from breaking the other. The cost is that a customer may need two logins.
- A shared database is enough for now. The shop and the recipes use the same Postgres database. That keeps cost and maintenance low, but backups and outages affect both at once. We've documented it and will split them when there's a real reason to.
- New features ship without disturbing the shop. The recipe platform was built on a separate branch and tested in a preview environment against the real shop back end. On the main codebase it stays switched off until its configuration is in place, and the shop keeps running as before.
When this approach makes sense
This setup fits when you sell both physical products and digital content and want customers to move naturally between them. It also fits when off-the-shelf store templates feel too limiting but building everything from scratch doesn't make sense.
If you only have a small catalogue and no extra services, a hosted platform is probably the better choice. We'll tell you that ourselves.
Let's talk
Planning a headless commerce build in Estonia, a Montonio and Omniva integration, or paid content with subscriptions? Tell us where you are and we'll work out together what makes sense for you. Get in touch.
Have a workflow that should work better?
START A CONVERSATION →