The lightest storefront I could build
One dependency, no build step, no platform subscription — and what Shopify and its peers are really charging for.
The mainstream hosted stores all charge rent. Shopify’s cheapest plan that gives you a real storefront is $29 a month billed yearly — $39 month-to-month. Squarespace starts at $19. Wix and BigCommerce start at $29. The rent is due whether or not anything sells, and it rises as you add the things a working store needs: apps, a theme, a better checkout.
My shop doesn’t pay it. Not because I found a cheaper host, or a loophole in the rules. I built the storefront, so there’s no subscription to bill me for.
Metatron Mind sells heavyweight t-shirts and hoodies: twelve listings across five blanks, $19.76 to $57.16, printed one at a time and shipped from the supplier’s floor. There is no account, no newsletter popup, and nothing to accept before you look. Behind the shop is an order desk where I pick a blank, place the artwork, price it, and publish a listing; when an order is paid, it becomes a production order.
The whole storefront runs as one Node process on a $23.37/month VPS that was already running another project of mine, so its marginal hosting cost is zero. The only money that moves when a shirt sells is the card fee and the printer’s per-item price.
| The store, counted | Value |
|---|---|
| Runtime dependencies | 1 (stripe) |
| Build steps | 0 |
| Server | 4,487 lines, 248 KB, one Node process |
| Customer-facing code | 6,683 lines, 324 KB |
| Self-hosted fonts | 2 files, 87 KB |
| Analytics, trackers, ad pixels | none |
| Cookie banner | none needed |
| Third-party companies the pages load | 1 — Stripe, on checkout only |
| Operator pages customers never load | 3,933 lines |
| Platform subscription | $0 |
| Hosting | a share of a $23.37/month VPS already in use |
That table is the story. But the reason it’s worth telling isn’t the line count — it’s the shape of the cost I don’t have.
Rent, itemised
The plan is the floor, not the bill. A working Shopify store typically adds $50–$200 a month of apps — email, reviews, a popup, a cookie banner — plus $100–$380 once for a premium theme, plus 2.9% + 30¢ processing on the Basic plan. If you’d rather use Stripe or PayPal than Shopify Payments, Shopify adds another 2% on Basic.
Added up honestly, the first year of a small store is roughly $950–$2,750 in platform and app subscriptions — before the first sale, before the blank, before the printer, before a customer.
The other hosts are variations on the same shape:
| Host | Cheapest plan that sells online | What the sticker hides |
|---|---|---|
| Shopify | $29/mo billed yearly ($39 monthly) | 2.9% + 30¢ processing; +2% if you use a non-Shopify gateway; apps and themes extra |
| BigCommerce | $29/mo billed yearly ($39 monthly) | plans step up with trailing sales; auto-upgrades past $30k/year |
| Squarespace | $19/mo billed yearly | 2% of online sales on Basic; 0% from Core ($29) |
| Wix | $29/mo billed yearly (Core) | the $17 Light plan can’t take payments |
| Webflow | $29/mo billed yearly | 2% of sales on Standard |
| WooCommerce | no platform fee | hosting $25–$350/mo plus paid extensions |
2026 US list prices, annual billing where that’s the lower rate. Card processing is roughly 2.9% + 30¢ on the entry plans, on top.
None of these are bad deals for the right store. But notice what they have in common: a fixed monthly cost. A fixed cost asks you to predict demand. A variable cost just follows it. At twenty $57 orders a month, a $29 platform fee is about 2.5% of revenue — the same order of magnitude as the payment processing it sits next to. Add two apps and the rent can exceed the card fees. At zero orders, the rent is the only bill left.
The smaller the store, the bigger the subscription is as a share of the business. That isn’t a scandal; it’s the shape of rent. It’s just a shape most of us don’t price before we’re inside it.
What I built instead
I didn’t start out wanting to write a storefront. I wanted to sell shirts directly, with the printer as the only company between me and the customer. The supplier already had the hard part — blanks, print, shipping, a real API — and charges per item with no monthly fee. The storefront was the missing piece, so the only question left was what the smallest honest version of it looked like.
It looked like a folder of text files.
There’s no framework, no bundler, no transpiler, no build step. The files in the repository are the files the browser runs; the server serves them as they sit on disk. package.json has one entry under dependencies, and it’s the payment library. Everything else — sessions, password hashing, the image proxy, the SMTP client that sends order confirmations — is ours. The mailer is 192 lines, written on Node’s own net and tls because an order confirmation didn’t justify a second dependency. Writing it instead of installing one caught three real bugs a library would have hidden.
Light isn’t thin. The storefront does the unglamorous things properly:
- Tax is Stripe’s number. Stripe computes sales tax from the delivery address its own form collects. We display Stripe’s figure; we never invent one.
- The totals reconcile by construction. On the order record the goods subtotal is derived by subtraction from the amount Stripe actually charged, so subtotal + shipping + tax always equal the total.
- The confirmation says what the receipt says. If those two can disagree, one of them is lying to the customer.
- The operator’s work stays off the customer’s page. The order desk and design composer are another 3,933 lines of admin code that customers never download.
The design follows the same rule. Two neutrals and one accent; one sans and one mono, self-hosted; motion is a handful of CSS transitions, not an animation library. No popups, no account, no newsletter capture, no invented stock counter. That’s partly taste and mostly consequence: every one of those things would have been another dependency, another script, another promise to keep. The constraint did the design work.
Open the network tab
The claim I care most about isn’t the line count. It’s what the page doesn’t load.
The storefront loads no analytics, no trackers, no ad pixels, no CDN fonts, no third-party scripts. There’s no cookie banner because there’s nothing to consent to. The only third party any page loads is Stripe, on the page where the card is entered, and Stripe’s own embedded form collects the number. The card goes from the customer’s browser to Stripe; it never touches our server, and there’s no field in our code that could hold it.
You don’t have to take my word for it. Open the page source and look for an external URL, or watch the network tab. A claim like that should be checkable by anyone with a browser. The footer says it in one line: “Every byte on this page is ours.”
It’s also not a claim you make once and forget. The first version was nearly false. The site sits behind Cloudflare, and Cloudflare was injecting its Web Analytics beacon into the page at the edge — for real browsers only. It didn’t appear in curl, in the response body, or in the server’s own HTML. It appeared in the rendered page. We found it, turned the feature off in the dashboard, and measured again: zero third-party origins, zero console errors, no beacon request.
That’s the part of a light footprint that’s easy to miss. On a platform, what loads on your page is a product decision made by someone else — a new app, a new analytics default, a new recommendation widget. You can write “no trackers” in the footer; the edge may disagree. Keeping the claim true means checking it again after every change that isn’t yours.
What it actually costs
I’m not going to pretend it’s free. It isn’t. It’s just not a subscription.
| Value | A typical hosted store | This store |
|---|---|---|
| Platform subscription | $29–$39/month | $0 |
| Apps and theme | $50–$200/month, plus $100–$380 once | $0 |
| Hosting | included | a share of a $23.37/month VPS already running |
| Payment processing | 2.9% + 30¢ | 2.9% + 30¢ (Stripe) |
| Per item | blank + print | blank + print |
| What you actually pay | the monthly bill | the code, and owning it |
At twenty $57 orders a month — about $13,700 a year — the hosted platform floor is somewhere between 7% and 20% of revenue before the blank, the print, or the card fee. Here, the only costs that scale with the business are the card fee and the printer’s per-item price. An empty month costs almost nothing. A good month costs more only in the ways that come out of sales.
The real price is the one that isn’t on the invoice: those 4,487 lines don’t maintain themselves. There’s no support line when something breaks, no app to install when I want a feature, no theme update that fixes accessibility while I sleep. I own every bug, including the boring ones. If you measure the trade in hours, Shopify wins for most people — and it should.
The fair case for paying rent
It would be easy, and dishonest, to make this a takedown. Shopify is a very good product. It runs the parts most people don’t want to learn — hosting, uptime, PCI, fraud, checkout edge cases, tax, support — and it does it for less than most businesses could hire someone to do the same. The app ecosystem means you can add email, reviews, and a loyalty program without writing code. On a Monday you can have a store.
The point isn’t that paying for a storefront is dumb. It’s that the recurring cost has a shape most of us don’t price out before we’re inside it: a fixed floor before revenue, plus the apps, plus the cut on the entry plan, plus the scripts those apps put on the page. Each item is defensible on its own. Together they mean a store that hasn’t sold anything yet can still have a bill — and the smaller the store, the larger that bill is as a share of it.
The alternative to a subscription isn’t always “build it yourself.” It’s to know what the rent buys, and to decide whether you’d rather pay it in money or in code. Those are the two currencies. There is no third one.
The invoice
The store is live. It takes real cards, sends real confirmations, and shows twelve things for sale. It doesn’t collect analytics, doesn’t ask anyone to accept a cookie, and the only third-party code any page loads is Stripe’s, on the page where a card is entered. Its monthly bill is a share of a server that was already running.
Both ends of the business — the printer and the payment processor — charge per item. The only fixed cost left was the storefront, and that’s the one I removed by building it.
I’m not going to tell you to build your own storefront. Most people shouldn’t, and time is the one cost you can’t get back. But if you’re about to pay for a shop, price the rent: what it costs in January, what it costs when nothing sells, and what it puts on the page. Then decide whether the rent-free version is something you could learn to build. The answer may be no. It’s still worth knowing the number.
Notes and sources
- The store: shop.metatronmind.com. Prices, listings and checkout checked October 2026.
- Platform prices: Shopify pricing, plus Fulfill.com’s 2026 platform comparison (updated September 2026) and Dropbuild’s 2026 Shopify fee breakdown (April 2026). US list prices, annual billing where lower. They change; check before committing.
- Processing: Stripe’s published US rate, 2.9% + 30¢. Shopify Payments charges the same entry rate on Basic; the subscription is on top.
- Footprint numbers: measured from the store’s own files, October 2026. Server: 4,295 lines
server.mjs+ 192 linesmail.mjs= 4,487 lines / 253,504 bytes. Customer-facing HTML, CSS and JS: 6,683 lines / 331,662 bytes. Fonts: 89,028 bytes. Admin/design pages: 3,933 lines / 204,688 bytes. Uncompressed, comments included. - “No trackers” check: the live storefront’s HTML contained zero external origins when fetched; the only external code any page loads is Stripe on
/checkout. The Cloudflare beacon and its removal are recorded in the repository’s third-party audit.
Receipts — every primary source used
Every claim in the piece maps to a measured file, a capture or the store’s own source. Files in backticks are in this pack.
| Claim | Primary source |
|---|---|
| Platform prices: Shopify $29 annual / $39 monthly, Squarespace $19, BigCommerce/Wix/Webflow $29 | platform-costs.csv, compiled from shopify.com/pricing, the fulfill.com 2026 comparison and dropbuild.com’s fee breakdown; checked October 2026 |
| Apps/theme and processing: $50–$200/month apps, $100–$380 once, 2.9% + 30¢, +2% non-Shopify gateway | platform-costs.csv; stripe.com/pricing |
Runtime dependencies 1 (stripe); build steps 0 |
the store’s package.json; described in server-excerpts.mjs |
Server 4,487 lines / 253,504 bytes (4,295 server.mjs + 192 mail.mjs) |
measured from the store’s files at the time of writing. The source has grown since; the counts are the October 2026 snapshot. mailer.mjs is the 192-line mailer in this pack. |
| Customer-facing code 6,683 lines / 331,662 bytes; fonts 89,028 bytes; admin pages 3,933 lines | measured from the store’s own files, October 2026 (same snapshot caveat) |
| Zero third-party origins on the storefront; no analytics, no trackers, no CDN fonts | third-party-audit.md — the browser audit after the injection was switched off |
The CDN-injected beacon that curl never saw |
third-party-audit.md §Finding and §Why it is hard to see |
| The CSP mitigation and then the source fix; the claim became unconditionally true | third-party-audit.md §Mitigation shipped and §DONE |
| The store’s one allowed third party is Stripe, on checkout only | third-party-audit.md; the brief’s allowed-exception rule |
| One pricing path: the cart quote and the checkout charge come from one function | server-excerpts.mjs §one pricing path and §the reconciliation point |
The mailer was written on node:net/node:tls and caught three real bugs |
mailer.mjs (the code and its header) |
| Verification method for the claim | verify-origins.mjs; third-party-audit.md §What we deliberately do NOT claim |
Capture date: October 2026. Platform fees and prices change; the CSV names the source and the check date so the table can be re-priced before it is relied on.