DEV3 Kilnfront – Multi-Tenant Store Builder SaaS with Themes, Custom Domains & Plan Billing (Next.js)

A self-hosted Shopify-style platform on Next.js 16 and MongoDB: merchants build stores from five themes and a section editor, sell on subdomains or verified custom domains, and pay per-store plans plus transaction fees. Includes tenant isolation, dunning and a super-admin console.

by DEV3 TechnologiesVerified Author(0) 0 sales 0 viewsUpdated 04 Nov 2026

Video tour. Pick a section below to browse 108 screenshots in 10 sections.

Kilnfront is a store-builder platform you host yourself, built by DEV3 Technologies on Next.js 16, React 19, TypeScript, Tailwind 4 and MongoDB. You run the platform; merchants sign up, build a store from sections and one of five themes, sell on a free subdomain or a domain of their own, and pay you a per-store plan plus a small transaction fee. It is a web product: a marketing site, a merchant dashboard, the storefronts and a super-admin console, with no mobile apps.

No live demo: the 108 grouped screenshots and the two video tours above show every screen, including onboarding, the theme editor, a checkout, adding a domain, a failed renewal and the platform console. Seed the demo dataset (12 fictional stores) on your own machine to click through every role.

What merchants get

  • Onboarding: a wizard asks for a store name, a free address with a live availability check, a niche and a starting look, then fills the store with starter content and a launch checklist.
  • Catalogue: products with variants (options, SKU, price, compare-at price, stock per row), manual and rule-based collections, an inline inventory grid, CSV import with row-level errors, CSV export, media uploads and a live search-result preview.
  • Orders: payment and fulfilment state, a full timeline, fulfilment with carrier and tracking, full and partial refunds with optional restock, cancellation, abandoned-cart recovery links and discount codes (percent, fixed amount, free shipping) with usage limits.
  • Shipping and tax: shipping zones with flat, price-based or weight-based rates, and tax rules by country and region, inclusive or exclusive of price.
  • Customers: per-store customer accounts, order history, tags and segments, CSV export.
  • Analytics: sales, orders, sessions, conversion, a funnel, top products and a 3D globe of shopper countries.
  • Team and API: seven roles from owner to designer, audit log, API keys, signed webhooks and a generated API reference on the top plan.

Five themes and a section editor

  • Five presets that are meant to look unrelated: Atelier (editorial home and craft), Marquee (fashion, oversized type and ticker bars), Kiosk (food, colour blocks and chunky buttons), Circuit (gadgets, dark with spec tables) and Bloom (beauty, pastel gradients).
  • A theme editor with a live preview, a section panel, field-driven settings and twenty sections across the home, product and footer pages, including a lazy-loaded 3D product pedestal.
  • Edits go to a private draft with optimistic concurrency, preview through a signed link, and publishing swaps a single pointer. The last ten published versions can be restored.
  • There is no raw HTML or CSS anywhere in a theme: settings are validated against a schema, so a merchant cannot paste a script into a store.

Addresses and domains

  • Every store gets slug.your-domain. Slug rules, a reserved-word list and a 30-day change window with redirects from the old address are built in.
  • Custom domains are verified with a TXT record plus a CNAME (or an A record for apex hosts). Both must pass, so pointing a CNAME at you does not take over someone else's host. A pending claim never blocks the real owner.
  • Verified hosts become active; active hosts are rechecked daily and suspended after three failures. One host per store is primary and the others redirect to it.
  • A tls-ask endpoint is included for Caddy on-demand certificates.

Plans, fees and billing

  • Three plans out of the box (Spark, Kiln and Furnace) with caps for products, custom domains, seats and themes, plus a transaction fee per plan. Prices, fees and caps come from one config file.
  • Caps are counted live. A downgrade never deletes anything: over-cap products stay on sale and extra custom domains are suspended.
  • npm run billing:renew bills the plan and adds a "Transaction fees (n orders)" line to the invoice.
  • A failed renewal starts dunning: a banner and emails for days 0 to 7, a read-only dashboard for days 8 to 14, and a paused storefront from day 15. Paying clears it.

Platform console

  • Tenants with plan, status, GMV, domains and last order; tenant detail; impersonation with a banner and audit entry; suspend and resume; a button to simulate a failed renewal.
  • A domain audit, plan view, revenue (plan revenue against fees), invoices, an email outbox and an audit log.
  • A support role that can look and impersonate read-only, and a 3D "Kiln Field" with one glowing kiln per store.

How it keeps tenants apart

Every merchant model carries an immutable orgId, and a Mongoose plugin throws if a query has none. Only platform code and scripts may query across tenants, and a unit test fails if anything else does. Store host headers are stripped and re-set in proxy.ts, customer cookies and sessions are bound to the store, and the same email can hold separate accounts in two stores.

