Third atlas

The Template
Atlas

Possible documentation pages for the Image Portal prototypes, built only from the pieces of the Visual Aid Atlas (charts and diagrams, numbered V) and the Type Atlas (text elements, numbered T).

Each page type comes in several radically different templates. Every template is a real, filled page you can read, click and resize.

Content: the Baseline prototype, the receipt feature and the silo rules. Facts from the repository are real; anything made up has an orange dotted underline.

Read the labels V numbers point at the Visual Aid Atlas, T numbers at the Type Atlas. Quoted from the repository Invented for illustration Mixed real rules, invented detail

01Landing / overview

The start page of one experiment: what it is, what to open, where to read on.

A full-bleed poster: generative art, one sentence, two buttons. Four numbers you can click, then the buying journey as a metro map whose stations open the screens.

Prototype · Image Portal

Baseline

Today's model, clickable. Search, buy and get a receipt, as a company or as a private person.

Numbers from the repository. Sparklines show invented weekly history.

Ride the buying journey

  1. SearchCreative and Editorial tabs
  2. Asset pageThe purchase panel
  3. CartChange license, remove
  4. CheckoutBuying as, terms, Pay now
  5. Waive withdrawalPrivate persons only
  6. ConfirmationOrder placed
  7. ReceiptA4 PDF

Read on

The classic three-column docs page: nav tree left, page in the middle, on-this-page right. Quiet and predictable; the visual summary is a strip of four key facts.

Baseline ☰
Rules
Components

Baseline

Today's model: main group, license group, product, base prices.

WhatThe public site and the admin
Try it as5 customers, via Alt ⇧ P
TestedAdmin, 30 September
Updated8 October 2026

What you can try

  • Search to receipt works for companies and private buyers.Done
  • The purchase panel in all five plan situations.Done
  • Checkout as UX designed it for LIP‑1440.Done
  • Contact us on the panel still opens the old form.Partly
  • Logged-out visitors aren't decided (LIP‑1546).Not yet

Read on

Who to ask

Ferdinand (UX) answers design questions for the checkout.

The prototype team keeps this page and the status up to date.

The experiment as a newspaper front page: the latest change is the lead story, numbers sit in the rail, a ticker rolls the small news. Serif, columns, dense.

Prototype editionTuesday 13 October 2026NTB Image Portal

The Baseline

Today's model, written up for designers, product owners and developers

LATEST
Checkout updated with Ferdinand's answers · 8 Oct Receipt decisions moved to their own feature · 7 Oct Header now matches the live site · 6 Oct Admin user test held · 30 Sep
Checkout · LIP‑1440

Everyone now pays prices including VAT

Companies and private buyers see the same prices, with the VAT on its own line.

By the prototype team · Updated 8 October 2026 · Decision D5
Sailing boat at sunset, Lofoten. Photo: Ola Berg / NTB. Sample image

The design split buyers. Companies saw prices without VAT, private buyers with.

Ferdinand (UX) changed that on 8 October: every customer sees prices including VAT.

“The prototype should look like the live site except for what it tests.”Decision D9

Every price says “incl. VAT”. Totals show subtotal, VAT (25 %) and total.

Prices are whole kroner. 1 711 kr plus VAT is 2 139 kr, not 2 138,75. D11

Admin prices stay excluding VAT. Only customers see the VAT added.

Try checkout as Kari →

No hero, no prose: the experiment's folder tree is the navigation. Every leaf is a page or a screen, so developers and designers read the same map.

baseline/

One folder is one website. Blue leaves are docs pages, orange leaves are app screens, grey is code.

Docs: readApp: click throughCode: change
Designers

Start in app/, then check components/.

Product owners

Start with Status and Decisions.

Developers

Start in -lib/rules/, then routing.

02Feature introduction

Show the feature first, then say three things about it. Here: the receipt.

The thing itself, big and tilted on a brand-coloured stage, like a product shot. Three bold facts and two buttons beside it; the six sample cases as chips underneath.

ReceiptOrder 2026-10431
NTB AS
Skippergata 24 (Pressens hus)
0154 Oslo
Kari Nordmann
Storgata 1, 0155 Oslo
Date13.10.2026
StatusPaid
BuyerPrivate
Ski jumper, HolmenkollenPhoto: Ingrid Haugen / NTBEditorial · NTB Editorial
1 500 kr
Northern lights, TromsøPhoto: Sana Mir / NTBWeb and social media
2 139 kr
Sailing boat, LofotenPhoto: Ola Berg / NTBEditorial · NTB Editorial
875 kr
Subtotal excl. VAT3 611 kr
VAT (25 %)903 kr
Total incl. VAT4 514 kr
License terms attached per licensePage 1 of 1
PAID
Feature · Receipt

A receipt you can print, keep and forward

One A4 page in NTB's colours with every image, the VAT and the license terms. R1

It keeps a copy of the order, so it shows what was paid even if prices change. R3

Screen, print and PDF are the same page. One thing to design and check. R4

A comic strip carries the whole idea before a single rule is stated: who gets the receipt, when, and why it must not change. Three numbered take-aways follow, each a link.

Kari buys a picture. Months later, the receipt still says the same.

The receipt feature, in four panels. Story invented; the rules behind it are real.

1
The receipt is a snapshot. Lines, prices and buyer are copied when the order is placed. R3
2
Every buyer sees the same breakdown: subtotal excl. VAT, VAT (25 %), total incl. VAT. R7
3
It works without any prototype. The feature has its own sample orders. R6

An isometric exploded drawing shows the feature as a stack: one order snapshot, one component, three outputs. The four real build steps sit underneath as a strip.

One component, three receipts

Screen, print and PDF come from the same React page.

  1. Three outputsOn screen, browser print, and a PDF from the server. R4
  2. One receipt pageSizes in millimetres and points, brand colours fixed. R1
  3. One order snapshotCopied at checkout, never recalculated. R3
Step 1Order placed

Checkout copies lines, prices and buyer.

Step 2Receipt page

React renders the snapshot as an A4 sheet.

