Studies

Kora

A bakery site the owner edits themselves — words, prices, hours and photo in two languages, with a draft, a publish button and every version kept.

The Kora bakery site in edit mode: dashed outlines around each section, and a panel beside it holding the menu’s names and prices in English and Serbian.

The brief

The Services page offers "a CMS if you want to self-edit", and until this project nothing in the portfolio showed one. It is also the question that ends more small-business conversations than price: if the site is hand-built, does every changed opening time mean ringing the person who built it?

So this is a bakery that edits its own website. Kora is a fictional Serbian bakery in north London, and its customers read English and Serbian. The owner changes the words, the prices, the hours and the photo — in both languages — and nothing reaches a visitor until they press Publish.

The constraints

  • The owner is not a web designer, and shouldn't have to become one. They will type a heading three times too long and paste a price with a comma.
  • A half-finished change must never go live by accident, and a mistake that did go live must be undoable without help.
  • Two languages, one owner. They will not always have time to translate everything before the Friday special needs to go up.
  • Photos come straight off a phone, at whatever size the phone felt like.

The decisions

The owner edits content, never layout

In edit mode every editable part of the page gets a dashed outline and a button that says what it edits. The button opens a panel of ordinary form fields: the heading, the introduction, each menu item's name and price, each day's hours. There is no way to move a section, change a colour or resize anything, so there is no way to break the design.

Each field carries the length the design was built for — 48 characters for the heading, 32 for a menu item's name — with a counter that fills as the owner types, and the field stops accepting characters at the limit.

What it costs: flexibility the owner might occasionally want. A new section is still a conversation with the studio. That is the trade that keeps the site looking the way it was designed six months later.

Everything lands in a draft first

Changes save as the owner types and the page previews them straight away, but only in the editor. Leaving the editor shows what visitors see, which is still the published version. A counter on the owner's bar says how many changes are waiting.

Publishing opens a list of every change in plain words — Burek with cheese: £4.20 → £4.80, Monday hours changed, Photo replaced — so the last look before something goes live is a read-through, not a guess.

What it costs: one extra step between typing and seeing it live. It is the step that stops a price being published half-typed.

Errors stop publishing. Missing translations don't.

An empty English heading, a menu item without a price, a closing time before the opening time, or a new photo with no description: each blocks the Publish button, and each is listed as a link that opens the field that needs fixing. A missing Serbian line is only a warning. The Friday special can go up in English at eight in the morning and gain its Serbian name at lunch.

A Serbian visitor looking at an untranslated item sees the English — marked in the markup as English, so a screen reader pronounces it as English instead of reading English words with Serbian rules.

What it costs: a Serbian page that is sometimes partly in English. Refusing to publish until every line was translated would have been tidier and would have left the Friday special unpublished.

Every published version is kept

Each publish is saved with what it changed. Any earlier version — including the original site — can be brought back, and it comes back as a draft, not straight onto the live site, so the owner can check it and publish it deliberately.

What it costs: the last twelve versions of the content kept in storage. A mistake that reached the live site stops being a phone call to the developer.

A photo is shrunk before it is stored

Phones take photos far larger than a web page needs — exactly the weight the Halden before shows costing a page its visitors. The editor redraws a chosen photo at no more than 1,600 pixels on its longest side and saves that as a JPEG. In testing, a 4,000 × 3,000 image of 7.1 MB was stored at 1,600 × 1,200. The owner is told both sizes.

A new photo also arrives with an empty description. The old description was of a different picture, and a wrong description is worse than none, so the photo cannot be published until it is described.

What it costs: an owner cannot put a full-resolution image on the site even if they want to. None of them has ever wanted a slower website.

Small things owners actually type

Prices can be typed as 4.80, £4.80 or 4,80 — the comma is how most of Europe writes a decimal, including the owner's family back home — and a nonsense price is flagged when the owner leaves the field rather than while they are still typing it. The "open now" line works from the hours the owner sets, in London time, and in Serbian it says otvaramo u sredu, with the day in the right grammatical case rather than dropped into an English sentence pattern.

What it costs: a little more code than a number field. It is where an owner decides whether the software was made for them.

Photos live somewhere other than the words

Every demo on this site shares one web origin, and so one browser storage quota. Words, prices and hours are small and go in local storage; photos go in IndexedDB. A single large photo in local storage could have exhausted the space Marlow's bookings rely on.

What it costs: a second storage layer to read from when the page draws. A real build moves both to the site's own storage, which is also what lets the owner's phone and laptop see the same draft.

Built with

  • Vanilla HTML, CSS & JS
  • No build step
  • <dialog>
  • IndexedDB
  • Canvas image resizing
  • Intl.DateTimeFormat
  • Cloudflare Pages

Everything is kept in the visitor's own browser — there is no login and no server, and the bar at the bottom of the page is labelled as a demo. In a real build that bar sits behind the owner's sign-in. The whole flow above was checked in a real browser before it shipped: 45 checks, from the draft staying invisible to visitors through to the phone layout.