Checkout without transactions

The order flow does not need multi-document transactions, so a standalone MongoDB works. It reprices on the server, reserves stock line by line, claims discount uses atomically, numbers the order and creates it, undoing earlier steps if a later one fails. A sweeper cancels unpaid orders after 30 minutes and returns stock once; a payment that arrives after that is refunded automatically.

Good to know

  • Real payments, email and DNS were not tested with live accounts. Stripe and Razorpay drivers for merchants' stores exist, with encrypted gateway keys, but the simulated gateway is the default and every test and tour used it (card 4242 succeeds, 4000 0000 0000 0002 declines). Email is stored in an outbox unless you configure SMTP, and SMTP was not run against a real mail service. The live DNS driver and Caddy certificate issuance were not run against real domains; tests use the simulated DNS driver. There is no SMS or push.
  • Web only, no physical devices. The mobile screenshots and the phone tour are a headless browser at phone size. Nothing was tried on a real phone or tablet.
  • Billing limits that come from the shared core. When a real gateway reports a failed payment, its webhook does not yet start Kilnfront's dunning; the core's renewal treats a past-due subscription as paid; and on a scheduled cancel the last period's transaction fees are skipped. Failed renewals are started from the platform console's simulate button, so wire your gateway's failure events to the past-due helper before taking real payments.
  • No reservation journal. If the server dies halfway through a checkout, the compensation steps and the sweeper clean up, but there is no journal of stock reservations to replay. A crash in that narrow window can leave stock held until the sweeper runs.
  • The REST API is on the top plan only. Keys on the other plans are refused before the handler runs.
  • Fees are in USD cents. Stores in other currencies convert with a fixed table in the code; there is no live exchange rate.
  • Custom domains need an HTTPS front proxy such as Caddy with on-demand certificates, and a wildcard DNS record for store subdomains.
  • Polish left over from review: filter toolbars stack on narrow tables, a few checkout rows are cramped on phones, and Arabic storefronts fall back to a system font. Right-to-left layout works; the Arabic font does not.
  • Transaction fees are not returned on refunds. That is the documented rule.
  • No Lighthouse score was recorded for this product.

Quality checks

The recorded check run for version 1.0.0 passed type-checking and linting (0 errors), 144 app tests and 49 core tests, a production build of 118 routes with 205.2 KB of gzipped first-load JS and CSS on the home page, and seeding of the empty and demo datasets. The same run covered a headless-browser pass over 54 routes with 18 happy paths, an install test from the packaged zip (npm ci, build, setup wizard, admin login) and a secret scan. All seven checks passed. The tests cover tenant isolation, host routing, domains, the order flow, pricing, themes, billing and slugs. Logic review fixed ten defects before release (they are listed in the build notes).

What's in the download

The kilnfront/ application source with the shared DEV3 core vendored under packages/next-core, an .env.example, the seed and scheduled-job scripts, the unit and browser test suites, HTML documentation, a licence and a START-HERE file. Run npm install once; node_modules is not included.

How it's built

Architecture, stack, key decisions and the quality gates DEV3 Kilnfront passed before release.

The engineering behind Kilnfront, DEV3's multi-tenant store builder: a Mongoose plugin that fails closed, host routing in one proxy file, domain verification, a checkout that needs no database transactions, an immutable theme store and a dunning ladder.

The problem it solves

A store builder is one codebase pretending to be thousands of shops. The same process must answer for the platform's own site, a merchant's dashboard, a free subdomain and a domain a stranger just pointed at the server, and none of them may see another's data. Money adds pressure: stock cannot be sold twice, a discount code with ten uses cannot be used eleven times, and a card payment that lands after an order expired must not be lost. MongoDB makes that harder when you assume a standalone server with no multi-document transactions. Merchants also need freedom to design their store without being able to inject a script into it, and the platform must bill them monthly, charge a fee per order, and cope with a failed renewal without deleting anyone's shop.

Architecture and approach

Kilnfront is a single Next.js 16 app on MongoDB, built on the vendored DEV3 Next core for sign-in, organisations, plans, invoices, files, API keys and webhooks. One organisation owns one store.

Tenant isolation that fails closed

  • A Mongoose plugin on every merchant model adds an immutable orgId and throws TenantScopeError when a query, update, delete, count or aggregation has no orgId.
  • Cross-tenant code is confined to lib/platform/ and scripts/. A unit test searches the source and fails the build if the opt-out appears anywhere else.
  • Store customers are separate from platform users. Their session rows carry the store, so a cookie replayed on another store finds nothing, and the same email can hold two independent accounts.