Step 3Headless Chrome

Opens the page in print mode, from localhost. R5

Step 4PDF

A4 with margins and page numbers.

Open the samples →Why headless ChromeAll decisions

03Tutorial

Learning by doing: a safe path with a result at the end. The reader follows; the page checks they got there.

A progress header and six steps. Each step pairs one action with a small picture of what you should see, and a box to tick when you see it. The header fills up as you go.

Buy your first image as Kari

0 of 6
  1. 1Open
  2. 2Be Kari
  3. 3Find
  4. 4Add
  5. 5Try to pay
  6. 6Pay
10 minutes. EstimateYou need the dev server running.You end with a receipt as a PDF.
1

Open the public site

Go to localhost:3100/prototypes/baseline/app.

NTBSearch imagesAP
2

Become Kari

Press Alt Shift P to open the prototype menu. Choose Kari, the private person.

3

Find the ski jumper

Search for ski. Open the ski jumper over Holmenkollen.

NTBskiKN
4

Pick a license, add to cart

Choose Editorial. Every price says “incl. VAT”, for every buyer. D3

Editorial1 500 kr
Web and social media2 139 kr
Prices in NOK, including VAT.
Add to cart
5

Press Pay now too early

Open the cart, go to checkout, and press Pay now without ticking anything. The button always works; it points out what's missing. D8

I accept the license terms
Please accept to continue
I waive my right of withdrawal
Please accept to continue
Pay now · 1 500 kr
6

Tick both, pay, open the receipt

Private persons tick two boxes; companies tick one. D15 There's no payment step yet. D14

I accept the license terms
I waive my right of withdrawal
✓ Order placed · Receipt (PDF)
Tick all six to finish.Then try the same as a company: Aftenposten.

The tutorial is a conversation. A guide gives one instruction at a time; you answer with a reply button, which reveals the next message. Checkpoints fill in the side rail.

See the purchase panel change · 5 minutes
GuideThe purchase panel changes with the customer. Let's see four of them.
GuideOpen any image's page. You're Aftenposten: no plan, so you see prices.
Editorial1 500 kr
Web and social media2 139 kr
Prices in NOK, including VAT.

A dark, code-first lesson for developers. A rail of numbered lessons with times; each lesson is one command, its output, and what to notice. Ends by breaking a rule on purpose.

1Install

im-web-prototypes
~/im-web-prototypesbun install
✓ 412 packages installed
✓ commit gate on (.githooks)

Installing also turns on the commit gate. Every commit is checked from now on.

2Copy Baseline

im-web-prototypes
~/im-web-prototypesbun scripts/new-prototype.ts baseline price-test
✓ copied 118 files → src/routes/prototypes/price-test
✓ rewrote routes and PROTOTYPE_ID
✓ regenerated route tree and agent rules

Your copy gets its own server state, so the two never share orders or carts.

3Look around

price-test/one experiment, one silo
route.tsxits name
_docs/docs at /prototypes/price-test
app/the running thing, at …/app
-lib/code; never a URL
-docs/markdown for people

Folders are the routes. A leading - hides a folder from the router; _ adds no URL. Routing

4Name it

Open price-test/route.tsx and change the title.

export const Route =
createFileRoute(1
'/prototypes/price-test',
)({
staticData: {
title: 'Price test',2
description: null,3
},
})
  • 1The path was rewritten for you in lesson 2.
  • 2The title feeds the tab title, breadcrumbs and docs nav.
  • 3Leave out staticData and the type checker stops you.

5Break a rule on purpose

Import the receipt's VAT helper straight from the receipt feature, then commit.

im-web-prototypes
~/im-web-prototypesgit commit -am "Use the receipt's VAT"
✗ fallow: price-test imports features/receipt
~/im-web-prototypesbun scripts/copy-from.ts receipt prototypes/price-test vat.ts
✓ copied vat.ts → -lib/from-receipt/
✓ noted source commit in copied-from.json
~/im-web-prototypesgit commit -am "Copy the receipt's VAT"
✓ format · lint · fallow: all clear

Experiments never import each other. Copy instead; your copy is yours to change.

You have a sealed experiment.Next: write its first decision · why silos

04How-to guide

One task, for someone who already knows what they want to do. Steps, no theory.

The whole task on one ruled index card: what you need on the left, three steps on the right, the menu drawn as you will see it. Nothing to scroll past.

Baseline › How-to › View the site as another customer
10 SECONDS How-to · Baseline

View the site as another customer

Works on every page of the running prototypeChanges prices, plans and the purchase panel

You need

The five customers

  • Aftenposten, no plan
  • Bergens Tidende, quota
  • Stavanger Aftenblad, subscription
  • Fædrelandsvennen, both
  • Kari, private

Do this

  1. Open the prototype menu with the flask icon, or press Alt+Shift+P. It works over open dialogs too.
  2. Pick a customer under “View as”.
    Prototype menu
  3. Look at the purchase panel. It now shows Bergens Tidende’s quota.
✓ Done. The cart stays as it was.
Why five? D38: a plan belongs to a workspace, so each panel case needs its own customer. · “10 seconds” is a guess.

A docs-shell page whose lead is a yes/no flowchart: most readers stop at their first “yes”. The command only appears at the end, for those who need it.

Docs › How-to › Reuse code

Reuse code from another experiment

Answer from the top. Stop at your first yes.

Is the code in your own experiment?same folder under src/routes
yes
Import it. That’s always allowed.
no
Is it in src/platform?UI, formatters, media, docs shell
yes
Import it. Every experiment may use the platform.
no
Does every experiment need it, with no product decision in it?
yes
Ask the team to move it into the platform. No form for this yet.
no

Copy it. The copy is yours.

# from the repository root
$ bun scripts/copy-from.ts features/receipt prototypes/baseline receipt-page.tsx
copied receipt-page.tsx, receipt.tsx, types.ts, vat.ts
wrote  prototypes/baseline/-lib/from-receipt/copied-from.json
Then point your imports at -lib/from-receipt/.

Never import across experiments. Fallow refuses the commit. See who may import whom.

