The project blueprint — fill it at the start of any project
For: a partner, a customer's own IT team or our Custom Development team starting a project for an iVendNext customer, before quoting it and before building. Reference: the demand-to-ladder map (the sampled needs and the ladder classes), the extension-point catalogue (guide chapter 9, The extension-point catalogue and requests), guide chapters 3 and 15 (The ladder, Customer archetypes) and the feedback forms (../feedback/).
A blueprint is one page per project that answers six questions: what does the project do, which door does each need use, how big is it, what does it connect to, which extra work does it switch on, and what could go wrong. It is the same page for a three-store shop and a fifty-store chain. The needs decide what the project gets, never the customer's size: "Standard" and "Enterprise" describe a customer, and they route nothing.
How to fill it
- Copy the template below into your project.
- Write section (a) first. Then list every need in (b), one row each, in the customer's words.
- Place each need on the ladder. Find the nearest sampled need (or, if none is near, the nearest request class) and take its ladder class. Pick the door. Set the status from the table in section (b).
- Fill (c) and (d) with real figures, or with a stated guess. A guess is fine if it is marked as one.
- Read (e) against the first four sections. Each module that applies is switched on, and its extra work joins the project.
- Write (f). A risk you did not write down is one you will meet on the day.
- Keep the blueprint up to date as scope changes. Attach it, or link it, to any point request, sample request or kit defect that concerns the project.
The ladder classes (the same names as the demand-to-ladder map):
| Mark | Class | Meaning |
|---|---|---|
| ✅ | deliverable today | a developer can deliver it now with no code inside the tenant and no product change |
| ✅ᵇ | deliverable today, with a stated bound | the same, with a limit you must state in the row (for example feed: until the scoped event feed ships, the integration user needs a broad role to read it) |
| 🔶 | needs a published extension point | waits on an extension point we are building (its name, as guide chapter 9 gives it, in the Door column) |
| 🔷 | needs product work that is not an extension point | a feature of a pack, our payments or our fiscal apps; ask us |
The doors, in order: configuration · outside app (the API and the event feed) · till key · manifest · sandboxed function · a request for an extension point. A rung is used only when the one above cannot do the job. The four rules (guide chapter 3) apply to every row.
The template — copy from the line below
# Blueprint: <project name>
Prepared by: <outside partner | customer IT team | Custom Development team>
Date: <date> · Version: <n>
Kit version: <the version of the kit you worked from>
Sandbox / staging site: <the site you tried it on>
## (a) The project in two lines
<What the customer wants, and what you will deliver. Two lines, no more.>
## (b) Fit-gap on the demand-to-ladder map
| # | Need (customer's words) | Nearest sampled need or request class | Ladder class | Door | Status | Note |
|---|---|---|---|---|---|---|
| 1 | | | | | | |
## (c) Scale profile
| Measure | Value | Basis (counted / estimated) |
|---|---|---|
| Stores | | |
| Tills per store, by kind (counter · phone · tablet · Handheld) | | |
| Active products (and variants) | | |
| Customers on file | | |
| Sales per day per till — an average day | | |
| Sales per day per till — the busiest day | | |
| Lines per sale (average) | | |
| Peak-hour share (share of a day's sales in the busiest hour) | | |
| Offline hours expected per till per week; the longest single outage | | |
| Integration event volume per day; at the peak hour | | |
## (d) Integration map
| System | Direction | Door | What moves | Volume (per day / peak hour) | Who owns the far side | Our connector or your app | Identity map kept by | If the far side is down |
|---|---|---|---|---|---|---|---|---|
| | | | | | | | | |
## (e) What this blueprint switches on
| Module | On / off | Because (row or figure) |
|---|---|---|
| Joint extension-point lane | | |
| Scale proof | | |
| Release gate in the customer's CI | | |
| Dedicated bench (Custom Development only) | | |
## (f) Risks and open questions
| # | Risk or question | Touches | What would settle it | Who can answer |
|---|---|---|---|---|
| 1 | | | | |
(a) The project in two lines
Say what the customer wants and what you will deliver, in business terms. If it takes more than two lines, it is two projects.
(b) Fit-gap on the demand-to-ladder map
One row per need. The columns:
| Column | What goes there |
|---|---|
| Need | In the customer's words, one line. Not a mechanism. |
| Nearest sampled need or request class | The row number of the nearest need in the map's 50 sampled needs, or the name of the nearest of its request classes (selling screen, print / receipt / label, ERP integration, back-office / stock / count, payment / tender, report / dashboard, fiscal, loyalty / gift / promo). If nothing is near, write none — that row probably needs a point request. |
| Ladder class | ✅, ✅ᵇ, 🔶 or 🔷, taken from the nearest row and checked against your case. |
| Door | The way in the row uses: configuration, manifest, event feed, till key, extension point (with its name from guide chapter 9), sandboxed function, outside app. A row can use more than one. |
| Status | One of the three below. |
| Note | The bound (for ✅ᵇ), the extension point's name, or what you checked. |
Status, from the ladder class and the catalogue:
| Status | When |
|---|---|
| Deliverable today | the class is ✅ or ✅ᵇ, and you have checked it on your sandbox. |
| Waits on an extension point | the class is 🔶 and the extension point is in the catalogue. Write its name as guide chapter 9 gives it. The row stays here until the extension point ships. |
| Needs a point request | no ladder class fits and no extension point in the catalogue does. Send a point request. |
| Product work on our side | the class is 🔷. It is not an extension point; ask us. |
⛔ A need that can be met only by breaking one of the four rules is not a row with a door. Rewrite the need ("what must be true for the customer") and place that.
(c) Scale profile
The profile says how big the estate is and how hard it is pushed, in numbers a test can reproduce. The scale-profile kit (tools/scale_profile/) books real till sales on a bench and reports the profile against what it measured — and, every time, what it did NOT measure (concurrency, many stores, a large catalogue, offline drains). Its figures are sequential, and no load test exists anywhere else, so a stated profile is the only way anyone will know the estate was ever sized. python3 tools/scale_profile/report.py <your profile.json> <the measurement> turns this section into that report.
Work out the peak. From the figures above:
sales per day = stores × tills per store × sales per till per day
sales in the peak hour = sales per day × peak-hour share
sales per minute at peak = sales in the peak hour ÷ 60
Do it once for the average day and once for the busiest day. Then check it against the known limits (below).
Known limits to check your profile against (guide chapters 15 and 16):
| Limit | Value |
|---|---|
| Largest live estate | 18 terminals |
| Load tests run | none |
| Our Acumatica connector | about 2.75 complete sales a minute per connection |
| ERPs per company | one |
| Company | one country and one currency |
| Handheld | books online only in its first release |
| Offline | the sales snapshot lasts 24 hours, the catalogue 72 hours, offline promotions 7 days |
| What is not offered offline | an answer from your service is not asked for on an offline till, unless it is a sandboxed function |
(d) Integration map
One row per outside system. The door is the event feed, the API or a file. A system with two directions gets two rows.
- Our connectors first. Where one of our connectors fits (the online shop, the ERP), name it. A connector replaces a row of your own work.
- Identity map. Every sync that keeps records on both sides needs someone to hold the map of record ids. Say who holds it.
- If the far side is down. Say what waits, where, and what catches up. The event feed holds what you have not collected.
- Who owns the far side is a role ("the customer's IT team", "the ERP vendor"), not a person.
(e) What this blueprint switches on
The needs decide, not the size. Each module below is switched on by something in sections (b) to (d), and by nothing else. The triggers are the proposed ones; a module you switch on adds work, and one you leave off is a risk to write in (f).
| Module | Switched on when | What it adds |
|---|---|---|
| Joint extension-point lane | a row is waits on an extension point or needs a point request and the project cannot go live without it | work with us on that extension point, from its specification to its first release, using the point-request form |
| Scale proof | any figure in (c) is above the known limits, is a guess you cannot back, or an integration leg's peak is near its known rate | the scale profile is run against a sandbox with the scale-profile kit before go-live, and the result is attached to the blueprint |
| Release gate in the customer's CI | the project reaches the sale or money (a till key, an extension point, a sandboxed function, a wallet), or the customer's own IT team will own upgrades | the recorded baskets, the money kit and the self-check run in the customer's own pipeline, and are re-run before every upgrade |
| Dedicated bench | Custom Development only, and only if embedded Python is the sole way to meet a need | a dedicated bench for that customer; the case also becomes a point request, so the next customer gets a door. Outside builders never need one. |
(f) Risks and open questions
Write what you do not yet know, and what could stop the project. Use these prompts:
- A row's bound that the customer has not yet accepted.
- An extension point the project waits on, and what you do if it slips.
- A figure in (c) that is a guess.
- A far side whose rate or availability you have not seen.
- Offline: what the stores do in a long outage.
- What the customer's gate will refuse.
- A need you could not place.
Each item names what would settle it and who can answer. Items that are questions to us go to the right form.
A filled example — a generic mid-size retailer
Invented for illustration. It is a specialty retailer with fourteen stores in one country, its own ERP and its own loyalty programme, and an online shop run by a separate team. No real customer.
Blueprint: Estate roll-out and own-systems link for a fourteen-store specialty retailer. Prepared by: customer IT team · 2026-10-04 · version 1 · kit of 2026-10-04 · the team's own sandbox site.
(a) The project in two lines
The retailer runs its stores on iVendNext POS and keeps its own ERP and loyalty service. We deliver the configuration, a manifest for the loyalty records, an outside service that links the ERP and the loyalty service, and the release gate.
(b) Fit-gap
| # | Need | Nearest | Ladder class | Door | Status | Note |
|---|---|---|---|---|---|---|
| 1 | Member-tier discounts for three customer tiers | #2 | ✅ᵇ | configuration | Deliverable today | one promotion per tier, limited by customer group; stacking follows the promotion rules; checked on the sandbox |
| 2 | Reason codes on voids, refunds and discounts | #39 | ✅ | configuration | Deliverable today | |
| 3 | Receipt with logo and tax number | #8, #10 | ✅ | manifest (print format) + configuration | Deliverable today | |
| 4 | Warranty lookup at the till | request class: selling screen — behavioural (the warranty sample) | ✅ | till key | Deliverable today | answered by the retailer's service; the sale goes on if the service is down |
| 5 | Earn loyalty points on every booked sale | #22 | ✅ᵇ | outside app + event feed | Deliverable today | bound feed: the integration user needs a broad role to read the feed until the scoped feed ships |
| 6 | Spend loyalty points at the till | #23 | 🔶 | extension point: Wallet on the tender screen | Waits on an extension point | not offered offline or when the service is down; other tenders remain |
| 7 | Block payment when any line has a price of 0.01 | #35 | 🔶 | extension point: Check before tender | Waits on an extension point | also needed offline: a sandboxed function once A host for sandboxed functions ships |
| 8 | Sales, stock moves and purchasing to the ERP; items and prices from it | #30 | ✅ᵇ | outside app + event feed + API | Deliverable today | the retailer's own identity map and nightly reconciliation; bound feed |
| 9 | Shelf labels from a phone or Handheld | request class: print / receipt / label | 🔶 | extension point: Labels from the till and Handheld | Waits on an extension point | |
| 10 | A refund must go back to the original tender | #25 | 🔷 | — | Product work on our side | a setting of the POS app; asked for, not an extension |
| 11 | A customs declaration slip printed on each export sale | request class: print / receipt / label | none fits | — | Needs a point request | form sent; the receipt blocks in Receipt QR, fiscal marks and WhatsApp may cover it, to be confirmed |
(c) Scale profile
| Measure | Value | Basis |
|---|---|---|
| Stores | 14 | counted |
| Tills per store, by kind | 1 counter, 3 phones, 1 Handheld (14 counters, 42 phones, 14 Handhelds in all) | counted |
| Active products (and variants) | 18,000 | counted |
| Customers on file | 120,000 | counted |
| Sales per day per till — average day | 180 on a counter, 40 on a phone | estimated from last year |
| Sales per day per till — busiest day | 2.5 times the average | estimated |
| Lines per sale | 3.2 | counted |
| Peak-hour share | 14% of a day's sales | estimated |
| Offline hours expected per till per week; the longest single outage | 2 hours; 6 hours | estimated |
| Integration event volume | about 16,500 a day (4,200 sales, 12,000 stock changes, 300 customer changes); about 2,300 at the peak hour | derived |
Peak. Sales per day = 14 × (180 + 3 × 40) = 4,200. In the peak hour: 4,200 × 14% = 588, or about 9.8 a minute. On the busiest day: about 24.5 a minute. That is above the 2.75 sales a minute that one of our Acumatica connections books, so the ERP leg must be sized by the retailer's own ERP intake, not by that figure (the retailer's ERP is its own, and is the far side in (d)).
(d) Integration map
| System | Direction | Door | What moves | Volume | Who owns the far side | Our connector or your app | Identity map | If the far side is down |
|---|---|---|---|---|---|---|---|---|
| The retailer's ERP | out and in | event feed + API | sales, stock moves, purchases out; items and prices in | about 16,500 events a day; 2,300 at peak | the retailer's ERP team | the team's outside service | the outside service | events wait in the feed; the service collects from its cursor and reconciles each night |
| The retailer's loyalty service | out | event feed | booked sales | about 4,200 a day | the retailer's loyalty team | the team's outside service | the loyalty service | events wait; points are credited when the service returns |
| The retailer's loyalty service | in | till key (and Wallet on the tender screen once it ships) | member status at the till; later a points tender | one call per sale | the retailer's loyalty team | the same service | — | the till carries on without the answer |
| The online shop | out and in | API | orders in; stock and prices out | about 600 orders a day | a separate team | our WooCommerce connector | the connector | orders queue on the shop side |
(e) Switched on
| Module | On / off | Because |
|---|---|---|
| Joint extension-point lane | on | rows 6, 7 and 9 wait on extension points and the project cannot go live without 6 and 7; row 11 needs a request |
| Scale proof | on | the busiest-day peak (24.5 sales a minute) is far above a connection rate we know, and the largest live estate is 18 terminals against this one's 70 devices |
| Release gate in the customer's CI | on | rows 4, 6 and 7 reach the sale, and the retailer's team will own upgrades |
| Dedicated bench | off | no need requires embedded Python; the project is built by an outside team |
(f) Risks and open questions
| # | Risk or question | Touches | What would settle it | Who can answer |
|---|---|---|---|---|
| 1 | The wallet (Wallet on the tender screen, guide chapter 9) may ship after the planned go-live | row 6 | the catalogue's build order, or go live without redemption at the till | us (the date); the retailer (whether it can wait) |
| 2 | The peak of 24.5 sales a minute has never been tested here | rows 5, 8 | the scale proof on the sandbox | the builder |
| 3 | The ERP's own intake rate in the busiest hour is not known | row 8 | the ERP team's figure | the retailer's ERP team |
| 4 | A six-hour outage at a store: does the store keep selling on the 24-hour snapshot? | all tills | the offline limits in guide chapter 16, and a rehearsal | the builder |
| 5 | Discounts for tiers and the shop's promotions may stack in a way the retailer does not want | row 1 | a basket test on the sandbox | the builder; the retailer |