Host routing in one file

  • proxy.ts removes any inbound x-kf-* headers, passes platform hosts through, rewrites slug.base-domain to /store/slug and every other host to a custom-domain route. It never touches the database; paused and suspended answers come from an internal gate request with a short cache.
  • The same /store/slug path works on the platform host as a no-index preview mode, which is how the theme editor and the tests reach a store.

Domains

  • A custom host needs a TXT record carrying a token and a CNAME or A record. A pending claim by one store never blocks the real owner, and the DNS driver can be simulated, which is how the tests and demo run.
  • A worker checks pending hosts every ten minutes, rechecks active ones daily and suspends a host after three failures. The Caddy tls-ask endpoint also answers for verified hosts, because the certificate is requested before the host can become active.

Checkout as a saga

  • Prices are recomputed on the server. Stock is reserved per line in sorted order with a conditional $inc; the discount use is claimed with a conditional update; the order number comes from a counter; the checkout key makes a retry return the same order.
  • Any failure undoes the earlier steps. A sweeper cancels unpaid orders after 30 minutes and only the call that wins the status update restocks, so it happens once. A late payment is refunded automatically.
  • Refund amounts and restock quantities are enforced by conditional updates, which closed over-refund races found in review.

Themes without raw HTML

  • A theme version is immutable once published. Edits go to one draft, saved with a version check so a stale save returns a conflict. Publishing swaps one pointer; rollback publishes a copy of an old version.
  • Section settings pass a schema: hex colours, a fixed font list, limited URL schemes, no HTML or CSS fields. Rich text is a block list rendered by React. Unknown section types fail validation.

Plans, fees and dunning

  • Structural caps (products, domains, seats, themes) are counted live; metered usage uses the core. Each paid order records a transaction fee from the plan's basis points, snapshotted on the order.
  • A renewal wrapper adds the fee line to the invoice. The dunning job reads a past-due date: a banner, then a read-only dashboard, then a paused storefront. Every dashboard action and API write goes through the read-only guard.

Quality gates and results

The recorded check run for Kilnfront 1.0.0 shows these results:

  • Static checks: the vendored core in sync with the shared source, tsc with 0 errors and ESLint with 0 problems across 266 TypeScript files.
  • Tests: 144 app tests and 49 core tests passing. The app suites cover the tenant plugin, cross-store isolation, the host matrix, domains, the order saga, pricing, themes, billing and slugs.
  • Build: a production build of 118 routes. The home page loads 191.1 KB of JavaScript and 14.1 KB of CSS gzipped (205.2 KB, against a 260 KB budget), and the 3D library is not in the initial payload.
  • Seed: the empty and demo datasets load on a test database: 12 stores, 381 products, 3,552 orders, 950 customers, 64 invoices and 73,471 analytics events.
  • Review: a logic review found ten defects, including a partial index that MongoDB 5 rejects, a guest order that could be claimed without email proof, a cart recovery token shared across carts and over-refund races. Each was fixed with a test, and a follow-up pass added more.

Known gaps are listed plainly: real gateways, email and DNS were not run with live accounts, there is no reservation journal for crashes between checkout steps, and a few billing edges come from the shared core. The listing's Good to know section has the detail.

Tech stack

Area Technologies
Application Next.js 16 App Router, proxy.ts host routing, Server actions, React 19, TypeScript
Tenancy Mongoose tenant plugin, Immutable orgId, Per-store customer sessions, Reserved slug list, Impersonation with audit
Commerce Stock reservation saga, Pricing and discount engine, Shipping zones, Tax rules, Refund service, Transaction fee ledger
Platform Plans and live caps, Renewal and dunning jobs, Domain verification, Caddy tls-ask, REST API and webhooks
Frontend Tailwind CSS 4, Theme tokens, Section registry, three.js accents
Quality Vitest unit suites, Browser smoke script, ESLint, Seeded demo data

Inside the build

Light and dark: The same dashboard on the porcelain light theme. Light and dark — The same dashboard on the porcelain light theme.

Feature tiles: Real product fragments instead of generic cards. Feature tiles — Real product fragments instead of generic cards.

Guides & articles

Practical guides and engineering write-ups for DEV3 Kilnfront.

Building a Shopify-style store builder: the hard parts, and where Kilnfront draws the line

Last updated
Building a Shopify-style store builder: the hard parts, and where Kilnfront draws the line: DEV3 Kilnfront

A store builder looks like an online shop until you notice there is a second customer. Your customer is the merchant, who needs a dashboard, a theme, a bill and an address. The merchant's customers are the shoppers, who need a fast storefront that never shows another shop's data. This guide goes through the parts of that problem that cost the most time when you build it yourself, and how Kilnfront, a Next.js 16 and MongoDB platform, deals with each. It also says where the answer stops.

