A software developer who is particularly good at turning strong design and business requirements into finished products.
Scope
Baudie sells scented personal care products. The storefront is a custom Shopify theme built from nothing, no Dawn and no purchased base, designed at Lumios Digital and developed entirely by me. Every page on the site is one I built.
It runs to roughly 31,500 lines of Liquid across 46 sections, 27 templates and 17 snippets, and I still develop and maintain it.
The decision that shaped everything
A theme can be built two ways. You can hardcode the pages the brand needs today, which is faster to write and looks identical on launch day. Or you can build a vocabulary of parts and let the brand assemble pages out of them.
The first option means every future change comes back to the developer. A new campaign, a reordered homepage, a seasonal hero: all of it is a ticket, a deploy and a wait. The theme is finished the day it ships and slowly becomes a constraint.
I built the second. Not because the founder wanted to do her own production work, but because a store that cannot be edited without a developer is a store that stops being edited.
What that meant in practice
Every section is written to be reused rather than to serve one page. That shows up as 597 settings across the section schemas, plus 22 repeatable block types. Copy, imagery, colors, layout direction, spacing, link targets and toggles are exposed in the theme editor rather than baked into the markup.
Product content is driven by 33 metafields rather than hardcoded per product. Scent names and notes, bottle sizes, ingredient lists, how-to-use copy and video, card images, portrait crops, hover states, gradient colors, card background and text colors, the bundle upsell target and a bundle's fixed components all live on the product. Adding a product means filling in fields, not writing a template.
That combination is why the same section set produces genuinely different page types. The two clinical product lines do not use the standard product page at all; they use a landing page composition, built from the same parts.
The bundle builder
The hardest single piece is the bundle. A customer picks several scents from a collection, and the page has to keep up: images swap as selections change, the price recalculates, and the whole thing has to arrive in the cart as a coherent order.
Most of the work is in what it refuses to offer. The selector reads from a collection rather than a fixed list, so new scents appear automatically, and it filters out anything unavailable or tagged as coming soon before a customer can pick it. An out-of-stock scent that is selectable is a bundle that fails at checkout, and the customer blames the store rather than the inventory.
It is built as a listbox with the correct roles and keyboard behavior rather than a styled div, which is the difference between something that looks like a picker and something that works like one.
A second bundle
A duo followed: one scent the customer picks, paired with a fixed pack of wipes. It is its own section rather than an option on the first bundle, because Shopify concatenates every section's styles and scripts into shared theme-wide files. Shared class names would have duplicated every rule, and the new page's script would have hooked into the original bundle's page as well.
It also exposed a blind spot. Until checkout a bundle is a single cart line, so the theme cannot see inside it: the cart listed the scent but not the wipes, and offered wipes as an upsell to a customer who already had them. Both are answered from the product side. A product reference on the bundle names its fixed component for the cart card, and each upsell knows which bundles contain it, so the cart treats either as already there.
Subscribe & Save
The brand wanted subscriptions on its scents. Appstle runs the subscriptions themselves: billing, renewals, payment retries and the customer portal. The open question was how much of the storefront to hand over with them. Subscription apps ship their own widget that injects a selector into the product page. It is quick to switch on, and it puts a second piece of interface on the most important page in the store, styled by someone else and out of reach of the theme editor.
So the app's widget stays off and the theme renders the choice itself, from the product's selling plans. Eligible products, delivery frequencies and the discount are all edited in Appstle and only read by the theme. A product added to a plan gets the selector with no code change, and the saving shown on the page is generated from the plan rather than typed in, so it cannot drift from what checkout charges.
The dropdowns are a select-only combobox wrapped around the native select. The select stays the source of truth, so the existing cart and form code kept working untouched, and without JavaScript the customer simply gets the native control. The whole feature shipped behind two theme settings, so launch day is a settings change, not a deploy.
Cart
The side cart is the largest file in the theme. It is a full cart surface rather than a drawer that links to one: line item editing, quantity changes and add-to-cart all run against the Shopify AJAX API without a page load, with upsells rendered inline from product metafields.
Getting this right matters more than it sounds. The cart is the last interface between a customer and a purchase, and every reload is somewhere to lose them.
Subscriptions raised that bar. A line can be switched between a one-time purchase and any delivery frequency from a dropdown on the cart card, and the change is optimistic: the label, price and subtotal update the moment it is picked, while a single request per line saves it in the background. The cart only redraws when it has to: when a switch merges two lines into one, or when a request fails and the real cart has to win.
Checkout, and where pricing lives
Checkout is the one surface a theme cannot touch. Theme code does not run there, so the moment a customer has already decided to buy is the moment none of the above applies.
The straightforward approach is to build everything into a checkout extension: read the cart, decide what to offer, apply the discounted price from the client. Less code, works in a demo, and wrong. Anything running in the browser can be changed by the person running the browser, and a discount decided there is a discount a customer can rewrite.
So it splits into two deployed apps. A Checkout UI Extension in Preact queries the Storefront API and decides what to show. A Shopify Function compiled to WebAssembly and running on Shopify's infrastructure holds the pricing rules and applies them. The extension can suggest. It can never decide what a customer pays.
One metafield, two systems
Both sides read the same field. A product carrying custom.upsell_price is an upsell product, and the value is its deal price. The cart drawer shows it, the checkout extension shows it, and the function charges it.
That is what makes new offers a content change rather than a deploy. The one-pack lands at its price and the three-pack at its own, and a future upsell product is covered by filling in a field. The merchant also controls the checkout block itself, with an enable toggle, the heading and the offered variants exposed as settings in the checkout editor, plus an admin panel rendered on the discount's own page.
The risk in that arrangement is drift. If the display rule and the pricing rule ever disagree, a customer sees one number and is charged another, which is the worst failure this system could produce. The shared rule is written down as an invariant in both codebases, and the display logic clamps to the variant price, so a mistyped metafield can never show a discount the function will not honor.
The rules underneath
The deal only applies when the cart also holds at least one product that is not an upsell. Buying the wipes on their own pays full price, which is the difference between an add-on and a permanently discounted product.
Discounts are applied per item rather than per line, so any quantity lands exactly at the deal price. And it is deliberately one function rather than several: Shopify applies one automatic discount at a time, so splitting this across multiple discounts would have meant they compete. One function covers every upsell product and every quantity at once.
Subscriptions added another price to keep apart. A subscribed line already carries its subscription discount, so the function skips any line on a selling plan, while a subscription to a regular product still counts toward unlocking the deal. Promo codes are limited to one-time purchases, so the subscription price never stacks with either.
Testing
Discount logic fails quietly. Nothing errors, nothing appears in a log, and the store sells at the wrong price until somebody notices it in the numbers weeks later.
The pricing and eligibility rules are covered by 25 unit tests, and the function itself by integration tests that build the WebAssembly module and run it against fixture carts: an empty cart, a cart of upsell products only, a cart that should qualify, a subscribed upsell next to a one-time one, and the cases where the discount class is absent. Every pricing rule described above has a test that fails if someone changes it.
Subscriptions were tested end to end on a separate development store holding a copy of the catalog, because test payments on the live store would have meant closing its checkout to real customers. Every frequency, mixed carts, discount codes, real renewal orders, mobile, and the customer portal's skip, pause, resume, cancel and card update were run through before it shipped.
Also in the build
Ongoing
The relationship started at Lumios Digital and continued independently after the studio wound down. I still build and maintain the storefront.