The source commit is recorded in copied-from.json, so drift can be shown later.

The reference is copied too, never imported: reference/working-model works as a source.

A dark, terminal-flavoured page where the command is the headline. Every word of it is labelled in place; below come the three results and the four ways it can fail.

How-to · one command

Copy a file from another experiment

Type this from the repository root.
bunrunsthe script with Bun
scripts/copy-from.tsthe toollives in scripts/
features/receiptsourceanother experiment, or reference/<name>
prototypes/baselinetargetyour experiment, <kind>/<id>
receipt-page.tsxfilesone or more; what they import comes along
# what you'll see
$ bun scripts/copy-from.ts features/receipt prototypes/baseline receipt-page.tsx
✓ 4 files → src/routes/prototypes/baseline/-lib/from-receipt/

What you get

The files and what they import, in -lib/from-receipt/, same layout.
Imports rewritten so the copy never points back at the source.
A note of the source commit and a hash per file, in copied-from.json.

If it fails

!

“Refuses to overwrite” means your copy has changed since. Keep it, or add --force to take the source again.

?

“Target must be <prototypes|features>/<id>”: you typed a path. Use prototypes/baseline, not src/routes/…

?

“Source and target are the same experiment.” Inside one experiment, just import.

i

Want a different folder? Add --into rules to copy into -lib/rules/.

Last step: point imports that used the source at the copy. Not sure you should copy? · Why copy at all?

05Reference

Look it up, don’t read it. Fields, rules, names and who may use what, complete and in a fixed order.

A real path, cut into coloured segments, is the first screen; under it a sticky row of names jumps into a three-column dictionary: name, what it means, where you’ll meet it.

Reference · routing

Route file names

src/routes/the router reads here
prototypes/kindor features/
baseline/experimentone silo
_docs/pathlessnot in the URL
rules/a real grouproute + index
$chartId.tsxparameterone page per chart

URL: /prototypes/baseline/rules/checkout

__root.tsxthe shell
The route around every page. The HTML shell, tab title and description.
Only one:
src/routes/__root.tsx
route.tsxnames a section
The folder’s own URL, usually a layout. Its title is the breadcrumb and the nav group label.
prototypes/baseline/route.tsx
index.tsxthe section page
The page at the folder’s URL. Every section has one, so every breadcrumb opens a page. The nav calls it “Overview”.
_docs/rules/index.tsx
$nameURL parameter
One file, many pages. Markdown docs, rule charts, component pages, orders. Needs entries for the nav.
_docs/rules/$chartId.tsx
_namepathless layout
Wraps pages without adding to the URL. _docs puts the docs shell around docs pages.
/features/receipt/variations, not …/_docs/variations
-nameignored
The router skips it. Code in -lib and markdown in -docs sit next to the routes that use them.
baseline/-lib/
a.b.tsxflat nesting
b under a, in one file name. Only for a page and its PDF, side by side.
app/receipt.$orderId.pdf.ts
(name)not used
Route group: never used here. Parentheses are risky in globs.
Use _docs and app instead.

Full rules and reasons: why the routes look like this. Names after TanStack’s file naming conventions.

Dense and tool-like: all 36 Baseline decisions as a waffle you can click, then one line each under a sticky filter bar with group chips, counts and live search.