The Kilnfront landing page: a kiln glows while storefront tiles glide out and snap together

Start with the address, not the product

Before a merchant adds a single product, the platform has to decide which store a request belongs to. Kilnfront does this in one proxy file. It strips any x-kf-* headers sent by the client, lets platform hosts through, sends slug.your-domain to that store's routes and sends any other host to the custom-domain route. The proxy never reads the database. Paused and suspended answers come from an internal request that is cached for a few seconds.

Two details save pain later. First, the same store is reachable on the platform host under /store/slug as a no-index preview, so the theme editor and every test can reach a store without DNS tricks. Second, store hosts only serve storefront routes, so /app or /admin on a merchant's domain is simply a storefront 404, and platform cookies never travel there.

Custom domains need two proofs

Letting merchants bring a domain invites squatting. Kilnfront asks for a TXT record carrying a token and a CNAME (or an A record for apex hosts), and both must pass. Pointing a CNAME at you does not claim anything. A claim that is still pending never blocks the real owner, who wins when their own check passes.

Verified hosts become active, are rechecked daily and are suspended after three failures; a store with several hosts has one primary and the rest redirect to it. A tls-ask endpoint is included for Caddy's on-demand certificates.

The DNS instructions page: a TXT and a CNAME record with copy buttons and live status

The honest limit: the tests and demo use a simulated DNS driver. The live driver and real certificate issuance were not run against real domains, so budget time for your own end-to-end check.

Let merchants design, but not inject

The theme system is a section registry. Five presets are tokens plus lists of sections, and twenty sections cover the home, product and footer pages. Every setting is validated against a schema: hex colours, a fixed list of fonts, limited URL schemes. There is no field for raw HTML or CSS, and rich text is a block list rendered by React, so a merchant cannot paste a script into a store.

Edits go to a private draft, saved with a version check so two open tabs cannot overwrite each other silently. Publishing swaps a single pointer, and the last ten versions can be restored.

The theme editor with a section panel on the left and a live storefront preview

Plans are caps, and caps are counted

Kilnfront ships three plans, with caps for products, custom domains, seats and themes and a transaction fee per plan. The caps are counted live from the data, not stored as counters that can drift. A downgrade never deletes anything: products over the cap stay on sale, creating new ones is blocked, and extra custom domains are suspended while the primary is kept.

Failed renewals are a ladder

The fee line is added to the invoice by a renewal wrapper ("Transaction fees (n orders)"). When a renewal fails, a past-due date starts a ladder. Days 0 to 7 show a banner and send emails. Days 8 to 14 make the dashboard read-only while the storefront keeps selling. From day 15 the storefront pauses with a 503 and a branded page. Paying clears it. Every dashboard action and API write goes through the read-only guard.

The past-due banner on day nine: the merchant dashboard is read-only until the invoice is paid

Limits to know before you take real money: when a real gateway reports a failed payment, its webhook does not yet start this ladder, so connect those failure events to the past-due helper. The shared core also bills a past-due renewal as paid and skips the last period's fees on a scheduled cancel.

Checkout without transactions

Kilnfront assumes a standalone MongoDB, so the order flow cannot lean on multi-document transactions. It reprices on the server, reserves stock line by line with conditional updates, claims a discount use atomically, numbers the order and creates it, undoing earlier steps if a later one fails. A retry with the same checkout key returns the same order. A sweeper cancels unpaid orders after 30 minutes and restocks exactly once, and a payment that arrives late is refunded.

What it does not have is a reservation journal. If the server dies between two steps, compensation and the sweeper recover, but a crash in that narrow window can hold stock until the sweeper runs.

See it in action

The video tour covers the landing page, onboarding, a storefront checkout and the platform console.

Video tour of Kilnfront

What else to compare

  • Platform console: tenants with plan, status and GMV, impersonation with a banner, suspend and resume, a domain audit, revenue split into plans and fees, and a 3D field of every store.
  • API: keys, signed webhooks and a generated API reference, available on the top plan only.
  • Languages and modes: English and Arabic right to left, light and dark. Arabic storefronts fall back to a system font.
  • What's not included: no mobile apps, no SMS, no live exchange rates (fees convert from a fixed table), and payments, email and DNS were not run with live accounts.
  • Quality: 144 app tests and 49 core tests passed in the recorded check run, with 0 type and lint errors and a production build of 118 routes.

Kilnfront is a source-code product you host yourself. The listing shows 108 grouped screenshots and two video tours instead of a live demo, and the "How it's built" section goes deeper on the architecture.

Frequently asked questions

The complete source code (version 1.0.0) as a download from your account, with the setup and usage guides shown on this page. You can modify the code to suit your product.

More from this author

View all

Related in Enterprise SaaS Starters

View all