Canvas + Loft Furniture Rewards Private app preview, built to your written spec

Dashboard

Every number below is live demo state: record referrals at the POS tile, fulfill orders in the lifecycle simulator, and watch payouts, clawbacks, alerts, and the Klaviyo feed update across the app.

Two-minute tour

1. Open the POS tile and record a referral in three taps, then link an order and watch validation pass or auto-void.   2. Run the Lifecycle simulator through fulfillment, a replayed webhook, and a clawback.   3. See what the customer sees in the earnings ledger.   4. Check the Discord alert and Klaviyo feed under Integrations.   5. Read how I would build it on real Shopify APIs.

Recent activity

Built to the spec

POS tile: search referrer, save, link laterWorking
Validation: first order, $1,000 minimum, no self-referralWorking
$100 payout on full fulfillment onlyWorking
Clawback up to remaining balance, spent portion absorbedWorking
Cashback 2%, toggle + percentage in SettingsWorking
Six referral statuses + customer-facing labelsWorking
Discord alert per event, fraud fields includedWorking
Klaviyo events + live profile propertiesWorking
Smile.io balance migration, "Loyalty upgrade" ledger labelWorking
Draft-order earning path, idempotent processingWorking
No referral cap, multiple referrals per order allowedWorking
Unlinked POS referrals expire after the Settings windowWorking

Referrals

Filterable by status. Manual void/override records a reason, debits any issued credit, and posts a Discord alert, exactly as the spec's admin-dashboard section asks.

Customers

The fraud-vetting view: sortable by current balance and lifetime credit earned, with search. Click a customer for their full referral history and credit ledger.

Click column headers to sort

Settings

Cashback and payout are configurable without code changes; the simulators read these values live.

Cashback programIssue a percentage of order value as store credit on fulfillment
Cashback percentageLaunching at 2% per your spec
%
Referral payoutNative store credit issued to the referrer on fulfillment
$
Unlinked POS referral expiryReferrals recorded at POS that never attach to an order
days
Discord webhookChannel for referral event alerts
KlaviyoPrivate API key connection
Connected (demo)

POS "Add Referral" tile

The showroom flow in as few taps as possible: open the tile, search the referrer, save. The referral starts Unlinked; when the sale's order is created, the app attaches it and runs validation automatically. Unlinked referrals expire after the window set in Settings.

Then the order comes in

Simulate the resulting sale

Pick the referee and an order total. The app links the newest unlinked referral, runs the three validation rules, and either sets it Pending or auto-voids it with a recorded reason and a Discord alert.

Admin block, order page

For online orders, draft-order sales, and after-the-fact corrections. Validation runs immediately on save, and the block shows any existing referral on the order with its status.

Shopify admin, order detail

Canvas + Loft Rewards app block

Referral on this order

Customer earnings ledger

What the customer sees in their account on the storefront. Shopify shows the balance and handles redemption natively; this ledger adds the "where it came from" story with live statuses. Referred friends appear as first name and last initial only.

Lifecycle simulator

Run a referral through every path in the spec, including the draft-order flow, partial fulfillment, and the clawback remaining-balance rule. The engine is idempotent: replaying a fulfillment event never double-pays.

No active scenario

Start a scenario to see the engine narrate every rule it applies.

Discord alerts + Klaviyo feed

Every referral event posts an at-a-glance fraud alert to your Discord channel, and pushes events plus live profile properties to Klaviyo, which has no native store-credit sync, so this app is the source of truth.

Discord channel #rewards-alerts

Klaviyo event stream

Klaviyo profile properties (kept current)

Powers segments like "store credit balance greater than $0", triggered flows like "your $100 is live", and balance merge tags in email and SMS.

How I would build it

Your spec says you care about the end result, not a forced approach. This is the architecture I would propose: every surface on Shopify's supported extension points, native store credit as the source of money, and an idempotent event pipeline so payouts can never double-fire.

Surfaces, all first-party Shopify

POS tilePOS UI extension on the smart grid: search customer, save. Works offline-first; the referral syncs when the register does.
Admin blockAdmin UI extension on the order and customer pages, validation runs on save, shows the live status.
Customer ledgerCustomer account UI extension (new customer accounts), reads the app's ledger, Shopify renders balance and redemption natively.
DashboardEmbedded app (App Bridge) inside Shopify admin, staff logins only.

Money and data

Store creditShopify's native store credit mutations (credit and debit on the customer's store credit account), so balances, checkout, and POS redemption stay 100% native.
Referral recordsApp database keyed to customer and order IDs, with full status history and reasons, the source of truth for the ledger, Discord, and Klaviyo.
Draft ordersEarning attaches to the order a completed draft becomes, so your special-order workflow needs nothing special from staff.

Event pipeline

Webhooksorders/create (link + validate), orders/fulfilled (payout, full fulfillment only), refunds/create and orders/cancelled (resolve or claw back).
IdempotencyEvery payout and clawback writes an idempotency key per order and event. Replayed or duplicate webhooks are acknowledged and ignored, the behavior you can test in the lifecycle simulator.
ExpiryScheduled job expires unlinked POS referrals after the window set in Settings.

Integrations and rollout

DiscordWebhook post per event with referrer, referee, lifetime totals, and balance, your at-a-glance fraud feed.
KlaviyoEvents API for Referral Added, Store Credit Issued (with source), Clawed Back; Profiles API keeps balance, lifetime earned, and referral count current for segments, flows, and merge tags.
MigrationOne-time script from your Smile export at your conversion rate, each credit labeled "Loyalty upgrade" in the ledger, run in parallel with Smile until you are confident.
RolloutBuild on a development store first, then install on your store behind a staff-only test, then enable POS tile and customer ledger last.

Smile.io migration

One-time import honoring existing balances: your exported Smile points convert to dollars (you supply the conversion), the app issues native store credit, and each amount appears in the customer's ledger labeled as a loyalty upgrade. Run both systems in parallel for verification before canceling Smile.

Import preview, smile-export.csv

Conversion: 100 points = $5.00 (demo rate)