Baseline decisions36 decided · one line each · newest wording

    Split screen: a dark adjacency matrix answers “may A import B?” at a glance and explains any cell you tap; the light side lists each folder as a card.

    Reference · silos

    Who may import whom

    Row imports column. Tap a square.

    Baseline Receipt Image grid Platform Reference Docs site
    allowedrefused, copy insteaditself
    Every experiment may import itself and the platform. Nothing else.

    The four kinds of folder

    src/routes/<kind>/<id>/

    One experiment: its docs, app, code and markdown.

    Imported by: only itself

    src/platform/

    Neutral building blocks: UI, formatters, media fixtures, docs shell, chart engine, design tokens.

    Imported by: every experiment

    src/reference/

    im-web today, team proposals and the working model.

    Imported by: only the Docs pages. Experiments copy.

    src/routes/docs/

    Docs and the lists of experiments, plus the root routes.

    Imported by: nobody

    Checked by Fallow after every edit and before every commit. What would go wrong without it?

    06Explanation

    Why it works this way. For reading away from the keyboard: context, reasons, trade-offs.

    An illustrated essay: the metaphor picture first, then a centred serif column with a drop cap, notes in the margin and one pull quote. On a phone the notes drop into the text.

    Sealed silos, one shared well, a truck for copies, no pipes in between.
    Explanation · the repository

    Why every experiment is a sealed silo

    Prototypes are allowed to disagree. Sharing code would make them agree by accident.

    From AGENTS.md and docs/routing.md · 4 minutes

    Experiments test ideas that contradict each other. One prototype may show prices without VAT while another shows them with it. Both have to keep working.1

    So each folder is a silo. Its docs, app, code and markdown live together, and it imports only itself and the platform.

    The platform holds no opinions. UI parts, formatters, media and the docs shell: mechanisms, never product decisions.2

    “Nothing has to stay compatible across them.”docs/routing.md

    But copying is duplication

    Yes, on purpose. A copy can change freely. An import would tie two experiments together, and the next change to one would quietly change the other.

    Copies remember where they came from. The script records the source commit, so drift can be shown later.3

    Who keeps the walls up

    A tool, not good intentions. Fallow checks imports after every edit and again before every commit. A cross-import never reaches the repository.

    The cost is small. About one copy a week, against never wondering whether a change here broke a test over there.

    Starts from what people wrongly believe. One myth fills the first screen, struck out beside its fact; smaller pairs follow; leftover questions fold into an accordion.

    Myth

    “I’ll just import the receipt into my prototype.”

    Fact

    You copy it. The commit with the import is refused.

    Fallow, before every commit

    Silos: five things people get wrong

    And why the repository works the way it does.

    MythShared code keeps experiments in step.
    →
    FactExperiments shouldn’t be in step. They test ideas that contradict each other.
    MythThe platform is where shared business rules go.
    →
    FactThe platform has no product decisions. Mechanisms only: UI, formatters, media, docs shell.
    MythThe working model is imported by every prototype.
    →
    FactIt’s copied. Baseline has its own copy in -lib/rules/. How
    MythA copy loses track of its source.
    →
    FactThe source commit is recorded with a hash per file, so drift can be shown.

    Questions people ask

    Can a feature use a prototype’s sample data?

    No. The receipt keeps its own licenses, prices and buyers (R6). Prototypes may change their samples freely.

    Where do the Docs pages get the lists of experiments?

    From the route tree. Nothing else lists pages, so nothing falls out of step. Route names

    What if I really need the same fix in two places?

    Copy it twice, or change the reference and copy again. Decide with the flowchart

    An explanation you operate: a sentence with live numbers, a network that tangles when you allow cross-imports, and the count of ties that a change could break.

    Explanation · try it

    What if experiments could import each other?

    With 6 experiments and cross-imports , a change in one experiment can reach 0 others.

    6possible ties to check

    Silos: each experiment ties only to the platform. One more experiment adds one tie.

    Counting every possible import. Real repos use fewer, but nobody can see which. Read the long version

    07Component page

    One UI component: every variant side by side, and what to check in each.

    No diagram and no prose: the page is a wall of live mock-ups, one per situation, each with its own tick list. Filter chips pick a customer.

    Baseline / Components / Purchase panel

    Purchase panel

    One panel, six situations. What it offers depends on the plan of the customer you view the site as.

    1No planViewing as Aftenposten. Buy a one-off license.
    Ski jumper, Holmenkollen
    NTB Editorial
    Prices in NOK, including VAT.
    Supplier instructionsEDITORIAL USE ONLY. No use in betting, games or single club/league/player publications.
    Other use? Contact us
    Check 0/4
    2Pack covers itViewing as Bergens Tidende. A download quota.
    Ski jumper, Holmenkollen
    NTB Editorial
    7 NTB Editorial pack7 of 10 credits left
    Editorial Included
    Need another use? Buy a one-off license
    Check 0/3
    3Pack emptySame pack, no credits left.
    Ski jumper, Holmenkollen
    NTB Editorial
    0 NTB Editorial pack0 of 10 credits left
    Check 0/2
    4SubscriptionViewing as Stavanger Aftenblad. Time-limited plan.
    Ski jumper, Holmenkollen
    NTB Editorial
    NTB Editorial subscriptionIncluded in your subscription
    Editorial Included
    Check 0/2
    5Pack and subscriptionViewing as Fædrelandsvennen. Quota plus a creative subscription.
    Ski jumper, Holmenkollen
    NTB Editorial
    3 NTB Editorial pack3 of 10 credits left
    Your NTB Creative subscription doesn’t cover this image.
    Check 0/2
    6Not in your planThe plan is for another product.
    Northern lights, Tromsø
    NTB Creative
    Your plan doesn’t include NTB Creative.
    Check 0/2
    Purchase panel chartDecision tableOpen in the prototypePanels driven by the same scenarios as the chart.

    An engineer’s data sheet: a blueprint-blue spine holds the facts, and four tabs hold one view each. It opens on the measured drawing.

    All measures are illustrative; the design file has the real ones.

    The screen itself leads, with numbered markers; hover a number to light its part. Below, a three-frame film strip shows the component change state.

    Order summary

    The right-hand panel in checkout. Seven things on it are decided.

    1. 1Buying as is read only. It comes from the workspace. D13, D19
    2. 2Three lines of totals for every buyer. D3, R7
    3. 3Whole kroner in every amount. D11
    4. 4One box accepts the license terms. D15
    5. 5Private buyers only see the waiver. D15
    6. 6The button shows the total and never greys out. D8
    7. 7Help is one quiet line under the button. D22

    Three states

    I accept the license terms
    I waive my right of withdrawal
    Pay now · 3 175 kr
    1 · UntouchedNothing ticked, no errors yet.
    I accept the license terms
    Please accept to continue
    I waive my right of withdrawal
    Please accept to continue
    Pay now · 3 175 kr
    2 · Pay pressed too earlyRed under each box; focus on the first.
    ✓I accept the license terms
    ✓I waive my right of withdrawal
    Pay now · 3 175 kr
    3 · ReadyPay places the order at once.

    A dark poster of right and wrong pairs, each with its reason, ending in a one-click quiz. The component is the smallest one there is: a price.

    Component · Price

    Write it this way.

    Every price on the site, from the panel to the receipt. Five rules, all decided.

    ✓ DO2 139 kr incl. VAT
    ✗ DON’Tkr 2,138.75
    Norwegian, whole kroner. D1 D2 D11
    ✓ DO1 875 kr incl. VAT
    ✗ DON’T1 500 kr excl. VAT
    Companies see VAT too. D5
    ✓ DOWeb and social media
    ✗ DON’TWeb & Social
    One name for the web license. D6
    ✓ DOIncluded
    ✗ DON’TSubscribed
    A covered license has one badge. D7
    ✓ DOlicense
    ✗ DON’Tlicence
    American spelling. D23

    Quick check

    A base price of 1 711 kr. What does the customer see?

    08Decision page

    What was decided, why, and what else was on the table. Example: D5, prices including VAT for everyone.

    One sheet of paper, like an architecture decision record: a stamp, four key facts in a ruled strip, the options as three columns, then consequences.

    DECIDED8 OCT 2026
    D5 · Prices and words

    Every customer sees prices including VAT, companies too.

    RuleCustomer prices incl. VAT
    Who decidedFerdinand (UX)
    SourceLIP-1440, Slack Q1
    WherePanel to receipt

    The design split buyers in two. Companies saw prices without VAT, private buyers with.

    Now one price for all, in the panel, mini cart, cart, checkout, confirmation and receipt.

    The admin is unchanged: base prices are still entered excluding VAT.

    Options

    A · THE DESIGN

    Split by buyer

    • Companies see what they book
    • Two prices for one image
    • Checkout must know the buyer first
    B · CHOSEN

    Incl. VAT for all

    • One price everywhere
    • Same totals block for all (D3)
    • Companies do the VAT sums
    C · NOT RAISED

    Excl. VAT for all

    • Matches the admin
    • Private buyers see a lower price than they pay

    What follows

    “incl. VAT” beside every price. D3

    Whole kroner, since 25 % gives øre. D11

    The receipt follows suit. R7

    The checkout chart’s comment is now out of date. To fix

    Sources

    The first screen is the change itself: grey past on the left, coloured present on the right, with the old price struck out. The rule’s wording follows as a word diff.

    Before

    Two prices for one image

    Company1 711 kr excl. VAT
    Private person2 139 kr incl. VAT
    Since 8 October

    One price for everyone

    Company1 711 kr2 139 kr incl. VAT
    Private person2 139 kr incl. VAT

    The rule, word by word

    Show customer prices excluding VAT to companies and including VAT to private persons incl. VAT for company and private buyers alike (purchase panel, mini cart, cart, checkout, confirmation, receipt).

    New wording from D5; the old wording is reconstructed from the checkout chart’s comment.

    Where it changes

    Why

    Ferdinand (UX) answered question 1 in Slack on 8 October.

    One price is easier to test than two that depend on the workspace.

    Not changed: the admin still takes prices excluding VAT.

    Decided · LIP-1440 · Related D3 D11 R7 · All decisions

    A story told as a timeline: the question, the chat where it was answered, the edit to the rule. A side panel keeps the outcome in view the whole way down.

    D5 · How we got here

    From two prices to one

    Five moments in nine days.

    The user test shows the admin

    Prices were entered without VAT in the admin that was tested.

    Admin as tested

    Two prices in the checkout design

    Companies without VAT, private buyers with. The prototype copied the design.

    LIP-1440

    The question goes to UX

    Prototype teamQ1: Should companies see prices without VAT, as in the design?
    Ferdinand (UX)No, everyone sees prices including VAT, companies too.
    +1 · 3
    Prototype teamSame totals for everyone, then?
    Ferdinand (UX)Yes. Subtotal, VAT, total.

    Answers and date are real; the wording is reconstructed.

    The rule is rewritten

    Checkout, confirmation and receipt totals, for private buyers for every buyer: “Subtotal excl. VAT”, “VAT (25 %)”, “Total incl. VAT”.D3, revised with D5 · old wording reconstructed

    The receipt follows

    R7 gives the receipt the same breakdown for every buyer.

    Receipt decisions

    09User-test guide

    Before you test a prototype: what to set up, what to ask, what to watch for.

    A cockpit for the facilitator on test day: the agenda as a Gantt bar, a ticking checklist with progress, keys and customers at hand. Built to be glanced at, not read.

    Checkout test · Baseline20 October 2026 · 60 min per participant · LIP-144000:00

    The hour click a block

    Before they arrive 0 of 7

    Keys

    Alt+Shift+PPrototype menu, even over dialogs
    Or click the flask icon

    View the site as

    Aftenpostenno plan
    Bergens Tidendequota
    Stavanger Aftenbladsubscription
    Fædrelandsvennenquota + creative
    Kariprivate

    Steer clear

    Logged-out visitors aren’t built. Stay logged in.
    “Contact us” in the panel opens an old form. Checkout has the new dialog.
    No order history yet. End each task at the receipt.

    A print sheet on a cutting mat: big serif task cards for the participant, handwritten stickies with what to watch for the facilitator. The stickies don’t print.

    Task cards

    Print, cut, hand over one at a time.

    For the participant

    1

    Your paper needs a picture of a ski jumper for tomorrow’s sports page. Buy one.

    Viewing as Aftenposten · no plan
    2

    You want the same picture for your newsroom’s Instagram too. What will it cost?

    Look for “Web and social media”
    3

    You’re buying a photo of the northern lights for yourself. Go all the way to paying.

    Viewing as Kari · private
    4

    Your accountant asks for proof of what you paid. Find it.

    Ends at the receipt PDF

    For you, the facilitator

    Card 1Do they notice “incl. VAT” beside each price? (D3)
    Card 2Do they expect to change the license in checkout? It can’t be done there (D18).
    Card 3Watch the waiver box. Do they read it, or tick and go? Ask what “withdrawal” means to them.
    Card 4Where do they look first: email, confirmation or orders? Order history doesn’t exist yet.

    The test is laid out as the buyer’s journey: stages across, rows for the task, the screen, what to watch and the rules in play, with an expected-mood line on top. On a phone it folds into one column per stage.

    Test scenario

    Kari buys a picture for a blog

    KKariPrivate buyer · first purchase
    Find
    Choose
    Cart
    Checkout
    Pay
    Receipt
    Expected mood *
    Task
    Search “nordlys”
    Pick the web license
    Check the total
    Read what you agree to
    Press Pay now
    Open the PDF
    Screen
    Search
    Image page
    Cart
    Checkout
    Checkout
    Confirmation
    Watch for
    Editorial tab first: does Kari switch?
    Three licenses: is the choice clear?
    Looks for VAT?
    Opens the terms, or not?
    Presses with a box unticked?
    Expects an email?
    Rules
    D25starts on Editorial
    D6 D3
    D10 D11
    D15 D22
    D8 D14
    R1 R7

    1 · Find 🙂

    Task: search “nordlys” on Search.

    Editorial tab first: does Kari switch? (D25)

    2 · Choose 😐

    Task: pick the web license on the image page.

    Three licenses: is the choice clear? (D6, D3)

    3 · Cart 🙂

    Task: check the total in the cart.

    Looks for VAT? (D10, D11)

    4 · Checkout 😟

    Task: read what you agree to in checkout.

    Opens the terms, or not? (D15, D22)

    5 · Pay 😐

    Task: press Pay now.

    Presses with a box unticked? (D8, D14)

    6 · Receipt 😀

    Task: open the PDF from the confirmation.

    Expects an email? (R1, R7)

    * The mood line is our guess, to compare with what you see. Task cards · Run-sheet · Status: what isn’t built

    10Architecture

    How the parts fit: what may depend on what, and what happens in which order.

    A poster: the layered diagram takes the whole first screen, four short floors read left to right under it, and a dark strip ends the page with what is checked before every commit. On a phone the drawing becomes stacked HTML layers.

    How the parts fit

    Sealed silos on a shared floor

    Every experiment stands alone. It may use itself and the platform, nothing else.

    SiteDocs and the lists of experiments, built from the route tree.
    Experiments · one silo each
    baselineprototypeproduct-adminprototype receiptfeatureimage-gridfeature page-builderfeaturepresentationsfeature order-flowfeaturedesign-systemfeature doc-skillsfeature

    ✕ No silo imports another. Reuse means copying.

    ↓ every silo may import ↓

    PlatformNeutral mechanisms, no product decisions.
    UIFormattersMediaDocs shellStatechartsDesign tokens
    Reference · beside, not below

    im-web today, proposals, the working model. Copied in, never imported.

    Site

    The routes are the only list. Nav, breadcrumbs and tab titles come from them.

    How routing works

    Experiments

    One folder per experiment. Docs at its URL, the running thing under app/.

    The shape of an experiment

    Platform

    Every experiment may import it. It holds mechanisms, never product decisions.

    What’s in the platform

    Reference

    Read by people, copied by code. Improve the working model there, then copy again.

    Copy, don’t import

    Before every commit
    1. Formatting
    2. Lint with the type checker
    3. No cross-imports (Fallow)
    4. No new unused code

    From docs/routing.md and AGENTS.md. The experiments are the folders in the repository today.

    An explorer instead of an essay: a list of experiments down the side, a network and an import matrix in the middle. Pick one and everything else fades; three boxes say what it may use, what it copied and what is refused.

    Who may use whom

    Pick an experiment.

    The repository as a network

    importscopied coderefused

    Rows import from columns

    Architecture told as one request, drawn on blueprint paper with a title block: a sequence diagram of how a receipt becomes a PDF, numbered steps with the files involved, and the bug that shaped it crossed out in red.

    How a receipt becomes a PDF

    Six hops, one rule: Chrome reads the page from this machine.

    Feature
    receipt
    Decisions
    R4, R5
    Sheet
    1 of 1
    1. You open the PDF link. Maybe through a tunnel, when the prototype is shared.
      featuresreceiptapp$orderId.pdf.ts
    2. The server finds the sample order. No order, no PDF: “Sample not found”.
    3. Headless Chrome opens the receipt page on localhost. Never the address you came in on. R5
      -libpdf.server.ts
    4. The page is the on-screen receipt. Print styles turn it into A4. R4
      -libreceipt.tsx
    5. Chrome prints it. Page numbers go in the footer of every page.
    6. You get the file. It opens in the browser as NTB-receipt-<order>.pdf.
    7. Before R5, Chrome went through the tunnel. It got ngrok’s warning page instead of the receipt.
    One Chrome stays running. It is started once and reused; each PDF gets a fresh page.

    11Annotated document

    One real artefact, its parts lettered, every letter tied to the rule behind it. Here: what’s on a receipt.

    The V69 drawing blown up to fill the first screen: the sheet in the middle, every part lettered and named on both sides. A lettered key with links follows. On a phone the letters sit on the sheet and the key becomes the page.

    Features / Receipt / What’s on a receipt

    What’s on a receipt

    Eleven parts, each there because of a decision. Click a letter to read why.

    The parts, A to K

    Not on the paper, but true of it

    What you see is what prints. Screen, print and PDF are one component. R4
    The PDF is made on this machine. So it also works through a tunnel. R5
    Its own sample orders. The receipt works without any prototype. R6

    Layout and rules from the receipt feature. Buyer from its sample data. Picture titles, IDs, credits, order number, reference and PO number are made up.

    The receipt stays pinned while short steps scroll past; each step dims the sheet and lights up one lettered part. Reads like a guided walk from the top of the paper to the bottom.

    Receipt · A walk down the page

    What’s on a receipt, from top to bottom

    Scroll. The sheet stays put and the part you’re reading lights up.

    A dark desk, the receipt on it, pulsing letters to tap. One explanation at a time in a side card, next and previous to walk through, dots to show what you’ve seen. “Show all names” labels every part at once.

    Tap a letter on the receipt

    Eleven parts. Each one is there for a reason.

    Want the whole list instead? Read the receipt decisions or open a sample receipt. Picture titles, IDs and order number are made up.

    The receipt as real, selectable text, read like a proof on the desk: lettered labels in the margin, and highlighter in four colours showing which decision governs each phrase. Press a colour to isolate it.

    What’s on a receipt, line by line

    The colour says which rule a line follows. The margin says what the part is.

    Highlight
    ALetterheadLike NTB’s letterR1

    13 October 2026

    Oslo

    BSellerFrom the brand guideR2

    NTB AS · Skippergata 24 (Pressens hus), 0154 Oslo · Boks 6817 St. Olavs plass, N-0130 Oslo · ntb.no · kundeservice@ntb.no · Org. no. 000 000 000 MVA

    CBuyerAs they were when they paidR3

    Aftenposten AS

    Org. no. NO 912 345 678 MVA

    Akersgata 55, 0180 Oslo

    Attn. Ola Nordmann

    DOrder factsAlways “Paid”R1D20

    Receipt

    Image licenses from NTB Bilder og video

    Order number2026-1013-04
    Order date13 Oct 2026
    StatusPaid
    Ordered byOla Nordmann
    Your referenceWinter sports
    PO number4500-1187
    EImagesOne row each, copiedR3D21
    ImageLicenseAmount incl. VAT
    HVATSame for every buyerR7D3
    Subtotal excl. VAT5 000 kr
    VAT (25 %)1 250 kr
    Total incl. VAT6 250 kr
    All amounts in NOK.
    ILicense termsOnce per licenseR1

    License terms

    Editorial use · NTB Editorial

    One time editorial use in one publication.

    ◆ For editorial use only. Not permitted in advertising or commercial contexts.

    Web and social media · NTB Editorial

    Editorial use online and on social media for 12 months.

    JInstructionsOnly when there are anyR1D17

    Supplier instructions

    ◆ ntb-9d4x6 EDITORIAL USE ONLY. No use in betting or games.

    KFooterPage numbers in the PDFR1R4

    The images are licensed under NTB’s license agreement for the use stated per image. Publish the credit line with each image. Questions: kundeservice@ntb.no.

    NTB ASPage 1 of 1

    F and G sit in each row. License with its product, and the amount incl. VAT in whole kroner. R7 D11
    No colour, no rule. Unmarked text is wording nobody has decided on yet.
    Same page as the PDF. This text is the receipt component itself. R4

    12Status and changelog

    What you can try today, what isn't there yet, and what changed. The page people check before a meeting.

    The page is a kanban board and nothing else: three columns, one card per fact from status.md, and chips that dim what isn't for you.

    Baseline: where it stands

    Updated 8 October 2026 · from status.md · open the prototype

    You can try it 5

    The public site, end to endSearch, image page, mini cart, cart, checkout, confirmation, receipt PDF.
    Open searchD9, D10
    Every purchase panel caseNo plan, pack, subscription, both, not covered.
    Side by sideComponents
    Checkout after Ferdinand's answersPrices with VAT for everyone, one terms box, invoice details.
    LIP-1440D5, D15, D20
    Five customers to view asSwitch in the flask menu, Alt Shift P.
    The admin from the 30 September testPrices on the public site come from it.

    Not there yet 5

    Logged-out visitorsWhat they should see isn't decided.
    Panel "Contact us"Still opens a message form. Checkout already has the new dialog.
    D30
    Order history and plan pagesNot built.
    Approval stepsFor editorial use and some suppliers.
    A designed front pageThe current one is a placeholder.

    Next 5

    Last assumptions to FerdinandSupplier instructions, terms links, ticked boxes on workspace switch.
    @Ferdinand (UX)
    Undo, long orders, legal readUndo after removing an image; collapse long orders; legal check of the text.
    Buy from the image pageSkip the cart for one image.
    Panels against FigmaFix spacing and copy frame by frame.
    Decide the logged-out view

    Older states: changelog · all decisions

    A serif logbook: a strip of days as the visual summary (bar height = changes that day), then one dated entry per change, newest first, typed New, Changed or Fixed.

    Baseline · What changed

    Six days, seven changes

    Checkout now follows Ferdinand's answers. Everything else this week was the admin, the docs and how experiments are kept apart.

    12 OctMon

    Baseline owns its copy of the receipt

    The receipt code was copied in, not imported, so Baseline can change it freely.

    RuleSilosdocs/routing.md
    9 OctFri

    The prototype moved to /app

    Docs live at /prototypes/baseline; the running prototype at /prototypes/baseline/app.

    ChangedLinks
    8 OctThu

    Checkout revised with Ferdinand's answers

    Every buyer sees prices including VAT. One box accepts the license terms.

    ChangedD5D15LIP-1440
    8 OctThu

    The admin mirrors the tested one

    Public prices now come from the admin, as tested on 30 September.

    NewD33
    8 OctThu

    Admin menu and sidebar

    The top menu opens under its own button and the sidebar collapses, like the tested admin.

    NewAdmin
    8 OctThu

    Admin menu stopped sliding sideways

    The page no longer shifts when a menu panel opens.

    FixedAdmin
    8 OctThu

    Receipt PDFs work through a tunnel

    A shared link now gets the receipt, not the tunnel's warning page.

    FixedR5

    Earlier: 7 October and before →

    A dark dashboard of tiles: four big numbers, a waffle of decisions, bullet bars for how far each area has come, and a screen inventory with status dots. No prose at all.

    Baseline · status

    8 Oct 2026 · details · changelog

    Decisions

    36

    All decided. Read them

    Screens to try

    7

    Search to receipt. Open

    Not there yet

    5

    Front page, history, plans…

    Customers to view as

    5

    Flask menu, who

    36 decisions, by area

    Checkout 14Prices and words 10Pages and layout 6Admin as tested 6

    How far each area has come

    Bar: share built. Tick: what the user test needs. Bands: rough, usable, done.

    Screens

    • SearchD25
    • Image page and panelD26
    • Mini cart and cartD10
    • CheckoutLIP-1440
    • ConfirmationD10
    • Receipt PDFR1
    • Admin, as testedD33
    • Front pageplaceholder
    • Logged-out viewLIP-1546
    • Order historynot built
    • Plan pagesnot built
    • Approval stepsnot built
    Try itStand-inUndecidedMissing

    Next

    1. Ferdinand confirms the last assumptions
    2. Undo after removing an image
    3. Buy straight from an image's page
    4. Panels checked against Figma
    5. Decide the logged-out view, LIP-1546

    13Glossary

    The words this repository uses, in one place, so a newcomer can read any other page.

    First screen: every word placed where it lives in the repository, as clickable chips on a silo diagram. Then a classic dictionary with an A–Z rail down the side.

    Docs · Glossary

    The words of this repository

    Fifteen words explain most pages. Click one on the map to jump to it.

    Where each word lives

    _ - /FOLDER NAMES
    _docsfolder

    The docs pages of an experiment. The underscore keeps it out of the URL.

    Example: baseline/_docs/decisions.tsx is the page /prototypes/baseline/decisions.

    -libfolder

    An experiment's code: components, rules, decisions. The dash hides it from the router.

    -docsfolder

    Markdown for people, like the status page.

    See also _docs.

    app/folder, URL

    The running prototype or feature. Reserved for nothing else.

    Example: /prototypes/baseline/app

    D
    Decisionrule

    Where sources disagree, the one answer an experiment uses. Numbered: D5 in Baseline, R7 in the receipt.

    See Baseline's decisions.

    E
    Experimentidea

    A prototype or a feature, tested with users before it reaches im-web.

    Kinds: prototype, feature.

    F
    Fallowtool

    Refuses a commit that imports across silos. It also finds unused code.

    Featureexperiment

    One part, built to work on its own. The receipt is a feature.

    P
    Platformfolder

    Neutral building blocks every experiment may import: UI, formatters, the docs shell.

    src/platform/

    Prototypeexperiment

    A whole site to click through. Baseline is one.

    R
    Referencefolder

    im-web as it is today, plus proposals. Read it, copy from it, never import it.

    S
    Silorule

    Each experiment is sealed off. It imports only itself and the platform.

    staticDatacode

    Every page's title and description. Tabs, breadcrumbs and the nav are built from it.

    Copy, don't importrule

    Reuse means a copy in -lib/from-<source>/, with the source commit noted.

    W
    Working modelrules

    The business rules experiments start from. Baseline keeps its own copy.

    A deck to learn the words: each card shows a tiny picture of the idea; tap to flip to the definition. Built for a newcomer's first hour, not for looking things up.

    Learn the words in ten cards

    Guess first, then tap to flip.

    Full list: the glossary · Where they come from: How routing works

    14Troubleshooting

    Something went wrong. Start from what you see, end with what to do.

    The page opens on the exact message you got, in a terminal, with tabs for the four ways a commit is refused. Below: what it means, how to fix it, how to check, in three columns.

    
        

    For people testing the prototype, not coding it. A fishbone of the four usual causes leads into an accordion of symptoms, each opening to cause and fix.

    The prototype doesn't do what you expect

    It's usually one of four things. Find your symptom on a bone, or in the list.

    There's no box to waive the right of withdrawalViewing as
    Cause

    Only private buyers see it. You are in a company workspace.

    Fix

    Switch to Kari in the flask menu: Alt Shift P. D15

    The purchase panel shows no planViewing as
    Cause

    Aftenposten has no plan. It's the "no plan" case on purpose.

    Fix

    View as Bergens Tidende (quota) or Stavanger Aftenblad (subscription). D38

    Pay now shows red text instead of payingRule
    Cause

    A box is unticked. The button always works and points at what's missing.

    Fix

    Tick the license terms. Private buyers also tick the waiver. D8

    Prices differ from the Figma framesRule
    Cause

    Everyone sees prices including VAT, rounded to whole kroner. Some frames show prices without.

    Fix

    Nothing to fix: the prototype is right. D5 · D11

    The receipt PDF shows a warning pageSharing
    Cause

    An old copy, shared through a tunnel. This was fixed on 8 October.

    Fix

    Ask whoever shared the link to update and restart. R5

    Checkout looks broken on a phoneNot built
    Cause

    Checkout isn't made for phones in this round.

    Fix

    Test on a laptop. D31

    The front page is nearly emptyNot built
    Cause

    It isn't designed yet.

    Fix

    Start from search instead. Status

    Still stuck? Ask in #im-web-prototypes with a screenshot and the customer you viewed as.

    15Comparison

    Two cases of the same thing, side by side: what's shared, what differs, and the rule behind each difference.

    A Venn diagram is the whole story at a glance; a rule-by-rule table under it gives the proof, with the differing rows tinted. On a phone the Venn becomes three stacked boxes and the table becomes cards.

    Baseline · Checkout

    Company buyer or private person

    Most of checkout is the same for both. Three things differ. The workspace decides which one you are.

    Company only
    • Company, org. no., address
    • "Ordered by": name and email
    • Optional invoice reference
    Both
    • Prices incl. VAT, whole kroner
    • VAT on its own line
    • One box for license terms
    • Buyer comes from the workspace
    • Pay now shows the total
    Private only
    • Own name, address, email
    • Waive the right of withdrawal

    Rule by rule

    Rule Company Private Source
    Prices include VAT ✓ ✓ D5
    Totals: subtotal, VAT (25 %), total ✓ ✓ D3
    Buyer type from the workspace, not chosen ✓ ✓ D13
    One box accepts the license terms ✓ ✓ D15
    Waive the right of withdrawal – ✓ D15
    "Ordered by" line with name and email ✓ – D19
    Invoice reference or PO number, optional ✓ – D20

    ✓ applies · – does not · tinted rows differ. Try both: view as Aftenposten or view as Kari.

    A poster-like face-off: the two checkouts as real mock-ups, left and right of a big VS, with numbered yellow marks on what differs and a switch that fades everything that's the same.

    Baseline checkout · same cart, two buyers

    Company vs private

    Same images, same prices, same total. Only the yellow parts differ.

    Company viewing as Aftenposten AS

    1

    Buying as

    Aftenposten AS

    Org. no. 912 345 678

    Akersgata 55, 0180 Oslo

    Ordered by Ingrid Haugen, ingrid@aftenposten.no

    Images (3)

    Ski jumper · Northern lights · Sailing boat

    Subtotal excl. VAT3 611 kr
    VAT (25 %)903 kr
    Total incl. VAT4 514 kr
    2

    Additional details for invoice

    Your reference (optional)
    PO / order number (optional)
    I accept the license terms for each image
    3

    Withdrawal

    Not shown to companies

    Pay now · 4 514 kr
    VS

    Private viewing as Kari

    1

    Buying as

    Kari Nordmann

    Storgata 1, 0155 Oslo

    kari@example.no

    Images (3)

    Ski jumper · Northern lights · Sailing boat

    Subtotal excl. VAT3 611 kr
    VAT (25 %)903 kr
    Total incl. VAT4 514 kr
    2

    Invoice details

    Not shown to private buyers

    I accept the license terms for each image
    3

    Withdrawal

    I waive my right of withdrawal once the download starts
    Pay now · 4 514 kr
    1Who is buying. Companies show who ordered; private buyers show their own details. D19
    2Invoice reference. Companies may add their own, folded away until needed. D20
    3The waiver. Only private persons waive withdrawal. D15
    Nobody picks. The active workspace decides which checkout you get. D13

    Before 8 October, companies saw prices without VAT. Now both see 4 514 kr incl. VAT (D5).