Skip to content

Powered by Grav CMS + Helios Theme

The demo printer

Kahuna Print Co. is a printer that doesn't exist. It has a catalogue, quotes postage, takes an order, makes it, ships it in a parcel or two and delivers it, and it never talks to anything outside your store. It sits behind exactly the same screens as Printful, Printify and Gelato, so what you see with it is what you'll see with a real provider.

Warning

Never switch it on for a store that sells for real. Every product and every price is invented, and every parcel moves on a clock instead of a van. A store running it would charge customers for goods nobody makes.

It's off until you switch it on. Off, it isn't registered, listed or served.

Use it to walk the Products, Orders, Providers and Review tabs, the order panel, the checkout rates and a tracking page before you open an account anywhere. A demo store uses it too, because a demo has no print account and no money to spend.

Switching it on

Two keys, in the store's own config:

YAML
# user/config/plugins/kahunacart-print-on-demand.yaml
demo_provider:
  enabled: true
  mode: auto

Both are needed. enabled registers the provider. mode: auto makes the order desk send each order the moment it is paid, which a read-only demo needs because nobody can press Send there. The settings screen has no fields for the demo provider, so Grav does not fill a default in for you: write mode out, or the demo waits in review mode like a real provider and an order sits unsent.

Two more keys are optional:

Key Default What it does
tick_seconds 60 How long one tick of the demo printer's clock is.
production_days 3 Days added to the delivery estimate at checkout for making the order.

Checkout rates need one more switch, and it is KahunaCart's, not this add-on's. The demo's Standard and Express appear at checkout only when shipping.carrier_rates.enabled: true is set in user/config/plugins/kahunacart.yaml. Without it the checkout says live rates are unavailable.

The catalogue

Three products, the same on every store. Amounts are plain numbers of the store's own currency, so a demo in euros or pounds has believable margins and nobody invents an exchange rate.

Product Variants Cost Suggested retail
Kelp Bay Surf Tee 4 colours (Black, White, Sand, Ocean) by 5 sizes (S to 2XL) 9.50, or 11.00 for 2XL 24.00, or 27.00 for 2XL
Tide Mug White, Seafoam 4.80 14.00
Reef Poster 12 x 18 in, 18 x 24 in, 24 x 36 in 6.00, 9.00, 13.50 18.00, 26.00, 38.00

The mockups are drawn for the demo and ship inside the add-on, with no photographs and no brand marks.

The postage

Arithmetic on where the parcel goes and how many things are in it. No clock, no randomness, no network.

TXT
price = base + per extra item × (items − 1)
Service Where Base Per extra item Days
Standard home country 4.50 1.50 3 to 5
Standard Europe 9.00 2.50 6 to 9
Standard rest of the world 14.00 4.00 9 to 14
Express home country 12.00 3.00 1 to 2
Express Europe 22.00 5.00 3 to 4
Express rest of the world 32.00 7.00 4 to 6

"Home" is the store's own country, and the United States when the store does not say. The days shown at checkout count production_days on top.

The clock

A tick is a stretch of time, a minute by default. Count the ticks since the order was sent and where it has got to is fixed. Nothing is stored beyond when it was sent, so a read that comes late catches up in one go and a repeat changes nothing.

Ticks since sent The order is
0 Submitted
1 In production
2 Shipped (the first parcel)
3 Shipped (the second parcel, when there is one)
4 Delivered

An order with two or more lines goes in two parcels, the second a tick behind the first, so a visitor sees what a partly shipped order looks like. A one-line order goes in one parcel and is shipped from tick 2.

What moves the clock. The job worker does, by itself: KahunaCart fires a worker tick after its queue drains and the add-on listens for it. By hand:

BASH
bin/plugin kahunacart-print-on-demand demo:tick
bin/plugin kahunacart-print-on-demand demo:tick --advance=4

--advance=4 moves every open order's clock on four ticks first, so a fresh order is delivered at once. The command works on a read-only demo, because demo.readonly refuses writes through the admin and leaves the command line open. It refuses to run when the demo provider is off.

Orders are moved through the same tracking the poll and the Check again button use, so what a demo order does is what a real one does: a core shipment with a carrier, a tracking number and a link, and KahunaCart's shipped email.

The tracking page

A real parcel's tracking link goes to the carrier's website. These parcels have no carrier, so the add-on serves a page at {your API}/kahunacart/pod/public/demo-track/{number}, and only when the demo provider is on. Tracking numbers look like KP and ten digits, and are worked out from the order, so the same order always gets the same numbers.

It is a bare page with its own markup, no theme, no assets and noindex, nofollow, with a banner saying this is a simulated carrier. It is public and unauthenticated, which is what a tracking page is, so it prints a status, a time and a place, and never a name, an address, an order number or a price. An unknown number is a 404, and anything but a GET is refused with a 401.

The two services ship with Kahuna Post (Standard) and Kahuna Express (Express) as the carrier names. KahunaCart's own carrier list does not know them, so on a customer's receipt the parcel reads as the Other carrier, with the right tracking link, until you add them in user/config/plugins/kahunacart.yaml:

YAML
shipping:
  carriers:
    - { code: 'kahuna-post', label: 'Kahuna Post', tracking_url: 'https://your-site.test/api/v1/kahunacart/pod/public/demo-track/{tracking}' }
    - { code: 'kahuna-express', label: 'Kahuna Express', tracking_url: 'https://your-site.test/api/v1/kahunacart/pod/public/demo-track/{tracking}' }

Config is yours, and the seeder never writes it.

The seeder

BASH
bin/plugin kahunacart-print-on-demand seed
bin/plugin kahunacart-print-on-demand seed --purge --yes

Run it after bin/plugin kahunacart seed --account --zones, because it adds shipping methods to the zones that command makes. It refuses to run when the demo provider is off.

What it writes:

  • The three products, imported, priced at the suggested retail and published, with their links and mockups.
  • Standard and Express added to every shipping zone, bound to Kahuna Print Co.
  • Two orders, placed and sent through the same order desk and tracking a visitor's order goes through. A tee and a mug, placed five days ago, went in two parcels and are delivered, with both shipments and tracking on the order. Two tees by Express were sent a tick and a half ago, so one order is still being made and the clock is moving it while a visitor watches. Every address is at example.com.

Two promises:

It is idempotent. Run it twice and the store is the same store. A product already imported, a method already bound and an order already placed are kept and never rewritten, so an hourly reset can run it without knowing what state the store is in.

It is reversible. --purge takes back exactly what it wrote: its products with their links, its shipping methods, and its orders with their provider orders and parcels. The zones, your own methods and anybody else's orders stay put. Two things core does not undo on a product or order delete: its picture folders under user/images/kahunacart/products/ stay, and the daily report rollup keeps counting the seeded orders until bin/plugin kahunacart reports:rebuild --from=<date> is run.

The seeded orders' dates are compressed. The delivered order is dated five days ago, but its parcels shipped minutes after it was sent, because the journey runs on the one clock. A seeded order's customer is at example.com, and the shipped emails it queues go nowhere.

Switching it off

Set demo_provider.enabled: false (or remove the block). The provider disappears from the Providers tab, the checkout stops quoting Standard and Express, the public tracking page returns a 404 and the clock stops. Orders it already made stay in the store, with their status as it was. To take the seeded content away first, run seed --purge --yes while it is still on. After that, run bin/plugin kahunacart reports:rebuild --from=<date> so the dashboard stops counting the seeded orders.